Andrew Byrd
Brief Resume Email me
Back to products

Soma, for people and their agents

I built Soma to bring workout planning, logging, and training readiness into one app. Then I gave coding agents a way to work with the same training data, and built a model-powered workout builder inside the product.

Open Soma
My roleProduct design and full-stack development
Built withNext.js, TypeScript, Prisma, PostgreSQL
Agent and AI workMCP, OAuth, structured model output

Planning should lead into doing

Knowing what I did last time is only part of planning the next workout. I also want to account for my equipment, recent performance, and which muscle groups have recovered.

Soma brings those pieces together in a mobile-first tracker. A plan holds the prescription; a workout records what actually happened. Keeping them separate means a suggested set never becomes invented training history.

I built the experience, the underlying services and data model, and the deployment. Actual use keeps turning up the next useful improvement.

From a conversation to a workout plan

This is an existing workflow: Codex and Claude use Soma's MCP tools to read training data and create plans.

  1. 1Read the product data

    The agent retrieves readiness, recent performance, and exercise records through MCP.

  2. 2Build the session

    It uses that context and the user's request to choose a workout and create a plan.

  3. 3Continue in the app

    The plan appears in Soma. The user starts the session and logs what they actually do.

A small, deliberate tool boundary

The OAuth-protected server binds access to a user. Read tools and plan mutations have separate scopes. Agents can create or revise plans; they cannot log sets, complete workouts, or rewrite history. The MCP server and dashboard share the same training-readiness model.

A proposal first, a plan after review

Limited training context goes to the model, which returns a structured proposal. Application checks run, the user reviews it, and only explicit acceptance creates a plan. A stale proposal is sent back to be rebuilt. Training context limited Model no tools, no database Proposal structured output App checks exercises, loads, equipment, duration You review and accept then it becomes a plan context changed? rebuild the proposal

The in-app AI builder is a separate integration from MCP. It receives a limited training context and produces a structured workout proposal. The model has no database or tool access.

Application code checks the result against eligible exercises, load choices, equipment, and the session's duration budget. The user can review and refine the proposal; only explicit acceptance turns it into a plan.

Acceptance also checks whether the relevant training context changed. If a proposal has become stale, the app requires rebuilding it instead of silently saving an outdated prescription.

The API worked. The handoff didn't.

Codex created a workout plan through MCP while Soma was already open. The write succeeded, but the dashboard still showed its old state. I had to close and reopen the app to see the plan.

I added dashboard refresh when the app resumes. That bug made the product boundary clear: creating the right record is only useful if the person can find it when they return.

Observe the workflow without collecting its content

I instrumented product and MCP activity with PostHog. Server-side events use an outbox written in the same transaction as the change. Privacy checks keep prompts, generated prose, and credentials out of analytics.

The work spans the interface, service contract, model behavior, and operation of a deployed product. Each part has to make the next one usable.