The co-construction loop is driven entirely server-side, so an API-only client and a browser
user produce the same state. Specifically, all of the following happen inside the agent turn
with no client involvement:
Two differences are worth knowing before you rely on the API alone.
Feedback vocabulary is not discoverable from the API. The backend deliberately validates
only the shape of a feedback row, so that the research instrument can evolve without a
migration (see ADR-0005). It enforces:
scope ∈ message, objective, plan, artifact, preferences, conversation
sentiment ∈ positive, neutral, negative (null for reports)
aspect as a bounded slug, and category as a bounded string, with no enum
The actual aspects (target_endorsement, plan_delta, artifact_satisfaction,
task_completion, trajectory_assessment, and so on) and their permitted category values
live only in frontend/src/lib/feedback-taxonomy.ts. Treat that file as the authoritative
list, and expect it to change between releases without the API contract changing.
The API does not enforce study-mode feedback gating. In the web UI under study mode, the
send button is blocked until the required feedback for a turn has been given. That rule is
implemented client-side only, so a script can advance turns without submitting any feedback.
If you are collecting study data over the API, enforce the requirement in your own client.
The default model is not a difference: a request that omits config runs the same
gemini-2.5-flash the web UI sends. See choosing a model
if you want to override it.