Wire an agent to a number

Connect an external or hosted agent, set its voice stack, and answer real calls.

An Skysay agent is the phone-side configuration that decides how a call is heard, thought about, and spoken. There are three modes:

  • external_audio — your own audio agent, connected over a webhook + audio stream URL. Use connect_external_agent for the common case.
  • external_text — your own text agent; Skysay handles STT/TTS around it.
  • hosted — Skysay runs the conversation for you. The default engine is Standard speech-to-text, a model, then text-to-speech. You can instead choose GPT-Live 1, which listens and speaks at once.

Or do it in the workspace

Everything below has a workspace equivalent. The Agents page lists what you have built, one row per AI agent, and each row says where it has got to:

StatusWhat it means
StoppedYou switched it off, so it answers nothing until you resume it
Needs a voiceSomething is unchosen or refused, so nothing would answer yet
Ready to testIt can hold a conversation in the browser; nothing is dialled
TestedIt has taken at least one call
Needs attentionA number is attached and its registration is waiting on you -- the carrier asked for more information, or turned the registration down
Number activatingA number is attached and the carrier has not finished
LiveA number is attached and activated, and nothing about the agent blocks a call

The Voice setup column shows the speech recognition, language model, and speech synthesis selections for hosted cascade AI agents. Native live engines show their saved model and voice. External integrations are identified as externally managed instead of being assigned platform model defaults.

Select an AI agent's name or voice setup to open its details panel, including the voice and any separate backend model. Open editor takes you to its configuration. You can search by name, language, phone number, or model and filter by voice setup. These filters apply to the loaded list; the page reports when only part of the workspace is loaded.

The summary describes saved settings, which can differ from the published configuration used by calls. Draft identifies saved unpublished settings; it is separate from whether the AI agent is ready to test. Activity combines calls today and the last call time, with the counting timezone shown below the list.

The Next column names the one thing to do next and links to the control that does it, so a row is never a dead end. Needs a voice covers more than a missing voice -- a suspended agent or an unreachable external endpoint lands there too -- so a row whose problem is something else sends you to the agent's Overview, where every problem is listed beside the control that clears it. Needs attention is the one state where the wait is yours rather than the carrier's: its next step is Fix the number, which opens that number on the Numbers page, where the checklist names what was asked for. Number activating prescribes no step, because nothing in the workspace makes the carrier finish sooner.

New AI agent opens three steps: Start (a blank agent, a preset, or bring your own), Identity (name, opening language, first message and instructions) and Voice. Choosing GPT-Live 1 at the Voice step replaces the three Standard components with one engine.

Inside an agent, the section rail groups the work: Agent (Overview, Identity, Voice, Languages), Uses (Knowledge, Tools, Phone), Conversation (Flow, Validation), Ship (Test, Versions, Call history) and Advanced (Tuning, Credentials). Overview is the landing section: it lists what is left to do before the agent can be published, and what still blocks publishing, each beside the control that fixes it.

A new agent also gets a short checklist on Overview, Three steps to the first call. It is an onboarding aid: it disappears once the walk to a first call is over — the agent has held a conversation, has a number attached, or has been stopped — leaving At a glance as the top of the section. Its rows do not repeat the editor's controls — each one takes you to the control that owns the step.

Talk to it, at the top of the agent editor, opens the test panel beside the editor, where you choose Browser or Phone and whether you are testing the Current draft or the Published snapshot. On a wide screen the panel is already open beside the editor and carries its own start control, so the header button appears when the panel is collapsed or the window is too narrow to show it.

Editing does not publish: Publish changes shows exactly which fields changed and asks before it writes. It is offered only while the draft differs from the published snapshot — when the editor says the page matches what is published, there is nothing to publish.

Stopping and resuming an agent

Stop answering, at the top of the agent editor, takes one AI agent off the air without deleting anything. Resume puts it back.

