Elizon Docs
Features & SpecsPortable definitions

Voice and SIP

Portable voice configuration and inbound SIP routing.

A Package can answer phone calls. It brings how the line behaves. The speech providers, the carrier, the trunk and the number all belong to the installer. At most one voice configuration and one SIP routing template per Package.

Voice configuration

voice/after-hours-line.yaml
name: Phone Line
sttProvider: soniox
sttConfig:
  languageHints: [en]
sttSlot: speech-in
ttsProvider: cartesia
ttsConfig:
  language: en
  speed: 1
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.call-handler
FieldMeaning
nameThe configuration's name in Studio.
sttProvider, sttConfigThe speech-to-text provider the configuration was built for, and its settings (providers, keys).
sttSlotThe stt Slot the installer fills with their own provider and credential.
ttsProvider, ttsConfig, ttsSlotThe same for text-to-speech (keys).
callBehaviorHow the call runs: the first message, turn-taking, interruptions and voice detection (keys).
recordCallsWhether calls are recorded.
consentMessageWhat callers hear before anything else when calls are recorded. See Recording and consent.
agentThe Agent that handles the call (agents.<name>).
elizon.yaml
voice:
  ref: ./voice/after-hours-line.yaml
slots:
  - { id: speech-in, type: stt, required: true, allowedProviders: [soniox] }
  - { id: speech-out, type: tts, required: true, allowedProviders: [cartesia] }

Providers

The provider keys a Package may use for sttProvider and ttsProvider, and in an stt or tts Slot's allowedProviders. They are the providers this platform runs. Write them in lowercase (they are matched without regard to case).

SideProvider keys
Speech-to-textsoniox, cartesia, elevenlabs, google, azure
Text-to-speechcartesia, elevenlabs, azure, google, soniox
  • allowedProviders narrows which of these the installer may choose. Omit it to offer them all.
  • An sttProvider or ttsProvider outside this list: validate warns (VOICE_PROVIDER_UNSUPPORTED). validate does not check allowedProviders entries; the install refuses to bind a Slot to a key outside this list (SLOT_BINDING_UNRESOLVED), and a Slot whose allowedProviders are all outside it cannot be bound at all.
  • The installer chooses the provider. If they choose the one you built for, your sttConfig or ttsConfig is kept. If they choose another one, it is dropped (its keys mean nothing to the other provider) and they set that provider up in Studio after the install.
  • The credential comes from the Slot: the install writes it into the configuration as apiKey. Never set apiKey yourself; validate warns (VOICE_CONFIG_KEY_IGNORED).
  • For google (both sides) the Slot's apiKey is not used. Google authenticates with the operator's service account (serviceAccountJson, set up in Studio after the install) or the voice worker's own Google credentials. Never set serviceAccountJson in a Package either; validate warns.

How the settings are read

sttConfig, ttsConfig and callBehavior are free-form in the schema: validate and build accept any key. A call reads only the keys listed below, for the provider in use, and drops every other one. validate warns about each key a call would ignore (VOICE_CONFIG_KEY_IGNORED), so an unknown key never fails a build, but it never does anything either.

  • A value the platform cannot turn into one the provider accepts is dropped too, and the provider's own default applies. "If omitted" in the tables below is also what you get then.
  • Language values take a language code (en, en-GB) or an English language name (English). Auto means "detect", where the provider can.
  • No value may look like an identifier (a UUID). The install refuses a configuration that carries one, because an id never means the same thing in another Organization. Cartesia voice ids are UUIDs, so leave Cartesia's voice out; the installer picks the voice in Studio.
  • region, location, voice ids and ElevenLabs dictionaries name resources in one provider account. They refer to the installer's own account, so leave them out unless the installer is expected to have the same ones.
  • Voices and models change often at every provider. The keys below are stable; which voice or model ids exist is the provider's catalog, not this page's.

sttConfig

soniox

sttProvider: soniox
sttConfig:
  sttModel: stt-rt-v3 # a model id from Soniox
  languageHints: [en, de]
  context: Industrial pumps, valves and service contracts.
  diarization: false
  languageId: true
