> ## Documentation Index
> Fetch the complete documentation index at: https://dev.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.md)). 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.

> [!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]
>
> 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.md#choosing-a-model)
> if you want to override it.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.