A stopped agent answers nothing:

  • no inbound or outbound telephone calls,
  • no browser test, and
  • no homepage demo.

Nothing else changes. The agent, its voice stack, its knowledge, its tools and its attached numbers all stay exactly as they were, and you can keep editing and publishing the draft while it is stopped.

Resume lifts the stop and does nothing else. It restores no snapshot: the agent comes back on whatever is published at that point and on the numbers routed to it then, and it answers as soon as the rest of its setup allows. So this is the safe way to take an agent out of service for an hour, a weekend, or a season — and if you publish changes while it is stopped, those are the changes it comes back with.

The one visible consequence is on your numbers: a number routed to a stopped agent stops answering, and the Phone numbers page shows it as a problem naming the stopped agent as the reason, until you resume the agent or route that number somewhere else.

Over the API the same control is the status field:

you › stop my receptionist answering
→ update_agent(agent_id=..., status="inactive")    # agents:write

status accepts active and inactive, and rejects anything else with a 400 — as it does any change to an agent whose stored status is neither of those. A call to a stopped agent is refused with the agent_inactive reason. A call already in progress when you stop the agent is not cut off.

A suspended agent is not a stopped one

If an Skysay operator has suspended an agent, that is a different state and you cannot clear it yourself — status will not move the agent out of it. Contact support.

1. Create the agent

you › connect my audio agent at wss://my-agent.example/stream
→ connect_external_agent(...)        # agents:write

create_agent is the full form (mode, first message, system prompt, voice stack). connect_external_agent is the shortcut for an external_audio agent with webhook and audio-stream URLs.

Changing an agent later

An edit through update_agent (PATCH /v1/agents/{agent_id}) takes effect on the agent's next call. An edit to its prompt, greeting, language or voice stack publishes the agent in the same step. If the agent could not be published that way (a greeting its voice cannot speak, for example), the edit is refused and nothing changes. Tools, the recording setting and tuning are read when each call starts, so they always took effect on the next call. Calls already under way keep what they started with, and an edit that changes none of these, such as a new name, publishes nothing. An edit made while the agent is not hosted is published when it becomes hosted again.

This fixes a bug. On an agent that had already been published, an edit to its prompt, greeting, language or voice stack used to be stored while calls kept running the last published version until the next publish from the editor.

A hosted agent that has never been published is published by the first save that leaves it valid. A save that does not is still kept, and the agent's metadata.publication says why:

{"state": "unpublished", "reason": "publication_variables_invalid", "where": "system_prompt.en", "issue": "UNDECLARED_VARIABLE"}

reason is one of publication_stack_incomplete, publication_greeting_missing, publication_variables_invalid, publication_workflow_invalid, publication_language_unavailable or publication_refused; where names the part of the agent to fix, and issue carries the call-variables code when there is one. Once published, the record reads {"state": "published"} with the other fields empty. It belongs to the platform: a metadata replace keeps it as it was.

Three settings belong to set_agent_voice_stack (PATCH /v1/agents/{agent_id}/voice-stack):

  • Follow the caller (metadata.follow_caller): update_agent refuses a change to it and keeps it through a metadata replace.
  • Phone menu navigation (metadata.navigation): on by default for every AI agent. update_agent refuses a change to it and keeps it through a metadata replace, so an explicit off survives. See Phone menu navigation.
  • A new language for an agent that runs a workflow: set_agent_voice_stack translates the workflow into that language first, including every language Follow the caller for all languages adds. update_agent refuses a language the workflow does not speak yet, and so does a switch back to hosted that would publish one.

Read Skysay phone-number coverage during a conversation

Attach this built-in tool to a hosted AI agent when it should answer questions about Skysay's supported phone-number countries:

{"type": "builtin", "name": "get_phone_number_coverage"}

The tool uses the same maintained, customer-safe coverage data as GET /v1/coverage-matrix. It works on inbound and outbound calls, browser tests, homepage demos, and SMS read-tool requests. It reads information without ordering a number or asking for confirmation. Each AI agent must explicitly have the tool attached; it is not enabled automatically.

