# Agents API

An agent bundles a system prompt with a provider/model choice for each of STT, LLM, and TTS. All endpoints require an [API key or dashboard token](/docs/authentication) and are scoped to the caller's account — you only ever see/modify your own agents.

## Create an agent

```
POST /agents
```

Body:

```json
{
  "name": "Support bot",
  "system_prompt": "You are a helpful support agent for Acme...",
  "llm_provider": "llmgateway",
  "llm_model": "gpt-oss-120b",
  "stt_provider": "groq",
  "stt_model": "whisper-large-v3-turbo",
  "tts_provider": "groq",
  "tts_voice": "autumn",
  "temperature": 0.7,
  "interruption_enabled": true,
  "interruption_sensitivity": 0.5,
  "endpointing_sensitivity": 0.5,
  "language_lock": null,
  "model_tier": "balanced",
  "latency_profile": "balanced"
}
```

All fields except `name`, `system_prompt`, and `tts_voice` have defaults (`llm_provider: "llmgateway"`, `stt_provider: "groq"` / `stt_model: "whisper-large-v3-turbo"`, `tts_provider: "groq"`, `temperature: 0.7`, plus the realtime knobs below) — `llm_model` and `tts_voice` are always required since they're provider-specific.

Returns `201` with the full agent object (adds `id`, `created_at`, `updated_at`).

## List agents

```
GET /agents
```

Returns an array of your agents, newest first.

## Get an agent

```
GET /agents/{agent_id}
```

`404` if the agent doesn't exist or belongs to a different account.

## Update an agent

```
PATCH /agents/{agent_id}
```

Body: any subset of the `POST /agents` fields (including the realtime knobs below) — only fields you include are changed.

## Realtime pipeline knobs

Every knob has a sane default, a documented range, and is validated on create/update (`422` for an out-of-range or unknown value). Existing agents keep their prior behaviour — each column has a server default.

| field | type | default | range / values | effect |
|---|---|---|---|---|
| `interruption_enabled` | boolean | `true` | — | whether the caller talking over the agent cuts it off (barge-in) |
| `interruption_sensitivity` | number | `0.5` | `0.0`–`1.0` | higher = a fainter/shorter caller utterance interrupts |
| `endpointing_sensitivity` | number | `0.5` | `0.0`–`1.0` | higher = a shorter pause counts as the caller's turn ending |
| `language_lock` | string / null | `null` | `"en"`, `"fr"`, or `null` | locks batch STT to that language and adds a "always speak X" instruction for realtime; `null` = auto-detect |
| `model_tier` | string | `"balanced"` | `"fast"`, `"balanced"`, `"quality"` | for realtime calls, takes effect only when set to a non-`balanced` value (otherwise the agent's explicit `llm_model` wins). The [batch LLM API](/docs/batch-llm-api) accepts the same tier names directly, independent of any agent |
| `latency_profile` | string | `"balanced"` | `"low"`, `"balanced"`, `"quality"` | advisory; surfaced to the client in the WebSocket `call_config` frame |

On WebSocket connect the server now sends one extra JSON frame with these values — see [The talk WebSocket](/docs/talk-websocket#call-config-frame). It's additive: existing clients that ignore unknown frame types are unaffected.

## Delete an agent

```
DELETE /agents/{agent_id}
```

Returns `204`. Deleting an agent does not delete its past calls/messages.

## Providers and models

`llm_provider`/`stt_provider`/`tts_provider` must be one of the values `GET /providers` returns (the dashboard's agent editor reads from the same endpoint, so it always matches what's configurable). As of writing:

| Component | Providers |
|---|---|
| LLM | `llmgateway` (routes to whatever chat model you pick — GPT, Claude, Gemini, Mistral, and others, by model id) |
| STT | `groq`, `voxtral`, `elevenlabs`, `deepgram` — `voxtral`, `elevenlabs`, and `deepgram` also support speaker diarization in the [batch STT API](/docs/batch-stt-api) |
| TTS | `groq`, `inworld`, `edge`, `elevenlabs`, `deepgram`, `voxtral` |

Sending an unknown provider on create/update returns `400`. Fetch `GET /providers` for the live, current model/voice catalog per provider rather than hardcoding it — LLM models in particular are fetched live from the LLM gateway and change over time.