KeyTypeIf omittedEffect
sttModelstring, a Soniox model idSoniox's defaultThe recognition model. A value containing a space is dropped.
languageHintslist of languagesnoneThe languages to expect. Auto and unknown names are dropped.
contextstringnoneWords and phrases that steer recognition (names, product terms).
diarizationbooleanSoniox's defaultTell speakers apart.
languageIdbooleanSoniox's defaultIdentify the language being spoken.

cartesia

sttProvider: cartesia
sttConfig:
  model: ink-2
  language: en
KeyTypeIf omittedEffect
modelink-whisper or ink-2ink-whisperThe recognition model. Any other value is ink-whisper.
languagelanguagedetectThe language spoken.

elevenlabs

sttProvider: elevenlabs
sttConfig:
  language: en
  tagAudioEvents: false
KeyTypeIf omittedEffect
languagelanguagedetectThe language spoken.
tagAudioEventsbooleanElevenLabs' defaultMark non-speech sounds (laughter, music) in the transcript.

google

sttProvider: google
sttConfig:
  sttModel: telephony
  languages: [en-GB, de-DE]
  detectLanguage: false
  addPunctuation: true
  spokenPunctuation: false
  location: eu
  minConfidence: 0.6
  keywords:
    - { keyword: Elizon, boost: 5 }
KeyTypeIf omittedEffect
sttModellong, short, telephony, medical_dictation, medical_conversation, chirp, chirp_2, chirp_3, latest_long or latest_shortGoogle's defaultThe recognition model. Any other value is dropped.
languageslist of locales (en-GB) or English namesGoogle's defaultThe languages to expect.
detectLanguagebooleanGoogle's defaultDetect the language spoken.
addPunctuationbooleanGoogle's defaultPunctuate the transcript.
spokenPunctuationbooleanGoogle's defaultTurn spoken punctuation ("comma") into the mark.
locationstring, a Google Cloud location (global, eu, us-central1)Google's defaultWhere recognition runs. Lowercased.
minConfidencenumber, 0 to 1Google's defaultResults below this confidence are discarded.
keywordslist of { keyword, boost }noneWords to favour, each with a weight (boost, 1 when left out).

The Google credential is the operator's service account, set up in Studio; the Slot's apiKey is not used.

azure

sttProvider: azure
sttConfig:
  region: westeurope
  language: en-GB
  profanity: Masked
  segmentation: Semantic
  phraseList: [Elizon, impeller]
  explicitPunctuation: false
  trueTextPostProcessing: true
KeyTypeIf omittedEffect
regionstring, an Azure regionnoneThe region of the installer's Azure Speech resource.
languagelocale (en-GB) or English nameAzure's defaultThe language spoken.
profanityMasked, Removed or RawAzure's defaultHow profanity appears in the transcript.
segmentationstring, an Azure segmentation strategyAzure's defaultHow speech is split into phrases.
phraseListlist of stringsnoneWords and phrases to favour.
explicitPunctuationbooleanAzure's defaultTurn spoken punctuation into the mark.
trueTextPostProcessingbooleanAzure's defaultClean up the transcript (disfluencies, formatting).

ttsConfig

cartesia

ttsProvider: cartesia
ttsConfig:
  model: sonic-2
  language: en
  speed: 1
  volume: 1
  emotion: content
KeyTypeIf omittedEffect
voicestring, a Cartesia voice idCartesia's defaultLeave it out: Cartesia voice ids are UUIDs, which a Package cannot carry.
modelstring, a Cartesia model idsonic-3The voice model. A value containing a space is sonic-3.
languagelanguagedetectThe language spoken.
speednumberCartesia's defaultSpeaking speed.
volumenumberCartesia's defaultLoudness.
emotionstring, a Cartesia emotionneutralThe tone of voice (neutral, content, happy, …).

elevenlabs

