Models & providers
STT/LLM/TTS/VAD interfaces, model-spec strings, and provider plugins.
An agent needs models — to hear (STT), think (LLM), speak (TTS), and detect voice
activity (VAD). The core defines these as interfaces; concrete
implementations come from provider plugins. Your agent code depends on the
interfaces, never a vendor SDK, so importing agents-go never pulls an HTTP
client or a media stack — you add exactly the plugins you use.
The four interfaces
stt.STT
Audio → text. Streaming transcripts, final + interim.
llm.LLM
Chat context → streamed tokens + tool calls.
tts.TTS
Text → streamed audio frames.
vad.VAD
Audio → speech/silence events for endpointing.
The STT/TTS/VAD interfaces expose a Capabilities() struct so the runtime can
adapt (e.g. whether STT streams). A model is just a value that satisfies its
interface — the session doesn't care who implements it.
The short way: model-spec strings
Import a provider plugin (a blank import is enough — it self-registers), then name
models as "provider/model[:variant]" in a Config. NewSession resolves them;
keys come from the provider's env var.
import (
"github.com/webdeveloperben/agents-go/agents"
_ "github.com/webdeveloperben/agents-go/plugins/openai"
_ "github.com/webdeveloperben/agents-go/plugins/anthropic"
)
session, err := agents.NewSession(agents.Config{
STT: "openai/gpt-4o-mini-transcribe",
LLM: "anthropic/claude-3-5-sonnet",
TTS: "openai/tts-1:alloy", // :variant is the voice for TTS, the language for STT
})Resolution is the database/sql pattern: providers register a factory in their
plugin's init, so the import wires them up. The registry holds factory functions
only — never credentials.
The full-control way: typed constructors
When you need options a string can't carry (temperature, base URL, a custom HTTP
client), construct the model and pass the value — Config fields accept a concrete
model as readily as a string, and per-agent overrides accept them too.
llm, err := openai.NewLLM(openai.LLMOptions{Model: "gpt-4o", Temperature: ptr(0.3)})
if err != nil {
return err
}
defer func() { _ = llm.Close() }()
session, _ := agents.NewSession(agents.Config{LLM: llm})Session default vs per-agent
Models resolve in two layers: a session default (on Config/AgentSessionOptions)
and an optional per-agent override (on AgentOptions). The runtime uses the
agent's model when set, else the session's — which is what lets a handoff switch
not just persona but the underlying LLM or voice.
Credentials
Each plugin reads its provider's standard environment variable by default (e.g.
OPENAI_API_KEY), or takes the key explicitly on the typed options. Prefer the
env var in production; pass APIKey only when you source it yourself (e.g. a
secret manager). The registry stores factories, not secrets. Mix providers freely
— the session only sees interfaces.
Available providers
The specifics for each provider — the model specs it registers, its options, credentials, and caveats — live in the Plugins catalog (OpenAI, Anthropic, Fake today; more as they land). To add your own, see Writing a plugin.
Next
- Turn detection & interruption — tune how turns end.
- Full API: Reference → Models.