Use it with hosted AI agents without a conversation flow. A published conversation flow cannot run this built-in as a tool step.

The model can call it with {} for a compact country list, or {"countries":["Estonia","Germany"]} for capabilities and onboarding details. Use up to ten English country names. Existing coverage aliases such as EE, US and UK also work. Unrecognized names appear in not_listed; they do not cause a fallback to all countries. Results include returned_count, total_countries and has_more, with at most 200 country rows returned.

Coverage is not a live inventory check. inventory_checked is false: availability of an exact number, current pricing, and country and number-type activation requirements still need a current number-catalog check. Instruct the AI agent to answer from the tool result and avoid promising an immediately available number or instant activation.

When attaching it through PATCH /v1/agents/{agent_id}, preserve the complete existing tools list and send its previously read value as expected_tools. Replacing the list with only this entry removes the other tools.

2. Choose a voice stack

For hosted or external-text agents, pick a conversation engine first. Standard uses STT / LLM / TTS providers from the catalog. GPT-Live 1 uses a GPT-Live voice and a backend model instead. get_agent_catalog lists selectable providers plus conversation_engines; filter Standard rows by component and language (for example, language=et requests the current Estonian options).

→ get_agent_catalog(component="tts", language="et", metered_only=true)   # agents:read or coverage:read
→ set_agent_voice_stack(agent_id="ag_...", ...)        # agents:write

Set metered_only=true only when you want component-metered choices; omit it to see every runnable adapter.

set_agent_voice_stack validates the effective selection against the declared runtime and its credential and billing contracts. The catalog exposes the runtime-declared combinations; a provider voice's advertised language count alone does not establish that its complete call stack is runnable. The tool maps to PATCH /v1/agents/{agent_id}/voice-stack; its language fields match the generated API reference.

Keep a fixed language per call, or enable Auto multilingual and choose all supported languages or your own subset. The underlying Follow the caller setting is optional: publish it only with a listening configuration that supports the accepted languages together. The AI agent may then switch among the call's admitted profiles on a clear request or stable language evidence, without changing its shared tools or business instructions. A voice's multilingual label alone is not proof of simultaneous listening support. See Multilingual calls for the API setting, boundaries, and test flow.

From MCP, use list_agents for a bounded newest-first page, get_agent for a single current projection, update_agent for ordinary mutable fields, and get_agent_voice_stack to read a published stack back. The key's organization is authoritative: omit the redundant organization_id, or repeat only the same workspace. A different workspace, project, or agent is rejected before a configuration write or preview render; treat that MCP error as a tenant validation failure, not a retry prompt for another workspace identifier.

preview_voice is the MCP Listen action. It has agents:write because it can contact a provider or validate a BYOK credential and is rate-limited per workspace; it is not a read-only preview. Browser-session create and settle remain browser/REST operations because they require a browser-owned LiveKit audio participant and later client settlement.

Optional outgoing ambience

An agent may also publish one optional audio_environment selection with its voice stack. It is strict and version-pinned: { preset_id, asset_version, volume }. Select it from GET /v1/audio-environments or MCP list_audio_environments; Off is an explicit selection with volume zero. An enabled preset needs a positive whole-number volume. Unknown fields, unknown presets, a missing asset version, and a mismatched version are refused rather than guessed or replaced.

This is an outgoing background track, shared across the agent's language profiles. It is never caller/STT input and does not change the chosen voice, language, or call's frozen voice-stack configuration. If you audition it with preview_voice, supply non-blank text; the exact text and selected language are preserved rather than substituted or translated. A preview is a bounded local audition, not proof of a receiver-side final mix.

Choose a voice, not a vendor. The Voice step shows voices available for your AI agent's language: play a sample, and picking a voice sets the provider, the model, and the exact voice id together. Voices in the sidebar is the same gallery unfiltered, for browsing across every provider and language before or without editing an AI agent.

