mcpField
S
setup-sip-trunk

setup-sip-trunk

github.com/bolna-ai云与 DevOps364 次安装2 天前更新
代码仓库

关于 setup-sip-trunk

为 Bolna Agent 配置自带 SIP 中继(BYOT)的技能,涵盖中继、号码和入站路由的设置,以及入站和出站呼叫的 API 流程。

主要功能

  1. 01创建和管理 SIP 中继
  2. 02注册及管理 DID 号码
  3. 03将入站 DID 映射到 Agent
  4. 04配置出站呼叫路由
  5. 05设置传输与媒体加密

适用场景

  1. 01沿用现有运营商号码处理呼叫
  2. 02通过 SIP 中继发起出站呼叫
  3. 03将入站号码连接到 Bolna Agent

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/bolna-ai/skills --skill setup-sip-trunk

安装后在 Claude Code 中输入/setup-sip-trunk确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
plivo-zentrunk.md
twilio-elastic.md
scripts/
add_trunk_number.py
create_sip_trunk.py
diagnose_trunk.py

详细介绍

Bolna SIP 中继(BYOT)

使用任何符合标准的 SIP 中继——Twilio Elastic SIP、Plivo Zentrunk、Telnyx、Vonage、Zadarma、DIDWW 或你自己的运营商——处理由 Bolna Agent 接听和拨出的电话。

Beta。 SIP 中继需要企业版访问权限。如果 API 调用返回访问错误,请先联系 [email protected],再更改代码。

为什么使用 BYOT

原因详情
保留现有运营商关系无需携号转网,也不会产生并行账单。
协商费率Bolna 不会加价收取你的通话时长费用。
号码可携带性使用你已有的号码。
合规性/区域运营商当地法规要求使用特定运营商时必需。

高层级流程

1. Provider portal:    Whitelist 13.200.45.61, set origination URI to sip.bolna.ai
2. POST /sip-trunks/trunks                       → create trunk in Bolna
3. POST /sip-trunks/trunks/{id}/numbers          → register your DIDs on the trunk
4. PATCH /v2/agent/{id} telephony_provider=sip-trunk   (for outbound)
5. POST /inbound/setup                           → link DID ↔ agent (for inbound)
6. POST /call with from_phone_number = your DID  → outbound dial

步骤 0 — 在 SIP 提供商的门户中

将 Bolna 的 IP 加入白名单
13.200.45.61

将此项添加到提供商的允许 IP/ACL/可信 IP 列表中。否则,Bolna 的出站 INVITE 和 RTP 数据包会被丢弃。

对于 ip-based 身份验证,这也是中继用于识别 Bolna 的 IP。

设置始发 URI(用于入站)
中继传输方式始发 URI
UDP 或 TCPsip:sip.bolna.ai:5060
TLSsip:sip.bolna.ai:5061;transport=tls

如果提供商只接受 IP,请在 UDP/TCP 中使用 sip:13.200.45.61:5060。TLS 入站必须使用主机名,以便运营商验证 Bolna 的 TLS 证书。

可按每个 DID 分别设置,也可在整个中继上设置——具体取决于提供商。

编解码器

默认使用 G.711 ulaw。至少允许 ulaw(最好也允许 alaw)。避免使用 G.729 和其他压缩编解码器。

端点

方法路径用途
POST/sip-trunks/trunks创建中继
GET/sip-trunks/trunks列出中继
GET/sip-trunks/trunks/{trunk_id}获取一个中继
PATCH/sip-trunks/trunks/{trunk_id}更新中继
DELETE/sip-trunks/trunks/{trunk_id}删除中继
POST/sip-trunks/trunks/{trunk_id}/numbers添加 DID
GET/sip-trunks/trunks/{trunk_id}/numbers列出 DID
DELETE/sip-trunks/trunks/{trunk_id}/numbers/{phone_number_id}移除 DID
POST/inbound/setup将 DID 的 phone_number_id 映射到 Agent
POST/inbound/unlink取消映射

所有路径都位于 https://api.bolna.ai 下。身份验证:Authorization: Bearer $BOLNA_API_KEY。

示例:Twilio Elastic SIP(userpass)

curl -X POST https://api.bolna.ai/sip-trunks/trunks \
  -H "Authorization: Bearer $BOLNA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Twilio Production",
    "provider": "twilio",
    "description": "Main Twilio Elastic SIP trunk",
    "auth_type": "userpass",
    "auth_username": "<your-sip-username>",
    "auth_password": "<your-sip-password>",
    "gateways": [
      { "gateway_address": "your-trunk.pstn.twilio.com", "port": 5060, "priority": 1 }
    ],
    "transport": "transport-udp",
    "allow": "ulaw,alaw",
    "disallow": "all",
    "inbound_enabled": true,
    "outbound_leading_plus_enabled": true
  }'