ttsProvider: elevenlabs
ttsConfig:
  voice: 21m00Tcm4TlvDq8ikWAM # a voice id from ElevenLabs
  model: eleven_flash_v2_5
  stability: 0.5
  similarityBoost: 0.75
  style: 0
  speed: 1
  useSpeakerBoost: true
  latency: 1
  audioEncoding: PCM 16000Hz
  enableSsml: false
  preferredAlignment: Original
  dictionaries:
    - { dictionaryId: pd-product-names, versionId: v1 }
KeyTypeIf omittedEffect
voicestring, an ElevenLabs voice idElevenLabs' defaultThe voice.
modelstring, a model id or its name (Eleven Flash v2.5)eleven_multilingual_v2The voice model.
stabilitynumber, 0 to 1ElevenLabs' defaultHow steady the delivery is.
similarityBoostnumber, 0 to 1ElevenLabs' defaultHow closely the output keeps to the original voice.
stylenumber, 0 to 1ElevenLabs' defaultHow much style is exaggerated.
speednumberElevenLabs' defaultSpeaking speed.
useSpeakerBoostbooleanElevenLabs' defaultBoost similarity to the original speaker.
latencynumberElevenLabs' defaultStreaming latency optimisation level.
audioEncodingMP3 44.1kHz 128kbps, MP3 44.1kHz 192kbps, PCM 16000Hz, PCM 22050Hz, PCM 24000Hz or PCM 44100HzElevenLabs' defaultThe audio format. Any other value is dropped.
enableSsmlbooleanElevenLabs' defaultRead SSML tags in the text.
preferredAlignmentstring (Original, any case)originalWhich text word timings are aligned to.
dictionarieslist of { dictionaryId, versionId }nonePronunciation dictionaries to apply.

azure

ttsProvider: azure
ttsConfig:
  region: westeurope
  voice: en-GB-SoniaNeural
  sampleRate: PCM 24 KHz 16 bit
  voiceRate: 1
  volume: 50
  pitch: Medium
  style: Friendly
KeyTypeIf omittedEffect
regionstring, an Azure regionnoneThe region of the installer's Azure Speech resource.
voicestring, an Azure voice nameAzure's defaultThe voice.
sampleRatePCM 8 KHz 16 bit, PCM 16 KHz 16 bit, PCM 22.05 KHz 16 bit, PCM 24 KHz 16 bit, PCM 44.1 KHz 16 bit or PCM 48 KHz 16 bitAzure's defaultThe audio sample rate. Any other value is dropped.
voiceRatenumber, 0.5 to 2Azure's defaultSpeaking rate.
volumenumber, 0 to 100Azure's defaultLoudness.
pitchExtra Low, Low, Medium, High or Extra HighAzure's defaultPitch.
stylestring, an Azure speaking style (Friendly, Cheerful, …)noneThe speaking style. Neutral means none.

google

Google text-to-speech uses no credential from the Slot: the Slot's apiKey is not used, and the voice worker authenticates with its own Google credentials.

ttsProvider: google
ttsConfig:
  voice: en-GB-Neural2-A
  encoding: LINEAR16
  rate: 1
  pitch: 0
  volume: 0
KeyTypeIf omittedEffect
voicestring, a Google voice nameGoogle's defaultThe voice.
encodingLINEAR16, MP3, OGG_OPUS, MULAW or ALAWGoogle's defaultThe audio encoding. Any other value is dropped.
ratenumberGoogle's defaultSpeaking rate.
pitchnumberGoogle's defaultPitch, in semitones.
volumenumberGoogle's defaultVolume gain, in dB.

soniox

ttsProvider: soniox
ttsConfig:
  voice: Aria # a voice from Soniox
  model: tts-rt-v1 # a model id from Soniox
  language: en
  format: MP3
  sampleRate: 24 kHz
KeyTypeIf omittedEffect
voicestring, a Soniox voiceSoniox's defaultThe voice.
modelstring, a Soniox model idSoniox's defaultThe voice model. A value containing a space is dropped.
languagelanguageSoniox's defaultThe language spoken.
formatMP3 or PCM (WAV)Soniox's defaultThe audio format. Any other value is dropped.
sampleRatestring in kHz (24 kHz)Soniox's defaultThe audio sample rate.