Browsing and listening are open in every language a provider advertises, which is wider than the set an AI agent can take calls in — a call also needs transcription and a qualified stack. A voice you can hear in a language but not yet deploy in says so on its card rather than disappearing from it.

Each card shows only what the provider supplied — structured gender, its own tags, its own description — plus the source of each of those fields. Nothing is inferred from the audio: no guessed age, accent, personality, or quality score. Cost and latency each carry the source of that number, which may be a measurement from real calls, a figure the vendor publishes, or a catalog estimate that says it is one.

Galleries are bounded, ordered selections rather than an unrestricted provider dump, and they say when they are showing a slice. Filtering and search on the Voices page are answered by the server, so a voice on a later page is still found. An engine that cannot be billed yet, or that this catalog does not offer for calls in the language you are filtering by, stays visible and disabled with that reason rather than disappearing, and if an existing AI agent uses a voice outside the current selection, its exact stored choice stays in that agent's Voice step instead of being silently replaced.

The full Voices page has four horizontal, searchable multi-select filters: Language, Accent, Character, and Provider. Several values in one filter are an "any of" selection; filters together narrow the result. Character is only the provider's own style or persona metadata, never a gender proxy. The page derives its values from the cached provider inventory, so a new provider voice or declared language does not need a frontend list or manual promotion.

Use Hear it as your AI agent to listen before saving. It speaks any sentence you type — your AI agent's first message by default — in any language the provider advertises. The audio is never stored, and the request is bounded and rate-limited per workspace.

The gallery is backed by the provider's scoped cached inventory rather than a frontend-maintained voice list. New provider voices therefore appear after a cache refresh without a frontend release or human promotion step. A failed refresh serves the last good inventory, and a bounded partial inventory never proves that an unobserved voice was removed.

On the full library page, a cached audio sample is a fast path for a selected target language only when its catalog provenance proves that match. At present, an Skysay ingestion-synthesized sample proves English; a provider sample with no spoken-language assertion is not assumed to be English. With no Language filter or chosen preview language, an existing recording can play as published and the row labels unverified spoken language rather than inferring one. A row with no suitable sample still offers Play, which makes the bounded, metered, rate-limited live preview request. If it cannot run, the page shows a local safe error rather than a provider credential, trace, or raw provider response. Several matching selected languages require an explicit choice in the row's searchable preview-language control; the library never silently chooses the first one. Entering your own text deliberately uses that live request and speaks the exact wording you enter without translation. With no typed text, the library uses a localized sample sentence for the chosen language when it has one; otherwise it asks you for text instead of substituting English.

Cartesia Sonic 3.6 follows that same contract. Its managed gallery contains only the provider's public, non-owned voices. If you use your own Cartesia credential, its owned or cloned voice IDs remain private to that credential's workspace and project; test the exact ID with your own text before saving it. The preview does not substitute a managed credential or a fallback voice.

On Skysay credentials, a new selection must belong to the managed scoped inventory. With your own provider credential, validation and preview stay scoped to that exact credential; cloned and private voice IDs can work without becoming visible to another workspace. A preview started with your credential never falls back to an Skysay one.

Skysay does not automatically choose a default or recommended language or voice. Select both explicitly. If a provider later withdraws an existing stored voice, the editor keeps that exact choice visible with a warning; it is never silently replaced by a fallback voice. An exact provider response that the voice no longer exists blocks future call admission until you choose a new voice or a successful explicit validation clears the marker.

Several languages, one hosted agent

Choose the agent's supported languages, an opening language, and one shared voice. You do not need separate copies of its identity, instructions, tools, knowledge, and business policy. Optional language overrides can change a voice, transcriber, or exact greeting without duplicating the rest of the agent. Unspecified values inherit the shared settings; clearing an override restores inheritance. An exact greeting is optional, not a publish checklist for every language.

