Cosmo Realtime SDK
Concepts

Clients, agents, and sessions

The three-tier model every SDK shares — credential, reusable persona, one live run.

All three SDKs are built around the same three nouns:

TierHoldsLifetime
Clientcredential (API key or token), base URL, transportyour process
Agentthe persona: instructions, model, voice, tools, skills, hooksreusable, immutable
Sessionone live run: LiveKit room, event stream, per-run optionsconnect → end

The split matters because the pieces vary at different rates: your credential is process-wide, your persona is designed once and reused, and a session is one conversation. If a value wouldn't differ between two runs of the same agent (voice, greeting, tool set), it belongs on the agent. If it varies run-to-run (resume id, whether to record), it's a session option.

client = CosmoRealtime(api_key=os.environ["COSMO_API_KEY"])

agent = client.agent(
    instructions="You are Alex, a support agent at Acme.",
    voice="Puck",
    tools=[lookup_order],
    greeting="Hi, this is Alex — how can I help?",
)

async with agent.start(store_recording=False) as session:
    async for event in session:
        ...
const client = new RealtimeClient({ token: endUserJwt });
const agent = client.agent({
  instructions: 'You are Alex, a support agent at Acme.',
  voice: 'Puck',
  tools: [lookupOrder],
  greeting: 'Hi, this is Alex — how can I help?',
});
const session = await agent.start();

In Swift the agent tier is the SessionConfig value you pass to RealtimeSession.start(_:config:) — build one SessionConfig and reuse it across sessions.

Inline agents

client.agent(...) defines the persona in code. Everything is explicit: instructions, model, model_options, voice, tools, greeting, interruption_sensitivity, audio, skills, hooks. How the agent sounds rides under voice (name, speaking_style); the audio pipeline rides under audio (output, noise_cancellation, ambience). Anything you omit gets a server default (for example, the workspace's default model and voice) — with one exception: an inline agent that leaves audio.noise_cancellation unset sends an explicit true, overriding the protocol's own false default. Pass it explicitly to opt out.

Derive variants without mutating: agent.with_(voice="Kore") in Python, agent.with({ voice: 'Kore' }) in TypeScript. The original agent is untouched.

Catalog agents

A catalog agent's configuration lives server-side, created and edited in the dashboard (Realtime agents). Your code launches it by its machine handle:

agent = client.catalog_agent(
    "support-triage",
    inputs={"customer_name": "Dana"},   # fills {{customer_name}} in the stored prompt
    voice="Puck",                       # per-run cosmetic override
)
const agent = client.catalogAgent('support-triage', {
  inputs: { customer_name: 'Dana' },
  voice: 'Puck',
});
var config = SessionConfig()
config.agentName = "support-triage"
config.agentInputs = ["customer_name": "Dana"]

Only per-run ride-alongs are accepted alongside a catalog handle — inputs, a voice override, extra tools, hooks. Sending stored-config fields like instructions or model with a catalog agent is a schema error: the stored config is the source of truth, and the server rejects the ambiguity rather than guessing.

Catalog agents are how you iterate on a shipped product without an app release: the client names the agent; prompt, model, voice, and server-tool changes land from the dashboard.

Session options

Per-run options ride on start(), not on the agent:

OptionEffect
resume_session_idcontinue a prior session's conversation (experimental — see Session limits & resume)
store_recordingpersist audio/transcript/tool artifacts server-side (see Recording & privacy)
max_session_secondsrequest a wall-clock cap; server enforces the minimum of yours and its own (exposed on Swift's SessionConfig today)
on_state_change (Python)callback for idle → connecting → connected ↔ reconnecting → disconnected

The server resolves the final configuration at session start and reports it on the ready event: the resolved agent summary (for catalog handles), any rejected_tools, and the effective max_session_seconds. Trust ready, not your request, as the statement of what the session actually got.

On this page