news 2026/9/7 8:25:37

OpenMontage 中基于 ElevenLabs + Twilio 的语音 Agent 外呼实践:agents 技能 outbound-calls 参考文档详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
OpenMontage 中基于 ElevenLabs + Twilio 的语音 Agent 外呼实践:agents 技能 outbound-calls 参考文档详解

OpenMontage 中基于 ElevenLabs + Twilio 的语音 Agent 外呼实践:agents 技能 outbound-calls 参考文档详解

【免费下载链接】OpenMontageWorld's first open-source, agentic video production system. 12 production pipelines, 100+ tools, 700+ agent skill and production-knowledge files. Turn your AI coding assistant into a full video production studio.项目地址: https://gitcode.com/GitHub_Trending/op/OpenMontage

本文围绕 OpenMontage 仓库中 outbound-calls.md 参考文档展开,系统讲解如何通过 ElevenLabs 语音 Agent 平台结合 Twilio 集成发起外呼电话:从前置条件、最小调用示例,到请求参数、响应结构、逐通电话的配置覆盖(Agent/TTS/电话配置/动态变量)与批量外呼完整示例。读完本文,你可以在 OpenMontage 的 agent 技能体系下,独立编写并调试一条「AI 主动拨打电话」的完整链路,并理解每个覆盖项在平台配置中的对应关系。

文档定位:agents 技能的外呼参考页

outbound-calls.md是仓库 agents 技能(ElevenLabs Agents Platform)的参考文档之一,与 installation.md、agent-configuration.md、client-tools.md 并列存放于references/目录。技能主文件SKILL.md的 frontmatter 声明了该技能的运行前提:需要联网访问和ELEVENLABS_API_KEY环境变量(见 SKILL.md 元数据)。

该文档的主题很明确:让已在 ElevenLabs 平台配置的语音 Agent,通过 Twilio 电话线路主动拨出电话,并支持在每次外呼时临时覆盖 Agent 的问候语、语言、语音音色以及注入动态变量。仓库中.claude/skills/目录下存在同名镜像文档 outbound-calls.md,内容保持一致,方便不同 AI 编程助手(Claude Code、Codex 等)读取同一套技能知识。

前置条件

发起外呼前需要满足三个条件(引自原文档 Prerequisites 一节):

  1. 一个已配置好的 ElevenLabs Agent——可通过 CLI 创建并推送:
    npm install -g @elevenlabs/cli elevenlabs auth login elevenlabs agents init elevenlabs agents add "My Assistant" --template complete elevenlabs agents push
  2. 一个绑定到该 Agent 的 Twilio 电话号码——需要从 ElevenLabs 控制台获取agent_phone_number_id
  3. ElevenLabs API Key——在 OpenMontage 中,该密钥对应根目录 .env.example 中的ELEVENLABS_API_KEY变量(位于 "Voice" 分组,用于 TTS 旁白、音乐生成等语音能力),SDK 与 cURL 请求均以此密钥认证。

SDK 安装方式(引自 installation.md):

  • Pythonpip install elevenlabs
  • JavaScript/TypeScriptnpm install @elevenlabs/elevenlabs-js。文档特别强调旧版elevenlabsnpm 包(v1.x)已弃用,不应再使用;
  • cURL:将密钥放入环境变量后,通过xi-api-key请求头传递。

最小调用:Python、JavaScript 与 cURL