Saving the voice stack publishes the effective profiles. A browser test or outbound call selects a published language before admission, and the resolved configuration is frozen for that call. A later agent edit does not change an in-progress call or its quoted component identities. This is fixed-language calling, not automatic mid-call language switching.

See Multilingual outbound calls for the request fields and application boundary. A Voice Library language filter controls an audition; it does not grant the agent permission to call in that language.

Interruptions and barge-in

Every hosted phone call, in every language, requires 500 ms of continuous caller speech before it interrupts the agent unless the agent sets its own threshold. That is the default, not a floor: an explicit min_speech_ms is honoured on phone calls in every language down to 150 ms, and a value below 150 ms is raised to 150 ms. Browser and web calls do not apply this setting: it is still stored on the agent and returned to you, but those calls are not phone calls and keep the browser stack's own threshold. The default deliberately reduces false interruptions from very brief background audio and backchannels while keeping a sustained request such as “stop” interruptible. Sustained background speech can still be treated as caller speech.

After the caller stops speaking, the agent waits for a fixed endpointing hold before it treats the turn as finished. On a phone call, an agent whose language has a trained turn detector holds for 600 ms when the detector judges the caller finished and up to 1200 ms when it judges them probably not finished; every other language holds for 800 ms. These holds keep a caller's mid-sentence pause (after their name, before a number, while leaving a message) from ending the turn on a narrowband phone line. A browser test call runs the shorter browser timings. The interruption_sensitivity presets move that hold by a different amount in each class, because in a language without the turn detector the hold is the whole end-of-turn decision:

PresetInterruption thresholdHold, language with the turn detectorHold, every other language
balanced (default)500 ms600 ms, up to 1200 ms800 ms
low750 ms900 ms, up to 1800 ms1100 ms
high150 ms260 ms, up to 600 ms600 ms

Languages with the trained turn detector are Arabic, German, English, Spanish, French, Hindi, Indonesian, Italian, Japanese, Korean, Dutch, Portuguese, Turkish and Chinese. Every other language, including Sinhala, Tamil and Estonian, uses the right-hand hold column. See Turn detection by language for how the two signals behind this table work and for guidance on choosing a preset per language.

The hold is a minimum wait, not the reply time. A turn never ends before voice detection reports the end of speech, which takes about 250 ms of silence, and never before the final transcript of what the caller said has arrived, which depends on the speech-to-text provider. The agent editor shows these figures for the agent's own language under Interruption sensitivity, with a timeline of when that agent's recorded replies actually started.

What turn_taking in set_agent_voice_stack adds is per-agent control over that threshold, the endpointing hold, and whether an interruption must also carry recognized words. interruption_sensitivity, min_speech_ms and silence_hold_ms all apply in every language. The preset sets both the threshold and the hold from the table above; an explicit min_speech_ms or silence_hold_ms takes precedence over the preset for its own knob, so you can combine a preset with one explicit number. min_interruption_words has its own condition and is the one setting here with a non-zero default; it is described under the table.

The controls are applied when a call starts; saving a voice stack never changes an in-progress call.

SettingEffect on a hosted phone call
interruption_sensitivityEvery language. balanced is the default: the 500 ms threshold and the platform hold. low requires 750 ms of continuous speech and holds longer after it. high uses 150 ms for callers who need a more responsive threshold, and holds for less. The hold each preset sets depends on whether the language has the trained turn detector (table above), and it is a minimum wait, not the reply time. min_speech_ms and silence_hold_ms, when set, take precedence for their knob.
min_speech_msEvery language. An explicit 80–2000 ms interruption threshold, overriding any sensitivity preset. On a phone call it is honoured down to 150 ms; a value below 150 ms is raised to 150 ms. A phone call without it, and without a preset, uses the 500 ms default. Browser and web calls store it but do not apply it.
silence_hold_msEvery language. The shortest wait, 100–2000 ms, after the caller stops speaking before their turn can end. It overrides the platform hold and any sensitivity preset. A value below about 250 ms has no effect, because voice detection needs that much silence to report the end of speech, and the wait is longer whenever the final transcript arrives later than this value.
min_interruption_words0–5. Defaults to 1 on hosted English calls and to 0 (off) everywhere else. An interruption must ALSO carry at least this many recognized words from the caller, on top of the speech-duration threshold. Set 0 explicitly to turn it off. Effective only on stacks whose transcriber reports words fast enough — see below.
barge_in_speech_rmsDeprecated. Accepted, stored and returned for compatibility only; the runtime does not apply it to call behavior. Use interruption_sensitivity, min_speech_ms and min_interruption_words to control interruptions.

