← Selected work

Case study / 02 / AI systems

Keeping AI training plans grounded in a controlled movement catalog.

A planning system that combines semantic retrieval, structured agent workflows, and product-level guardrails to generate useful training-plan drafts without letting the model invent the underlying content.

Why grounding mattered

A training plan looks simple at the surface, but it has real constraints: the exercises must exist in the product, they must suit the athlete’s goals and available equipment, and the schedule needs to be coherent, progressive, and safe. A language model alone can write something plausible, but plausibility is not a reliable way to choose from a clinical and movement-focused catalog.

I treated the model as a planner operating within product boundaries, not as the source of truth. Before it can construct a draft, it searches the controlled assessment and exercise catalog. Every activity it proposes must reference an ID returned by that search during the current run; if the right item is not found, the system omits it instead of fabricating an exercise or reusing a stale record.

Curv AI conversation collecting an athlete's training focus, schedule, and program lengthCurv AI program view showing the generated workout schedule and exercises
From a guided conversation about goals and constraints to a structured program schedule.

Retrieval over the catalog

Each public catalog item is embedded from its title and instructions using OpenAI’s text-embedding-3-small model. The 1,536-dimensional vectors live alongside the catalog in PostgreSQL through pgvector, with an HNSW index for fast similarity search. At query time, the API embeds the request, filters to public definitions, and ranks candidates by vector distance before returning the most relevant records to the agent.

Query embeddings are cached in Redis using a deterministic key built from the normalized query and embedding configuration. That removes repeated embedding calls for common searches without making the cache a second source of truth. The database remains responsible for which catalog entries are available and how they rank.

From intent to a typed draft

The planning workflow gives the agent a typed search tool and a typed program-creation tool. It asks the agent to plan its queries in batches, reuse results where possible, and stop after a small bounded number of search calls. The search tool runs the requested queries independently, so one failed query can be reported without discarding the rest of the retrieval set.

The agent’s output is constrained to a JSON schema rather than free-form prose. Its instructions define limits on program length, session cadence, rest timing, progression, and daily activity count. The API validates the draft and can return it synchronously or stream it to the client, while preserving a trace ID for diagnosis. The result is a structured schedule linked to application-owned records—not an unbounded block of generated text.

Why this architecture holds up

The system separates responsibilities cleanly. OpenAI provides embeddings and the planning runtime; PostgreSQL and pgvector own retrieval over the controlled catalog; Redis reduces repeated work; and the application owns the rules that make a draft valid. The model can reason about intent and tradeoffs, but it cannot bypass catalog integrity or write an unstructured program directly into the database.

That separation makes the system more dependable and easier to evolve. Retrieval quality can improve without changing the program schema, new guardrails can be added without retraining a model, and a tool failure is an explicit application event rather than an ambiguous piece of generated text. The streaming endpoint also cancels the upstream run when a client disconnects, avoiding work that can no longer be used. It is a practical pattern for turning AI capability into a bounded product workflow.