callBehavior

Four sections, each optional. Nothing else in callBehavior is read: a greeting key, for example, does nothing. What callers hear first is callFlow.firstMessage.

callBehavior:
  callFlow:
    firstMessageMode: say
    firstMessage: Thanks for calling. This is an automated assistant — how can I help?
    userAwayTimeout: 20
    userAwayAction: hangup
    hangUpAwayTime: 30
    minConsecutiveSpeechDelay: 0.2
    preemptiveGeneration: true
    filterMarkdown: true
    filterEmoji: true
  timing:
    turnDetectionProvider: Multilingual Model
    unlikelyThreshold: 0.2
    minEndpointingDelay: 0.5
    maxEndpointingDelay: 2
  interruption:
    allowInterruptions: true
    minInterruptionDuration: 0.5
    minInterruptionWords: 1
    discardAudioIfUninterruptible: true
    falseInterruptionTimeout: 2
    resumeFalseInterruption: true
  sensitivity:
    vadProvider: silero
    minSpeechDuration: 0.05
    minSilenceDuration: 0.55
    prefixPaddingDuration: 0.5
    maxBufferedSpeech: 60
    activationThreshold: 0.5
    forceCpu: true

callFlow

KeyTypeIf omittedEffect
firstMessageModesay, generate or nonenonesay speaks firstMessage as written; generate has the Agent open the call, using firstMessage as its instructions.
firstMessagestringemptyThe opening line (or, with generate, the instructions for it). Nothing is said while it is empty.
userAwayTimeoutnumber, seconds15How long the caller can be silent before they count as away.
userAwayActionhangup, nothing, say or generatehangupWhat happens when the caller is away. say and generate need an away message the platform does not carry yet, so they do nothing.
hangUpAwayTimenumber, secondsnoneWith say or generate, how long to wait after the away message before hanging up. Since those two do nothing yet, this has no effect today.
minConsecutiveSpeechDelaynumber, seconds0The shortest pause between two things the Agent says.
preemptiveGenerationbooleanfalseStart the reply before the caller has finished, to answer faster.
filterMarkdownbooleantrueStrip Markdown from the text before it is spoken. Setting both this and filterEmoji to false does not turn stripping off: with neither, the worker falls back to stripping both.
filterEmojibooleantrueStrip emoji from the text before it is spoken. See filterMarkdown for setting both to false.

timing

KeyTypeIf omittedEffect
turnDetectionProviderAuto, STT, VAD, Realtime LLM, Manual, Multilingual Model or English ModelAutoHow the end of the caller's turn is detected. Auto lets the platform choose.
unlikelyThresholdnumber, 0 to 1noneBelow this end-of-turn likelihood, the Agent keeps waiting.
minEndpointingDelaynumber, seconds0.5The shortest wait after the caller stops before the Agent answers.
maxEndpointingDelaynumber, seconds3The longest wait, however unsure the turn detection is.

interruption

KeyTypeIf omittedEffect
allowInterruptionsbooleantrueWhether the caller can talk over the Agent.
minInterruptionDurationnumber, seconds0.5How long the caller must speak to interrupt.
minInterruptionWordsnumber0How many words the caller must say to interrupt.
discardAudioIfUninterruptiblebooleantrueDrop what the caller says while the Agent cannot be interrupted.
falseInterruptionTimeoutnumber, seconds2How long to wait before deciding an interruption was a false alarm.
resumeFalseInterruptionbooleantrueAfter a false alarm, carry on with what the Agent was saying.

sensitivity

