Elizon Docs
Guides & Walkthroughs

Voice and SIP

Build a Package that answers phone calls on the installer's own number.

A phone-answering Package brings how the line behaves: the first message, the Agent that talks, the speech settings and the call routing. The installer brings everything that costs money or identifies them: speech-provider accounts, the carrier, the trunk and the number.

1. The Agent that takes the call

An ordinary Agent. Write its instructions for speech: short sentences, no markdown, confirm what you heard.

2. The voice configuration

voice/after-hours-line.yaml
name: After-Hours Line
sttProvider: soniox
sttConfig: { languageHints: [en] }
sttSlot: speech-in
ttsProvider: elevenlabs
ttsConfig: { model: eleven_flash_v2_5, stability: 0.5 }
ttsSlot: speech-out
callBehavior:
  callFlow:
    firstMessageMode: say
    firstMessage: Thanks for calling. This is an automated assistant — how can I help?
recordCalls: false
consentMessage: null
agent: agents.intake

Say in the first message that the caller is talking to an automated assistant. It's the honest thing to do, and it's what the EU AI Act's transparency obligation asks of conversational systems.

sttConfig, ttsConfig and callBehavior accept any key, but a call reads only the ones listed for each provider in Voice and SIP definitions. npx @elizon/cli validate warns about every other key.

3. The inbound routing template

sip/inbound.yaml
sipTrunkSlot: phone-line
direction: inbound
inbound:
  srtp: allow
  sipHeaders: x_only
  noiseCancellation: true

What each srtp and sipHeaders value does, and when to pick it, is on Voice and SIP definitions. sipTrunkSlot must name a declared sip-trunk Slot, or validate refuses it; use the one your trigger names. The headers sipHeaders lets through arrive on the call as sip.h.* participant attributes. npx @elizon/cli example sip prints a complete phone-line project to start from.

4. The manifest

elizon.yaml
compatibility:
  requiredCapabilities: [voice, sip]

voice:
  ref: ./voice/after-hours-line.yaml
sip:
  ref: ./sip/inbound.yaml

slots:
  - id: speech-in
    type: stt
    required: true
    allowedProviders: [soniox]
    description: Your speech-to-text account.
  - id: speech-out
    type: tts
    required: true
    allowedProviders: [elevenlabs]
    description: Your text-to-speech account.
  - id: phone-line
    type: sip-trunk
    required: true
    description: The trunk your after-hours number rings on, with the number routed to it.

triggers:
  - id: after-hours-call
    type: inbound-call
    sipTrunkSlot: phone-line
    routing:
      ref: ./sip/inbound.yaml
  - id: run-manually
    type: manual
    description: Replay a request without a call, to test after installing.

The manual trigger matters. It lets the installer test the Package from Studio before any call arrives.

Recording calls

If the Package records calls, set recordCalls: true and write the consentMessage callers hear first. The installer must read it and confirm it suits where their calls are recorded, and the wizard won't enable recording without a message.

What the installer does

  1. Voice step: choose their speech-to-text and text-to-speech providers and credentials (only the providers in allowedProviders are offered).
  2. SIP Inbound step: pick one of their inbound trunks that's ready, and the number the Package answers.
  3. Test inbound: call the number from any phone. The wizard confirms the call reached Elizon before activation. The line answers as it does today until the Package is activated.
  4. Activate: the routing template is applied to the chosen trunk. Nothing else about the trunk, the carrier account or other numbers changes.

Tell installers to arrange the trunk and number before they start. Carrier setup is the slow part; the install itself takes minutes.

See also Voice and SIP definitions and the Triage walkthrough.