outbound-calls.md的 Basic Usage 一节将三语言的最小示例指向主技能文件的 Outbound Calls 章节(原文档中的局部相对链接../SKILL.md#outbound-calls,此处转换为仓库根路径 SKILL.md),其代码如下:

Python

response = client.conversational_ai.twilio.outbound_call( agent_id="your-agent-id", agent_phone_number_id="your-phone-number-id", to_number="+1234567890", call_recording_enabled=True ) print(f"Call initiated: {response.conversation_id}")

JavaScript

const response = await client.conversationalAi.twilio.outboundCall({ agentId: "your-agent-id", agentPhoneNumberId: "your-phone-number-id", toNumber: "+1234567890", callRecordingEnabled: true, });

cURL(直接调用 REST API)

curl -X POST "https://api.elevenlabs.io/v1/convai/twilio/outbound-call" \ -H "xi-api-key: $ELEVENLABS_API_KEY" -H "Content-Type: application/json" \ -d '{"agent_id": "your-agent-id", "agent_phone_number_id": "your-phone-number-id", "to_number": "+1234567890", "call_recording_enabled": true}'

从三组示例可以推断,SDK 的conversational_ai.twilio.outbound_callconversationalAi.twilio.outboundCall均是对POST /v1/convai/twilio/outbound-call这一端点的封装:Python 用 snake_case 参数名,JavaScript 用 camelCase,请求体字段则与下表中的参数名一致。

请求参数

外呼接口接受以下参数(原文档 Request Parameters 表完整保留):

参数类型必填说明
agent_idstringElevenLabs Agent 的 ID
agent_phone_number_idstring绑定到该 Agent 的 Twilio 电话号码 ID
to_numberstring被叫号码,必须为 E.164 格式(如+1234567890
conversation_initiation_client_dataobject覆盖本次通话的会话设置(详见下文)
call_recording_enabledboolean是否允许 Twilio 录制通话
telephony_call_configobject电话呼叫设置,如振铃超时时间

两个必填参数构成了外呼的「主叫身份」:agent_id决定谁(哪个 Agent 人设)来打电话,agent_phone_number_id决定用哪条 Twilio 线路呼出;to_number采用 E.164 国际号码格式(国家码 + 号码,不含空格与连字符)。

响应结构

调用成功后返回如下 JSON(原文档 Response 一节):

{ "success": true, "message": "Call initiated successfully", "conversation_id": "conv_abc123", "callSid": "CA1234567890abcdef" }
字段类型说明
successboolean呼叫是否成功发起
messagestring状态信息
conversation_idstringElevenLabs 侧的会话 ID,用于后续追踪会话
callSidstringTwilio 侧的 Call SID,可用于在 Twilio 侧查询呼叫状态

注意响应里同时保留了两个体系的标识:conversation_id归属于 ElevenLabs Conversational AI 会话体系,callSid归属于 Twilio 呼叫体系。这意味着外呼链路上存在两个可追踪的句柄——前者用于追踪 Agent 对话内容与工具调用,后者用于查询传统电话侧的状态(如未接、忙线)。

自定义单通电话:conversation_initiation_client_data

原文档 Customizing the Call 一节的要点是:通过conversation_initiation_client_data可以为单次外呼临时覆盖 Agent 的默认设置,而不会修改 Agent 本身。下面完整保留原文档的 Python 与 JavaScript 示例:

Python

response = client.conversational_ai.twilio.outbound_call( agent_id="your-agent-id", agent_phone_number_id="your-phone-number-id", to_number="+1234567890", call_recording_enabled=True, conversation_initiation_client_data={ "conversation_config_override": { "agent": { "first_message": "Hello! This is a reminder about your appointment tomorrow.", "language": "en" }, "tts": { "voice_id": "JBFqnCBsd6RMkjVDRZzb" } }, "dynamic_variables": { "customer_name": "John", "appointment_time": "2:00 PM" } } )

JavaScript

const response = await client.conversationalAi.twilio.outboundCall({ agentId: "your-agent-id", agentPhoneNumberId: "your-phone-number-id", toNumber: "+1234567890", callRecordingEnabled: true, conversationInitiationClientData: { conversationConfigOverride: { agent: { firstMessage: "Hello! This is a reminder about your appointment tomorrow.", language: "en", }, tts: { voiceId: "JBFqnCBsd6RMkjVDRZzb", }, }, dynamicVariables: { customer_name: "John", appointment_time: "2:00 PM", }, }, });

conversation_initiation_client_data的结构分两部分:conversation_config_override覆盖conversation_config中的对应小节(示例中覆盖了agenttts),dynamic_variables则是本次通话注入的键值对。对照 agent-configuration.md 中conversation_config的完整结构(agentttsasrturnconversationvad等小节),可以推断覆盖对象与 Agent 配置使用的是同一套字段命名——即你在 Agent 控制台配置过的字段,都可以在单通电话级别做临时替换。

配置覆盖项详解

Agent 设置

选项类型说明
first_messagestring本次通话的自定义开场白
languagestring语言代码(如enesfr
promptobject覆盖 Agent 的 prompt 与 LLM 设置

其中prompt对应 Agent 配置中的 LLM 设置(system prompt、模型、温度等),结构详见 agent-configuration.md 的 prompt 章节;覆盖后仅对当前通话生效。

TTS 设置

选项类型说明
voice_idstring本次通话使用的语音 ID
stabilitynumber语音稳定性(0.0–1.0)
similarity_boostnumber音色相似度增强(0.0–1.0)
speednumber语速倍率

这几个字段与 Agent 级 TTS 配置同构。参考 agent-configuration.md 中给出的默认值作为调试基准:stability默认0.5(越低越富表现力)、similarity_boost默认0.8(越高越贴近原音色)、speed默认1.0(有效范围约 0.7–1.2)。示例中的JBFqnCBsd6RMkjVDRZzb是 ElevenLabs 预置音色 "George" 的 ID,与技能主文件 SKILL.md 列出的常用音色 一致。

电话呼叫配置

选项类型说明
ringing_timeout_secsinteger对被叫振铃多久后放弃,默认60

该配置位于telephony_call_config参数(请求参数表中的object类型项)之下,属于 Twilio 线路层行为:被叫未接听时,达到该秒数后呼叫被放弃。批量外呼场景下可按业务调整(例如营销提醒类可缩短以节省线路资源,重要通知类可保持默认)。

动态变量

通过dynamic_variables向 Agent 的 prompt 注入自定义数据,在 prompt 中用{{variable_name}}语法引用。例如把customer_nameappointment_time传入后,Agent 的开场白模板即可渲染出「John,您明天下午 2:00 有一个预约」。

原文档还提到一个sanitize选项:在动态变量赋值时,若开启该选项,赋值内容会在送入 LLM 和会话转录(transcript)之前从工具响应中剔除,但变量赋值本身照常完成。

字段类型默认说明
sanitizebooleanfalsetrue时,赋值内容在发送到 LLM/转录前从工具响应中移除,但仍参与变量赋值

这一设计的用途很具体:当工具响应里携带敏感值(例如完整的账号或账单明细),你可以只让变量拿到该值用于后续逻辑,而不让原始响应文本进入 LLM 上下文与通话记录,从而降低敏感信息在转录中的暴露面。

完整示例:批量个性化外呼

原文档 Complete Example 一节给出了一段可直接运行的 Python 代码:遍历客户列表,为每位客户发起一通携带个性化开场白与动态变量的外呼,并做基本的错误处理。完整保留如下:

from elevenlabs import ElevenLabs client = ElevenLabs() # Make personalized outbound calls customers = [ {"name": "Alice", "phone": "+1234567890", "balance": "$150.00"}, {"name": "Bob", "phone": "+0987654321", "balance": "$75.50"}, ] for customer in customers: try: response = client.conversational_ai.twilio.outbound_call( agent_id="payment-reminder-agent", agent_phone_number_id="your-phone-number-id", to_number=customer["phone"], call_recording_enabled=True, conversation_initiation_client_data={ "conversation_config_override": { "agent": { "first_message": f"Hello {customer['name']}, this is a friendly reminder about your account." } }, "dynamic_variables": { "customer_name": customer["name"], "balance": customer["balance"] } } ) print(f"Called {customer['name']}: {response.conversation_id}") except Exception as e: print(f"Failed to call {customer['name']}: {e}")

这段代码覆盖了外呼的三个关键实践点:

  • 一人一话术:用 f-string 把customer['name']写进first_message,同时用dynamic_variablesbalance等字段交给 Agent 的 prompt 模板,两者互补——开场白立即个性化,后续对话中 Agent 也能引用动态变量;
  • 失败隔离:逐通try/except,单个号码失败不影响批量任务继续;
  • 可追踪:成功时打印conversation_id,后续可用它回查该通电话的会话数据;配合响应中的callSid,还可以在 Twilio 侧核对线路状态。

错误处理方面,技能主文件 SKILL.md 归纳了平台常见错误码:401(密钥无效)、404(资源不存在,如agent_idagent_phone_number_id写错)、422(配置非法)、429(限流)。批量外呼时建议把 429 单独识别并做退避重试。

在 OpenMontage 仓库中如何找到这份文档

  • 技能入口:.agents/skills/agents/SKILL.md 的 "Outbound Calls" 章节给出三语言最小示例,并在末尾以「configuration overrides and dynamic variables」为由指向本文档;
  • 参考文档目录references/下按主题拆分——安装(installation)、Agent 配置全量字段(agent-configuration)、客户端工具(client-tools)、外呼(outbound-calls)、网页组件嵌入(widget-embedding),便于按需检索;
  • 多助手镜像.claude/skills/agents/references/下存有同套文档副本,例如 outbound-calls.md,内容一致;
  • 密钥配置:仓库根目录 .env.example 提供ELEVENLABS_API_KEY占位项,实际使用时在本地.env中填入真实密钥即可,SDK 会优先读取该环境变量。

需要再次强调的前提:外呼能力依赖 ElevenLabs 平台的 Twilio 集成与真实电话线路,agent_phone_number_id必须在 ElevenLabs 控制台为 Agent 绑定后取得;本文涉及的接口行为、参数与默认值均以当前仓库文档为准。

【免费下载链接】OpenMontageWorld's first open-source, agentic video production system. 12 production pipelines, 100+ tools, 700+ agent skill and production-knowledge files. Turn your AI coding assistant into a full video production studio.项目地址: https://gitcode.com/GitHub_Trending/op/OpenMontage

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/7 8:25:10

迪奥720同款颜色口红一件代发,色差才是工厂生死线

来我办公室聊“口红色号定制”的,十个里有八个拿的是社交平台高光滤镜图,一问要哑光还是滋润,当场愣住。做红棕调不是截图就能做出来的,更不是把色粉往蜡里一搅就完事。色号做得像不像,涂上嘴十分钟见真章;…

作者头像 李华
网站建设 2026/9/7 8:24:08

MMD技术进阶:从虹膜收缩特效到完整3D动画工作流

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/7 8:23:31

JAVA第四课

跟日记本一起学JAVA!相信你可以的,加油~本课闯关内容:1.照猫画虎(0/5)2.熟悉基础知识(0/6????)———————————————————————————————————…

作者头像 李华
网站建设 2026/9/7 8:21:55

极端武力雷霆风暴未开刃战术直刀赏鉴:M390与61HRC硬核设计解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华