KeyTypeIf omittedEffect
vadProvidersilero or builtinno separate detectorWhich voice activity detector listens for speech. Only silero builds one; with builtin or nothing set, the speech engine's own detection is used and the other sensitivity keys are ignored.
minSpeechDurationnumber, seconds0.05The shortest sound that counts as speech.
minSilenceDurationnumber, seconds0.55The silence that ends a stretch of speech.
prefixPaddingDurationnumber, seconds0.5Audio kept from just before speech starts.
maxBufferedSpeechnumber, seconds60The most speech held at once.
activationThresholdnumber, 0 to 10.5How confident the detector must be that a sound is speech.
forceCpubooleantrueRun the detector on the CPU.
  • recordCalls: true records every call. When it is on and consentMessage is not empty, callers hear the consent message first, before the firstMessage. With recording off, the consent message is never played.
  • validate and build do not check the pair. Write the message yourself whenever recordCalls is true; consentMessage: null means nothing is said.
  • In the install wizard, a Package that records calls shows the installer the consent message. They can edit it, and must confirm it is right before the Voice step is complete; the wizard will not finish, or let them skip the step, with an empty message. The install refuses a reviewed message that is empty (PORTABLE_DEFINITION_INVALID). A Package that does not record calls has no consent step.
  • An install with no wizard (from the CLI) has no one to review the message, so your wording is installed as you wrote it.

These rules are pinned by the wizard's tests (apps/web/src/components/packages/steps.test.ts, StepVoice.test.tsx) and the voice codec's (packages/contracts/src/packages/codec/capabilities.test.ts, 22.32-UNIT-003).

Recording and consent are legal decisions

The installer is shown your consent message and must confirm it's right for where their calls are recorded. The wizard won't set up recording with nothing said first. Write the message for the strictest jurisdiction you expect to be installed in.

SIP routing template

How the installer's inbound trunk handles a call: media encryption, which SIP headers it keeps, and noise cancellation. npx @elizon/cli example sip prints a complete phone-line Package built around this file.

sip/inbound.yaml
sipTrunkSlot: phone-line
direction: inbound
inbound:
  srtp: allow
  sipHeaders: x_only
  noiseCancellation: true
FieldMeaning
sipTrunkSlotThe sip-trunk Slot the installer binds to one of their inbound trunks. See the note below the table.
directionAlways inbound. See Inbound only.
inbound.srtpMedia encryption for the call audio. See srtp.
inbound.sipHeadersWhich SIP headers reach the call. See sipHeaders.
inbound.noiseCancellationtrue turns on noise cancellation for the caller's audio on the trunk; false leaves the audio as it is.

All three inbound fields are required, and no other field is accepted: validate and build refuse an unknown key, a value outside the tables below and a direction other than inbound, with PORTABLE_DEFINITION_INVALID at the field's path (for example sip.inbound.srtp).

sipTrunkSlot must be the id of a type: sip-trunk Slot declared in slots. Use the same one your inbound-call trigger names: validate and build check that the Slot is declared and is a sip-trunk Slot, not that it matches the trigger. They refuse any other id with PORTABLE_UNDECLARED_REFERENCE at sip.sipTrunkSlot: "Slot line is not declared in this Package." for an undeclared id, or "Slot reasoning is a llm Slot, not a sip-trunk Slot." for a Slot of another type. Copy the id from the trigger.

srtp

ValueWhat it doesWhen to pick it
disableCall audio is never encrypted (plain RTP).Only for a carrier that can't negotiate SRTP at all. Not recommended.
allowEncrypted and unencrypted calls are both accepted.Recommended when you don't know the installer's carrier; also a new trunk's setting in Studio.
requireOnly encrypted calls are accepted; an unencrypted one is refused.When the line handles sensitive calls and you're sure installers' carriers support SRTP.

The value is passed to the carrier, and becomes the media-encryption setting of a number's call route when that number is set up on the line (At install). require with a carrier that doesn't offer SRTP means calls never connect. The wizard's test inbound call won't catch this: it uses the trunk's current setting, and the template is applied only at Activate, so calls start failing after activation. Say in your Package's README that it needs an SRTP-capable carrier.

sipHeaders

ValueWhat it doesWhen to pick it
noneNo SIP headers reach the call.Recommended unless you need a header; also a new trunk's setting in Studio.
x_onlyOnly the custom X- headers reach the call.When the installer's carrier adds X- headers you want, such as a caller reference.
allEvery SIP header from the INVITE reaches the call.Rarely; it passes on the most data about the caller.