A wordless burst that clears the threshold does not end the reply. If no caller speech follows, the runtime classifies the interruption as false: the agent’s reply pauses for up to a second and then resumes from where it paused.

Requiring words as well as duration

min_interruption_words addresses a different problem from the duration threshold. Raising min_speech_ms rejects short bursts, but a long stretch of non-speech audio — a television, a passing vehicle, a cough — can clear any duration threshold you would still be willing to interrupt on. Requiring a recognized word rejects that class outright: with min_interruption_words: 1, the agent yields the floor only when the caller has both held it for the duration threshold and actually said something.

Both conditions must hold. The setting never lowers the duration threshold and never makes an interruption happen sooner.

The default

A hosted English agent that has not set min_interruption_words runs with 1: one recognized word as well as the duration threshold. Agents in every other language default to 0 and run on the duration threshold alone, because the requirement is only enforceable where the transcriber can report a word in time (see below).

To turn the requirement off on an English agent, set min_interruption_words to 0 explicitly. An explicit 0 is stored and returned; leaving the setting out is what selects the default.

It is accepted and returned for any agent in any language, but it is effective only where the transcriber emits words fast enough to land inside the interruption decision — today that is the Deepgram stacks, which serve English and Estonian. On every other stack the setting is stored, returned unchanged by get_agent_voice_stack, and ignored at call time: those calls run on the duration threshold alone, exactly as they do with the setting unset. The distinction is the transcriber's timing, not the language: a transcriber that reports a caller's first word a second or two after they start speaking would refuse ordinary interruptions rather than only the wordless ones, which is worse than not having the setting.

Sounds that do not count as words

On hosted English calls, short listening noises from the caller do not count toward min_interruption_words. "mm-hm", "uh-huh", "yes", "yeah", "okay", "right", "sure", and hesitation sounds such as "uh" and "um" are what a caller says to show they are following, not to take the floor, so a transcript containing nothing but one or two of them will not interrupt the agent however long the caller holds it.

This is English-only, and deliberately so. Estonian is the other language whose transcriber is fast enough for min_interruption_words to take effect, and an Estonian agent that sets it runs the word requirement in full — but every word counts there, including "jah" and "okei", because the equivalent list has not been measured for that language. Applying an English list to it would refuse nothing while this page claimed otherwise.

The caller is still heard. What they said is delivered to the agent when the reply ends, so a caller who says "okay" is answered afterwards rather than ignored — they simply do not cut the agent off mid-sentence to do it.

Anything else counts, including short words that sound similar in isolation. "no" is a word; so is "wait", "stop", and "huh". So is any phrase that mixes the two: "yes but" carries a word the agent will stop for.

Expect a small added delay when the setting is on. On the Deepgram stacks transcription results arrive about once a second, so roughly half the time the caller's first word is already recognized when the duration threshold opens and the interruption is unchanged; the rest of the time it is delayed until the next result, by up to about half a second. A word recognized before the threshold opens costs nothing — the interruption still happens the moment the caller has spoken for long enough.

1 is the English default for this reason. Values above 1 require most of a phrase before the agent will stop, which callers experience as an agent that does not listen.

