An Agent is a persisted persona record on Speko. It bundles the values you’d otherwise have to repeat on every session create:Documentation Index
Fetch the complete documentation index at: https://docs.speko.dev/llms.txt
Use this file to discover all available pages before exploring further.
systemPrompt— the agent’s instructionsvoice— TTS voice id (provider-specific)intent—languageand optionaloptimizeFor(latency/quality/cost)llmOptions— optionaltemperature,maxTokens,modelstackPreferences— optional per-layer allowlists (which STT / LLM / TTS providers the router is allowed to pick)
agent_a1b2c3d4e5f60718) when starting a voice session. Per-call body fields still override the agent’s stored defaults — agents are sensible defaults, not a wall.
When to use an agent
Use one when the same persona is starting more than one session — that is, almost always in production. Without an agent, everyPOST /v1/sessions ships the full config inline; with an agent, you ship just { agentId }.
Stack preferences
Speko’s default behavior is auto-routing — for each session, the highest-scoring provider per pipeline layer (STT, LLM, TTS) is picked from every benchmarked option. Stack preferences narrow that pool per agent, so you can express opinions like “this agent’s STT must be Deepgram or AssemblyAI” or “LLM must be OpenAI or Anthropic” without giving up auto-routing or failover within the allowed set.Vendor vs model entries
Each entry in anallowedProviders list is either a vendor id (allow any model from that vendor) or "<vendor>:<model>" (allow only that specific model). Both forms can be mixed in the same array. Failover stays active across all entries in the layer.
eleven_flash_v2_5 and nothing else.
["deepgram:nova-3", "deepgram:nova-2"] is also valid — that pins to two specific Deepgram models, with no fallback to other Deepgram models within the vendor (failover to other allowed vendors still applies). Use GET /v1/providers/known to enumerate every (vendor, model) pair the router knows about — the id field on each entry is the verbatim string to put here.
Rules of thumb:
- Empty / missing layer = no constraint. A
sttallowlist of[](or absent entirely) means the router has full freedom for STT. - Failover stays active within the allowed set. If you allowlist Deepgram + AssemblyAI for STT, and Deepgram errors mid-call, the router will fail over to AssemblyAI rather than to a non-allowed provider. The same holds across model-level entries —
["deepgram:nova-3", "assemblyai"]will fail over from Nova-3 to AssemblyAI. - Per-call overrides win per layer. When you start a session with both an
agentIdand an inlineconstraints.allowedProviders.stt, the per-callsttlist replaces the agent’ssttlist — but the agent’sllmandttslists still apply unless those are also overridden. - Empty allowlist with no fallback fails to route. If you allowlist a provider that has no benchmark data, the router can’t rank it; the session will error rather than silently picking an alternative.
stackPreferences in POST /v1/agents / PATCH /v1/agents/{id}.
Session history
Every session started withagentId (whether via POST /v1/sessions directly or via the SDK’s VoiceConversation.create({ agentId })) is linked to that agent at create time. The dashboard surfaces them under the Sessions tab on the agent’s detail page; the API equivalent is GET /v1/sessions?agent=<id>, which scopes the standard sessions list down to that agent’s calls and combines with the existing cursor, status, kind, and limit filters.
The link is read-only — sessions are not retroactively attached to an agent, only at create time.
Tools live under agents
Every tool you register is scoped to a specific agent — the unique key is(organization, agentId, toolName). This means:
- Different agents in the same org can register tools with the same name (
lookup_user,book_appointment) without colliding. - Adding a tool to one agent doesn’t expose it to your other agents.
- The voice worker fetches
GET /v1/agents/{agentId}/toolsat session start to assemble the tool list.
/v1/agents/{id}/tools API.
Lifecycle
| Operation | Endpoint | Notes |
|---|---|---|
| Create | POST /v1/agents | Returns the new id. Names are unique per organization. |
| List | GET /v1/agents | Returns every agent in the calling key’s organization. |
| Read | GET /v1/agents/{id} | 404 if not found / not in your org. |
| Update | PATCH /v1/agents/{id} | Partial — send only the fields you want to change. |
| Delete | DELETE /v1/agents/{id} | Cascades to tools. The Default agent cannot be deleted. |
The Default agent
When your organization is created, Speko seeds a single agent named Default so you have something to point at on day one. It’s a regular agent in every other respect — edit its system prompt, voice, and intent freely. It’s only special in two ways: it can’t be renamed, and it can’t be deleted.
Where to next
Browser SDK
VoiceConversation.create({ agentId }) — browser-side WebRTC against your agent.Dashboard
Manage agents and their tools from the web dashboard.
API reference
Full request/response shapes for the
/v1/agents endpoints.