SpekoLLM is a llm.LLM implementation. It flattens a LiveKit ChatContext into Speko’s messages format and calls the proxy. The router picks the best LLM provider per intent and fails over automatically.
SpekoLLM doesn’t need a StreamAdapter — LiveKit’s voice.AgentSession is happy with a non-streaming LLM that emits a single chunk.
Constructor
SpekoLLMOptions
| Field | Type | Required | Description |
|---|---|---|---|
speko | Speko | ✅ | @spekoai/sdk client. |
intent | Intent | ✅ | Validated at construction time. |
temperature | number? | Forwarded to /v1/complete. | |
maxTokens | number? | Forwarded to /v1/complete. | |
constraints | PipelineConstraints? | Allow-list constraints. |
Properties
label() → 'speko.LLM'provider = 'speko'model = 'speko-router'
.chat(params)
Standard LiveKit LLM entry point. Returns an LLMStream that emits exactly one ChatChunk carrying the full assistant response, then closes.
Signature (from @livekit/agents):
Context conversion — chatContextToSpeko
Exported for when you want to reuse the flattening logic (e.g. unit tests, custom pipelines).
- Only
llm.ChatMessageitems are considered. Function-call and handoff items are skipped. - Roles are normalised:
developer→system;system/user/assistantpass through; anything else is dropped. - Empty
textContentmessages are skipped. - Ordering is preserved.
.chat() rejects with SpekoAdapterError('INVALID_CONTEXT').
v1 — no tool calls
/v1/complete doesn’t expose tool invocation yet. If a non-empty toolCtx is passed, the adapter warns once (deduped per instance) and proceeds as if no tools were set:
Errors
SpekoAdapterError(exported): thrown for adapter-internal problems.codeis one of:'INVALID_CONTEXT'—ChatContextproduced no convertible messages.
speko.complete() surface unchanged — SpekoApiError, SpekoAuthError, SpekoRateLimitError from @spekoai/sdk.