Four protections are not settings and are not English-only. On every hosted phone call, in any language:

  • The runtime holds what the caller is transcribed as saying while the agent is preparing or delivering a reply, and delivers it once that reply ends. Background speech picked up by transcription therefore cannot cut the agent off mid-sentence.
  • For agents using the Standard conversation engine on an inbound call, or on a call bound to an agent workflow, the opening line is not interrupted by the phone being picked up. While the opening line plays, caller speech shorter than one second of continuous speech — a "hello?", a syllable, a breath — does not cut it, in any language and whatever the agent's interruption threshold. What the caller said is still transcribed and is answered once the opening line has finished, so nobody who spoke is ignored. A caller who keeps speaking for longer than a second has taken the floor: the ordinary interruption rules apply from that moment and the opening line stops as any reply would. Speech that arrives after the call is answered but before the opening line has started — the callee answering into a line that has not said anything yet — is held exactly like a pickup during the opening and is answered once the opening line has finished; on a workflow-bound call a held "hello" typically costs one clarification turn rather than being lost, since the identity question has not been heard yet. The opening line itself is still spoken immediately in every case — nothing waits for that early speech before starting it. The opening line also cannot be cancelled before its first audio frame reaches the caller, so mis-transcribed background noise cannot open a call in silence. On an outbound call with the Standard engine none of this applies: the agent lets the person say hello first, and its opening is an ordinary reply the person can interrupt. See Who speaks first. If the opening line cannot be synthesised at all, a short line in the call's own language is played in its place; that substitute exists for English, Estonian, Sinhala and Tamil, and a call in another language, or one whose substitute also fails to synthesise, still opens in silence. GPT-Live 1 and Gemini Live agents handle barge-in on the model side: the opening line is not held uninterruptible by this protection, and a pickup-shaped "hello?" may still cut it. Workflow-bound calls cannot use either engine, so the early-speech hold described above applies to Standard agents only.
  • When an interruption does qualify, the agent plays on for a bounded moment instead of stopping at the exact instant it is cut, so the sound it is part way through finishes rather than being clipped. This is a time budget of up to 300 ms, and it decides when the agent stops rather than where in a word: an interruption early in a long word still lands inside it, one syllable later. What it buys is a less abrupt stop and a shorter gap when a brief interruption turns out to be false.
  • When the agent does stop, the last fraction of a second it had already committed to the call is played out under a quick fade rather than dropped, so the final word ends instead of being clipped part way through. On agents whose voice provider reports word timings — today ElevenLabs and Cartesia, which covers English and Estonian — the stop is moved to the end of the word being spoken whenever that end is close enough to reach; otherwise, and on every other voice, the fade is used. Either way the agent is silent within about half a second of the interruption qualifying, and it never plays anything the caller was not already about to hear.

None of these needs configuration, and browser tests are unaffected.

When the caller seems to start talking before a reply

If the caller appears to start speaking just as a reply is ready, the agent waits rather than talk over them. Background noise — a television, traffic, people nearby — can sound like the start of speech, so on a hosted phone call the agent does not wait on sound alone forever:

  • On hosted English calls transcribed by Deepgram, with min_interruption_words at 1 or more (the English default), the agent waits at most 1.5 seconds when no words are recognized, then speaks. Listening sounds such as "mm-hm", "okay" or "uh" do not count as words. That is longer than it takes the transcriber to report a caller's first word. If the caller does say a word during the wait, the agent keeps waiting for them, up to eight seconds.
  • A reply that starts after such a wait still stops for the caller: the caller's recognized words (min_interruption_words of them, one by default), held for the interruption threshold, interrupt it as usual. Continued noise with no words does not.
  • Every other language and transcriber keeps the eight-second limit until the transcriber's word timing for that stack has been measured. The speech-to-speech engines are unchanged.

This is not a setting. interruption_sensitivity, min_speech_ms and silence_hold_ms do not change it.

3. Point a number at it