The value is applied to the number's call route (create, and every later refresh, such as the one at Activate); the wizard's test inbound call uses the trunk's current value. The headers you choose arrive on the caller's participant in the call room as sip.h.<header> attributes (for example sip.h.x-customer-id).

Available on the call, not read by the Agent

The headers are available as participant attributes, but the Agent and the voice configuration don't read them: nothing a Package defines can use them yet. Pick none unless you have a reason to change it.

Inbound only

direction has one value, inbound. There is no outbound routing template: an outbound trunk's settings (its SIP server, its transport) belong to the carrier account, so there is nothing a Package could carry. A Package can't place calls through a trunk of its own.

In the manifest

The voice configuration and the routing template from this page, wired together. npx @elizon/cli example sip prints the same wiring as a complete project, with its own file, Slot and trigger names.

elizon.yaml
entryPoint: agents.call-handler
agents:
  - name: call-handler
    ref: ./agents/call-handler.yaml
voice:
  ref: ./voice/after-hours-line.yaml
sip:
  ref: ./sip/inbound.yaml
slots:
  - { id: reasoning, type: llm, required: true }
  - { id: speech-in, type: stt, required: true, allowedProviders: [soniox] }
  - { id: speech-out, type: tts, required: true, allowedProviders: [cartesia] }
  - {
      id: phone-line,
      type: sip-trunk,
      required: true,
      description: The trunk your after-hours number rings on.,
    }
triggers:
  - id: after-hours-line
    type: inbound-call
    sipTrunkSlot: phone-line
    routing:
      ref: ./sip/inbound.yaml
  - id: run-manually
    type: manual
compatibility:
  requiredCapabilities: [voice, sip]
  • sip: points at the routing template. A Package has at most one.
  • The sip-trunk Slot is what the installer binds to their trunk. The template's sipTrunkSlot and every inbound-call trigger name it by id.
  • The inbound-call trigger is what makes a call start the Package. It takes sipTrunkSlot (a declared sip-trunk Slot, or validate refuses it with MANIFEST_TRIGGER_SLOT_UNRESOLVED) and routing.ref (the template). routing.ref must name the same file as sip.ref, because install applies only the sip: template: validate and build refuse a different file, or an inbound-call trigger in a Package with no sip:, with MANIFEST_INVALID_FIELD at triggers[<i>].routing.ref. See Triggers → inbound-call.
  • The entry point. Like every trigger, inbound-call fires the Package's one entryPoint. Unlike schedule and webhook, it doesn't need a Workflow: an Agent, a Team or a Workflow entry point is wired the same way. The call itself is answered by the voice configuration's agent, so the simplest Package makes that Agent the entry point, as above. The Triage demo uses a Workflow entry point instead.
  • Which voice configuration answers. The Package's own. At Activate, the bound number is routed to the Package's voice configuration, the same way Studio → Phone Configurations routes a number it adds. A number that already answers with another live voice configuration (one made in Studio, or by another Package) is not taken: that trigger is failed, and the installer removes the other routing first (see At install). A number that answers with this Package's own earlier voice configuration (from a previous version) is re-pointed.
  • requiredCapabilities must list voice and sip when the Package has an inbound-call trigger. validate and build refuse each one that is missing with MANIFEST_CAPABILITY_DISAGREEMENT at the trigger, and the install's Review step refuses a platform without telephony with PKG_MISSING_CAPABILITY.
  • A manual trigger lets the installer test the Package from Studio before any call arrives.

There's no field that could hold a carrier account, credential or number: not in the template, not in the Slot, not in the trigger. The installer supplies all three (see At install). The template, the sip-trunk Slot and the trigger accept only the fields above: validate refuses anything added to the Slot or the trigger (a number or trunk added to an inbound-call trigger gets a hint saying where it comes from), and build refuses anything added to the template. At install, a template that carries a vault reference, a secret-named field or an id is refused.

At install