响应中包含中继 id。请保存。

示例:Plivo Zentrunk(ip-based)

curl -X POST https://api.bolna.ai/sip-trunks/trunks \
  -H "Authorization: Bearer $BOLNA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Plivo Zentrunk",
    "provider": "plivo",
    "auth_type": "ip-based",
    "gateways": [
      { "gateway_address": "21467306465797919.zt.plivo.com", "port": 5060, "priority": 1 }
    ],
    "ip_identifiers": [
      { "ip_address": "15.207.90.192/31" },
      { "ip_address": "204.89.151.128/27" },
      { "ip_address": "13.52.9.0/25" }
    ],
    "transport": "transport-udp",
    "inbound_enabled": true
  }'

ip_identifiers 是运营商的出口 IP。Plivo、Telnyx 等会公布这些 IP。

示例:TLS + SDES(加密媒体)

适用于支持信令和媒体加密的运营商:

curl -X POST https://api.bolna.ai/sip-trunks/trunks \
  -H "Authorization: Bearer $BOLNA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Twilio Production (encrypted)",
    "provider": "twilio",
    "auth_type": "userpass",
    "auth_username": "<u>",
    "auth_password": "<p>",
    "gateways": [
      { "gateway_address": "your-trunk.pstn.twilio.com", "port": 5061, "priority": 1 }
    ],
    "transport": "transport-tls",
    "media_encryption": "sdes",
    "media_encryption_optimistic": false,
    "inbound_enabled": true
  }'
参数作用
transport: "transport-tls"加密 SIP 信令。端口为 5061。
media_encryption: "sdes"使用 SDP 交换密钥的 SRTP。需要 TLS 传输。
media_encryption_optimistic: true如果运营商不提供加密,则回退到普通 RTP。适用于测试。

你的运营商也必须在其一端启用 SDES/SRTP——否则,SIP 呼叫虽能建立,但媒体无法建立(通话无声)。

向中继添加 DID 号码

curl -X POST "https://api.bolna.ai/sip-trunks/trunks/$TRUNK_ID/numbers" \
  -H "Authorization: Bearer $BOLNA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "phone_number": "919876543210",
    "name": "Mumbai Support Line"
  }'

响应中包含 phone_number_id——这是进行入站映射时要使用的 ID。请保存。 Bolna 会原样存储号码字符串;入站匹配时查找可有可无 +,但请保持一致。

从中继拨打出站电话

更新 Agent,使 Bolna 通过你的中继路由:

curl -X PATCH "https://api.bolna.ai/v2/agent/$AGENT_ID" \
  -H "Authorization: Bearer $BOLNA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"agent_config":{"telephony_provider":"sip-trunk"}}'

然后照常拨打电话——from_phone_number 必须是已在中继上注册的 DID:

curl -X POST https://api.bolna.ai/call \
  -H "Authorization: Bearer $BOLNA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id": "'$AGENT_ID'",
    "recipient_phone_number": "+918800001234",
    "from_phone_number": "+919876543210"
  }'

呼入中继的电话

注册 DID 后,将其映射到 Agent:

curl -X POST https://api.bolna.ai/inbound/setup \
  -H "Authorization: Bearer $BOLNA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "agent_id": "'$AGENT_ID'",
    "phone_number_id": "'$PHONE_NUMBER_ID'"
  }'

Bolna 会自动将 Agent 的音频格式设为 ulaw,以符合通过 SIP 路由的呼叫对 Asterisk 的要求。

一个号码对应一个 Agent。 将 DID 重新映射到新的 Agent 时,会自动取消其与之前 Agent 的映射。若要在不重新映射的情况下解除关联,请使用相同的请求体调用 POST /inbound/unlink。

创建中继字段参考