Number rules decide what happens when someone calls a number and which agents can use it to place calls. Update them with update_number_rules (numbers:write); read them with get_number_rules (numbers:read).

To take a number back off an agent, POST /v1/phone-numbers/{number_id}/detach-agent (numbers:write). It is a pure control-plane unbind: the number stays imported and owned by the workspace, its rules become disabled, and no carrier work happens. Inbound calls are declined until you attach an agent again or change the rules. Detaching a number that already answers without an agent replays as a no-op with idempotent: true. The same action is available in the workspace on the agent's Phone section and on the number's page.

If you decided to detach from a view of the number that may since have moved on — a page a teammate reassigned under you — name the binding you expect. Send expected_agent_id, or expected_agent_endpoint_id when the rule answers through an endpoint you cannot resolve to an agent. A number that by then answers with a different binding is refused with 409 and nothing changes, so you cannot take a colleague's fresh assignment offline by confirming a stale screen. Naming an identity the rule no longer carries is refused the same way: an expectation that cannot be confirmed is not treated as confirmed. A binding that is gone entirely is not a conflict — the state you wanted already holds, so it replays as the idempotent: true no-op. Send neither field to detach whichever agent answers.

Test in the browser first

Before assigning a live number, use a browser test with welcome credit or purchased funds to hear your agent. No number provisioning is needed. A separate, normally funded phone test is needed to prove the carrier route.

Check incoming-call configuration

Open Phone numbers and select the number. The existing Activation checks distinguish purchase and carrier-order completion from incoming-call configuration. A purchased, active number can still need attention before its AI agent can answer.

A warning in the number list points to the explanation in the selected number's checks. Follow the suggested action, such as assigning an AI agent or contacting support when pricing is unavailable. Supported call-in/call-out capabilities describe the number's features; they do not prove that a call can connect right now.

These checks describe saved configuration. Available funds, current capacity, call policy and carrier reachability are still checked when a call arrives. Outbound support depends on the selected destination and is checked when the call is requested. Refresh the page after correcting a prerequisite.

Bring your own agent

Two of the three modes let your own application do the thinking. Both are created in the workspace from Agents → Bring your own agent, or over the API with POST /v1/agents.

Webhook agent (external_text)

Skysay runs speech-to-text and text-to-speech around your app, so the app only deals in text.

  • What Skysay sends. A POST to your webhook URL for each call lifecycle event and each transcript turn, signed with X-Agent-Telco-Timestamp and X-Agent-Telco-Signature.
  • What your app returns. The words to say next, as a text or NDJSON response. Skysay speaks them to the caller.
  • Where the URL goes. The Webhook URL field on the create form, or webhook_url on POST /v1/agents with "mode": "external_text".

Realtime audio agent (external_audio)

Your app hears and speaks the call itself; Skysay runs no speech stack for it.

  • What Skysay sends. Call lifecycle events to your webhook URL, and bidirectional call audio to your realtime audio URL — the gateway opens that wss:// connection while the route is active.
  • What your app returns. Audio, on the same connection.
  • Where the URLs go. The Webhook URL and Realtime audio URL fields on the create form, or webhook_url plus audio_stream_url on POST /v1/agents with "mode": "external_audio". connect_external_agent is the shortcut for the same pair.

POST /v1/agents answers with the agent's signing secret in agent_endpoint.webhook_secret, once. Save it immediately: every later read returns [REDACTED]. It signs each event and tool call Skysay sends to your webhook; verify X-Agent-Telco-Timestamp and X-Agent-Telco-Signature as described in Post-call results. Agents created before 24 September 2026 cannot retrieve their signing secret; recreate the agent or contact support.

Webhook signature verification, idempotency and backpressure handling stay in your app. GET /v1/agents/{agent_id}/handoff returns the generated setup contract for either mode: the endpoints it will call, the events to expect, and the headers to verify.

To send a phone number's calls to a realtime audio agent, open Phone numbers, select the number, and pick Send live audio to my app under "When someone calls".