> ## 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.

# Streaming agent turns

> The Server-Sent Events contract for POST /api/query/stream_steps/sse, and how to choose the model that runs the turn.

The agent endpoint streams Server-Sent Events. Omit `thread_id` (or pass `null`) to start a new
conversation; the first `conversation_info` event carries the assigned `thread_id`, which you reuse
on later turns.

```bash theme={null}
curl -N -X POST https://haico.gr/api/query/stream_steps/sse \
  -H "Authorization: Bearer $HAICO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"query": "chart Q1 vs Q2 revenue: 120, 180", "thread_id": null}'
```

> [!WARNING]
>
> This endpoint consumes LLM credits on every call, and it requires a `read,write` token.

## Reading the stream

The stream emits **only `data:` lines**. There are no SSE `event:` lines, so do not key off
them: the event kind is the `type` field **inside** each JSON payload. Lines beginning with
`:` are keep-alive comments and must be skipped.

```
data: {"type": "conversation_info", "thread_id": "th_3173225a...", "title": "..."}

data: {"type": "step", "thread_id": "...", "step": {...}}

: keep-alive

data: {"type": "complete"}
```

| `type` | Meaning |
| - | - |
| `conversation_info` | The `thread_id` for this conversation. Arrives first. |
| `step` | One reasoning step: a tool call or its result. |
| `artifact` | A chart, table, or other artifact the agent produced. |
| `complete` | Terminates the stream. Carries no payload beyond the type. |
| `error` | The turn failed. Carries an `error` string; the stream then ends. |

Always handle `error`: it is returned with HTTP 200 inside the stream, because the response has
already begun by the time the failure happens. The exact `step` and `artifact` shapes are
documented in [agent-core-logic §7](/docs/agent-core-logic.md).

## Choosing a model

A request that omits `config` runs on the server-side default from `llm:` in the deployment config.
That default is **the same model the web UI sends**, `gemini-2.5-flash`, so an API turn and a
browser turn are comparable out of the box.

To run a different model, pass `config`:

```json theme={null}
{
  "query": "…",
  "thread_id": null,
  "config": {
    "API": "google",
    "model_id": "gemini-2.5-flash",
    "args": {"temperature": 0.7}
  }
}
```

| Field | Meaning |
| - | - |
| `API` | Provider: `openai`, `google`, `anthropic`, `mistral`, `cohere`, or `bedrock`. This is the only name for the field: a `provider` key is refused |
| `model_id` | The vendor's model identifier |
| `endpoint_url` | Optional OpenAI-compatible base URL (OpenAI's own `https://api.openai.com/v1`, DeepSeek, xAI, Together, vLLM, UKP's Ollama, …). It must be an endpoint the server is configured for, and any other URL is refused |
| `args` | Generation settings: `temperature`, `max_tokens`, `top_p`, `top_k`, `stop`, `seed`, `frequency_penalty`, `presence_penalty` or `reasoning_effort`, plus `timeout` (seconds) for the provider call. Any other key is refused |

`max_tokens` is clamped down to the chosen model's own output ceiling, so a generous server-side
default cannot make a request invalid for a smaller model.

A refused `endpoint_url` or `args` key ends the turn with an `error` event that names the problem.

The model picker on the hosted deployments offers OpenAI, Anthropic, Google Gemini, Mistral and models self-hosted at UKP. Cohere, xAI, Together AI, DeepSeek and Alibaba Cloud are grayed out there but stay reachable through the API. A request for a provider whose key the server does not hold also ends the turn with an `error` event.

> [!WARNING]
>
> **Not every model can drive this agent.** Every tool the agent can call carries a required
> `action_and_reasoning` argument, which is what produces the user-visible reasoning trace. Smaller
> models routinely omit it, and because it is required, the tool call fails validation and the agent
> retries the same call until the turn is exhausted. The symptom is a stream full of
> `action_and_reasoning: Field required` errors and no result.
>
> `gpt-4o-mini` fails this way on most tool calls and is not offered in the model picker. If you
> override `config`, prefer a frontier model and verify that a tool-using turn actually completes
> before you rely on it for a batch.


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