字段类型必填默认值备注
namestring是—账户内唯一。
providerstring是—twilio、plivo、telnyx、vonage、custom 等。
descriptionstring否null内部使用。
auth_typestring是—userpass 或 ip-based。
auth_username / auth_passwordstring有条件必填—当 auth_type == "userpass" 时必填。
gateways[]array是—一个或多个 {gateway_address, port, priority}。
ip_identifiers[]array有条件必填[]当 auth_type == "ip-based" 时必填。包含 {ip_address} 列表。
allowstring否"ulaw,alaw"以逗号分隔的编解码器。始终包含 ulaw。
disallowstring否"all"以逗号分隔的编解码器。
transportenum否"transport-udp"transport-udp、transport-tcp、transport-tls。
media_encryptionenum否"no"no 或 sdes。sdes 需要 transport-tls。
media_encryption_optimisticbool否false如果运营商不提供加密,则回退到未加密的 RTP。
inbound_enabledbool否false开启后可接收来电。
outbound_leading_plus_enabledbool否true拨出时在号码前添加 +。部分运营商会拒绝 +。
direct_mediabool否false保持为 false。
rtp_symmetricbool否trueNAT 所必需。
force_rportbool否trueNAT 所必需。
qualify_frequencyint否60SIP OPTIONS ping 的间隔秒数;0 表示禁用。
phone_numbers[]array否[]创建时可选添加的初始 DID。

故障排除

呼入通话已接通,但只有单向音频或没有音频

最常见的原因:Bolna 与运营商之间 SRTP 不匹配。

  • 运营商已禁用 SRTP,但 Bolna 上的 media_encryption: "sdes" → 设置 media_encryption: "no",或调整运营商设置使其一致。
  • 快速测试:media_encryption_optimistic: true 会回退到未加密的 RTP。
  • 在通话建立正常前完全跳过加密:transport-udp + media_encryption: "no"。
422 media_encryption='sdes' requires transport='transport-tls'

SDES 密钥通过 SDP 传输,因此需要加密信令。可以:

  • 将 transport 切换为 transport-tls(并将网关上的 port: 5061),或
  • 设置 media_encryption: "no"。
呼出 INVITE 一直响铃 / 在某个运营商上无提示地失败

UDP 分片。运营商在 INVITE 中添加了较大的标头(较长的 Diversion、多个 Route、P-Asserted-Identity),导致 UDP 数据包超过 MTU。

解决方法:transport: "transport-tcp"。无需使用 TLS — 单独使用 TCP 即可避免分片。

完全没有呼入通话

按以下顺序逐项检查:

  1. 运营商上的 Origination URI 是否设置为 sip:sip.bolna.ai:5060(或 :5061;transport=tls)?
  2. 是否通过 POST /sip-trunks/trunks/{id}/numbers 将 DID 添加到了中继?
  3. 中继上的 inbound_enabled: true 是否已设置?
  4. 是否通过 POST /inbound/setup 将 DID 映射到 Agent?
  5. 运营商是否已将 Bolna IP 13.200.45.61 加入允许名单?
  6. INVITE 的 Request-URI 或 To 标头是否与存储的号码格式匹配(带 + 或不带 +)?
呼出时 from_phone_number 被拒绝
  • from_phone_number 必须是已注册到中继的 DID(/sip-trunks/trunks/{id}/numbers)。
  • Agent 的 telephony_provider 必须更新为 sip-trunk。
  • 中继上的 is_active: true。
  • 部分运营商会拒绝拨出号码前导的 + — 请切换 outbound_leading_plus_enabled 以匹配运营商要求。
userpass 身份验证失败

重新检查运营商门户中的 SIP 凭据 — 它们与账户凭据分开。Twilio Elastic SIP 使用专门用于 SIP REGISTER 身份验证的 “Credential List”。

安全

删除中继会级联删除其网关、IP 标识符和号码映射。活跃的呼入和呼出将立即停止。执行 DELETE /sip-trunks/trunks/{id} 前,务必先征得用户确认。

深入了解

文件内容
references/twilio-elastic.mdTwilio Elastic SIP 端到端设置,包含运营商侧的准确界面截图。
references/plivo-zentrunk.mdPlivo Zentrunk 设置,包括 ip_identifiers。
scripts/create_sip_trunk.py封装 POST /sip-trunks/trunks。
scripts/add_trunk_number.py封装 POST /sip-trunks/trunks/{id}/numbers。
scripts/diagnose_trunk.py读取中继、号码和活动映射,用于排查问题。

另请参阅

  • setup-inbound — DID 到 Agent 的映射(对 Bolna 托管的 DID 和 SIP 中继 DID 采用相同方式)。
  • make-call — 出站 API;telephony_provider 为 sip-trunk 时,工作方式相同。
  • manage-phone-numbers — Bolna 托管的 DID(BYOT 的替代方案)。
  • https://raw.githubusercontent.com/bolna-ai/skills/main/references/india-compliance.md — 即使使用自己的中继,您的号码仍须满足 DLT 要求。

评论

支持 Markdown