The problem
The client ships a consumer fitness app. The plan feature offered a four-week program from a template: goal, days per week, equipment. Members started it. Most were gone by week two. Support tickets said the plan ignored what the person had actually done the week before, including sessions they had skipped or cut short.
The founders wanted the next session to reflect the log. They also had a bright line from their counsel: the app is not a clinician. It must not diagnose, prescribe, or tell a member to train through pain. A generic model with a fitness prompt crossed that line often enough that they would not ship it.
Why the log is the product
A useful next session, for this app, is one the member can recognize as theirs. That means the suggestion names the sessions already logged, the gap the member hit, and a change that stays inside the plan they already accepted. A eloquent plan that could have been written for anyone was the thing members were already ignoring.
Architecture
The log is the only member data
The coach reads the member's logged sessions, the plan they selected, and the equipment they marked as available. It does not read health records, and it does not ask for injuries in free text. A free-text pain note is routed to a static screen that tells the member to stop and talk to a professional, which is a product decision, not a model completion.
Every suggestion points at a logged session
The draft has to name the session it is adjusting. If it cannot, it is discarded. That check runs in code on the structured output, so a fluent paragraph with no session id never reaches the member.
A refusal list written with counsel
We encoded the phrases and intents the app must not produce: diagnosis, supplement instruction, training through reported pain, and comparisons that shame a missed week. Those outputs are replaced with the refusal screen. We tested the list against a set of adversarial prompts, not only against happy-path logs.
On device where the log already is
Session history is on the phone. The coach runs there for the common adjustment, so a missed workout does not require uploading the log to assemble a generic cloud plan. Heavier copy review stays server-side on text only, never on a video of the member.
Challenges and tradeoffs
- Templates kept leaking into the prompt. Early drafts still recommended the default four-day split when the log showed two days. We moved the plan constraints into the structured input and rejected outputs that named a session type the member does not have equipment for.
- Missed weeks were being framed as failure. Copy that said the member had fallen behind tested well with the team and poorly with members. The revision treats a missed week as a scheduling fact and proposes a shorter session, which is what the log supports.
- Store review asked where health data went. We documented that the coach does not read Health-app data and does not upload video. That statement had to be true in the build, not only on the questionnaire, so we removed a planned cloud upload of session notes.
Results
Among members who started a four-week plan after the coach shipped, 34% more reached the end of week four than in the prior template cohort, measured the same way the client already measured completion. Every suggestion in the reviewed sample cited a logged session. Reviewers found no medical instruction in the released output set.
The app still does not know if a member is injured. It knows what they logged, and it declines the questions a coach in this product is not allowed to answer.
What we'd do differently
We would have put the refusal set in front of counsel before the first prompt, not after the first internal demo. The demo produced two answers counsel rejected outright, and we rebuilt the output schema around the refusal rather than trying to soften those answers.