> ## Documentation Index
> Fetch the complete documentation index at: https://haico.gr/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# API-only clients

> What the server does for you regardless of client, and the two places where a script must do what the browser does.

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:

| Concern                 | Where it happens                                                                                                                                                                                                       |
| ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Turn indexing**       | `increment_turn` runs server-side before the agent, and the assigned `turn_index` comes back on `conversation_info`. You never track it yourself.                                                                      |
| **Workspace snapshots** | Written during the turn, keyed by `(thread_id, turn_index)`. This is what makes branching and history work.                                                                                                            |
| **Artifacts**           | Persisted by the tool layer as the agent produces them, already tagged with the right turn.                                                                                                                            |
| **Trajectory graph**    | `GET /api/conversations/{id}/graph` is computed from persisted data. The web UI only does visual layout on top of it.                                                                                                  |
| **Branching**           | `POST /api/conversations/{id}/branch` reconstructs the workspace from the snapshot. The `workspace` field is an optional override the UI uses to carry unsaved edits; **omit it and the server does the right thing.** |

Two differences are worth knowing before you rely on the API alone.

<Warning>
  **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](/docs/adr/0005-user-feedback-frame)). 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.
</Warning>

<Note>
  **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.
</Note>

<Note>
  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](/docs/api-guide/streaming-turns#choosing-a-model)
  if you want to override it.
</Note>