The sip-trunk Slot binds to two things the installer already has:

  1. A trunk: one of their inbound SIP trunks (Studio → Phone Configurations), by its id. It must be ready: inbound, provisioned without error, with its inbound settings saved and, for a managed carrier, its carrier credentials linked. A trunk that isn't is refused with SLOT_BINDING_UNRESOLVED and the reason.
  2. An inbound phone number on that trunk, optional: the number the Package answers, in E.164 (+4930123456) or 7 to 15 digits. Without a number the trunk still binds, but no inbound-call trigger can be wired to it: the trigger stays not answering yet until a number is given.

The installer also supplies, before installing, everything the Package can't carry: the carrier account, its credentials, the trunk itself and the number (all set up in Studio → Phone Configurations), and the speech-provider accounts for the stt and tts Slots.

In the wizard, the SIP Inbound step offers the installer's ready inbound trunks and the number to answer. It then offers a test inbound call that confirms calls really reach Elizon before activation. A number that silently never rings is the worst failure a phone Package can have. At Activate, once an inbound-call trigger can be wired (a trunk and a number are bound):

  1. The routing template is written to the chosen trunk's inbound settings and the carrier step is re-run. Numbers on that trunk that are already set up get their call routes updated with the template's media encryption and noise cancellation. If one of them can't be updated, the error is shown on that number in Studio → Phone Configurations.
  2. The bound number is routed to the Package's voice configuration. A number with no call route gets one, with its own dispatch rule. A number that already has a route keeps it, and its dispatch rule is updated in place to answer with the Package's voice configuration, so it is never left without a route. A number already routed to the Package's voice configuration is left as it is.

The trigger is wired only when both steps worked. Otherwise it is failed with the reason, and the rest of the Package still activates. A trigger fails when:

  • the template can't be applied (the trunk is no longer one of the Organization's inbound trunks, for example);
  • the number isn't a number on the bound trunk (+… is not a number on the bound trunk);
  • the number already answers with another voice configuration (+… already answers with voice configuration <name>. Remove that routing first.). Nothing about that number is changed;
  • Elizon's SIP service can't set up the route. The error is stored on the number. A new route points the number at the Package's voice configuration but answers no calls yet; an existing route keeps answering with its old voice configuration.

To recover, fix the cause, then either:

  • in Studio → Phone Configurations, remove the number and add it again with the Package's voice configuration. That runs the same routing as Activate; or
  • apply an update of the Package, which wires its triggers again.

Activate runs once per installation, so activating again isn't one of the options.

A trunk bound without a number gets neither step. Apart from those call-route settings, nothing else about the trunk, the carrier account or the other numbers is changed: the other numbers keep the voice configuration they answer with. On uninstall, a number routed to the Package's voice configuration is un-routed and its call route and dispatch rule are removed. The number and the trunk stay.

From the CLI

npx @elizon/cli install ./my-package.pkg --slot.phone-line=<trunk-id> …
npx @elizon/cli packages bind <installation-id> --slot.phone-line=<trunk-id> --yes

A sip-trunk Slot takes --slot.<id>=<trunk-id>, where the trunk id is the trunk's id from Studio → Phone Configurations. The limits:

  • No number. The CLI value is the trunk id and nothing else, so a CLI binding carries no inbound number. The trunk binds, but the Package's inbound-call triggers are not wired, and the template's srtp, sipHeaders and noiseCancellation are never applied to the trunk. Bind the line in the wizard or on the Package's page in Studio, where you pick the number, if the Package has an inbound-call trigger.
  • defer (--slot.phone-line=defer) leaves the Slot for later. The Package installs as installed-incomplete and the trigger is not live until the Slot is bound.
  • The trunk id must be the id of a trunk in the target Organization at that scope. Anything else is refused with SLOT_BINDING_UNRESOLVED.

These rules are pinned by the CLI's binding tests (packages/cli/src/install/install.test.ts, 22.29-UNIT-048 and 22.29-INT-001; packages/cli/src/packages/packages-bind.test.ts, 22.46-CLI-001). See install and packages bind.

See Voice and SIP for a walkthrough.