Cosmo Realtime SDK
Telephony

In-call tools

Hanging up and combining call control with hooks.

Call control is expressed the same way as every other agent capability: as tools the agent is explicitly given. An agent that should be able to hang up gets the end_call tool. Nothing is implied.

Hang up with end_call

const agent = client.agent({
  instructions: '…End the call politely once the delivery window is confirmed.',
  tools: [endCallTool()],
});
from cosmo_ai import end_call_tool

agent = client.agent(
    instructions="…End the call politely once the delivery window is confirmed.",
    tools=[end_call_tool()],
)
let agent = try client.agent(
    instructions: "…End the call politely once the delivery window is confirmed.",
    tools: [.endCallTool()]
)

When the model calls it, the server ends the call — every leg drops, not just the agent's — and the session winds down; your event stream finishes with the terminal session-ended item like any other shutdown. The goodbye the model just spoke is allowed to finish playing first, so the caller doesn't get cut off mid-sentence. Without this tool the agent can't hang up: the call ends when the human does, a silence-timeout EndCall hook fires, or your code calls session.end().

Granting the tool also enables a default closing policy: when the conversation reads as finished — the caller says so, or closes with a thank-you and no new question — the agent speaks a closing line and then hangs up, staying on the line through holds. Add hang-up criteria to the instructions to tighten or change when that happens.

Guard call control

Call-control tools are server tools, so PreToolUse hooks don't intercept them — the guarantee is in which tools you grant, plus the server hooks you declare:

from cosmo_ai.hooks import SilenceTimeout, Say, EndCall

agent = client.agent(
    instructions="…",
    hooks=[
        SilenceTimeout(timeout_seconds=30,
                       action=Say(prompt="Gently check whether the caller is still there."),
                       max_count=2, reset_mode="on_user_speech"),
        SilenceTimeout(timeout_seconds=90,
                       action=EndCall(farewell="I'll let you go — call back anytime.")),
    ],
)

This combination — explicit grants, described policy, declarative timeouts — is the whole call-control story: no hidden telephony mode, just composed primitives you can read back off the agent config.

On this page