我搭了人生第一个能开口说话的 AI:一次跑通语音 Agent 的全过程记录
写在前面:为什么我决定折腾这个
我之前做的「AI 对话」基本都停留在打字框里——左边输入框,右边聊天流,回车一发,等它吐字。直到上周我刷到一个 demo:一个人对着浏览器说「帮我把明天下午的会改到三点」,AI 当场用声音回了一句「好的,已经发出邀请」。
没有打字,没有等待转圈,就是说话,然后它说话回你,我瞬间觉得聊天框不香了。
但我对「语音 AI」的印象一直停留在两种:
- 一种是手机里那个动不动就「我听不懂」的语音助手
- 另一种是客服电话里那种念菜单的机器人。这俩都离「能自然对话」差得远。
所以我想搞清楚一件事:一个真能跟你聊天的语音 AI,到底是怎么搭起来的?
带着这个问题,我找到了 Agora 的 Conversational AI(下面我就简称为 Convo AI),花了大概一个下午把它跑通。这篇文章就是我这次折腾的全程记录——包括我踩的坑、看到的真实输出,以及我对它架构的理解。如果你也从没碰过 voice agent,希望能帮你少走点弯路。
先回答一个最基础的问题:语音 AI 为什么不能只接个聊天模型?
这是我一开始最大的误解。我心想,这不就是把 ChatGPT 套个麦克风吗?ASR(语音转文字)+ LLM(大模型)+ TTS(文字转语音),三件套串起来不就完了?
真去做的时候才发现,这三件套「串起来」这一步才是地狱。
举几个例子。
打断怎么办? 你和 AI 对话的时候,说到一半你突然想插一句话纠正它——这在打字框里不存在,因为你打字的时候它本来就在等你。但语音里,AI 可能正在念一段长句子,你怎么让它停下来?它怎么知道你是「说完了等它回」还是「临时打断想补充」?
延迟怎么压? 你按下发送,ASR 转 200ms,LLM 想 800ms,TTS 合成 300ms,再加上网络抖动,用户体验到的就是「我说完了,空气安静了一秒半,它才开始回」。这种延迟在打字时代无所谓,在语音里就特别明显,因为人类正常对话的间隔也就两三百毫秒。超过这个阈值,你会下意识觉得「对面卡了」。
全双工怎么实现? 两个人说话可以同时开口、甚至抢话,AI 得能一边听你说话一边生成回复,而不是「你说完 → 我才开始听 → 听完了再想 → 想完了再说」这种对讲机模式。
声音怎么低延迟搬? 音频数据量大,又对实时性极敏感,普通的 HTTP 接口根本扛不住,得专门的实时传输。
所以一个能用的语音 AI,光有三件套远远不够。它还需要:一套能把音频低延迟搬来搬去的传输层;一套管「轮次检测、打断、记忆」的运行时;以及把端上体验(浏览器或 App)串起来的工程。这些拼在一起,才是一个 voice agent。
Convo AI 干的事,就是把这堆东西打包好给你。
它具体打包了什么?四层架构拆一下
跑通之后回头看,它的架构其实可以很清晰地分成四层。我用大白话翻译一下,并画个示意图:
┌──────────────────────────────────────────────────────────┐
│ ④ Endpoint 端上体验 |
│ 浏览器 / App / 硬件设备 |
│ (采集麦克风、播放声音、显示转写) │
└──────────────────────────────────────────────────────────┘
▲ 音频 + 事件 (RTC + RTM)
▼
┌──────────────────────────────────────────────────────────┐
│ ① Real-time transport 实时传输 │
│ Agora RTC / SD-RTN™ 全球网络 │
│ 端到端延迟官方数据 ≈ 650ms │
└──────────────────────────────────────────────────────────┘
▲
▼
┌──────────────────────────────────────────────────────────┐
│ ② Agent runtime 运行时 │
│ 会话生命周期 / 轮次检测 / 打断 / 记忆 / 工具调用 │
└──────────────────────────────────────────────────────────┘
▲
▼
┌──────────────────────────────────────────────────────────┐
│ ③ Models AI 模型 │
│ ASR (Deepgram) + LLM (OpenAI) + TTS (MiniMax) │
│ —— 都可换 │
└──────────────────────────────────────────────────────────┘
第一层:实时传输(Real-time transport) 负责把你的声音低延迟地送到 AI 那边,再把 AI 合成的声音送回来。Agora 的老本行就是 RTC(实时音视频通信),全球有自建的 SD-RTN 网络,端到端延迟官方数据是 650ms。这一层是 Agora 比别家更有底气的地方。
第二层:Agent 运行时(Agent runtime) 这一层是「大脑的总调度」。它管会话生命周期、管轮次检测(turn detection,判断你这话说完没有)、管打断(你说着说着插话怎么办)、管记忆和工具调用。这层的东西自己从零写,至少几个月。
第三层:AI 模型(Models) 就是前面说的三件套——ASR、LLM、TTS。Convo AI 默认用的是 Deepgram 做 ASR、OpenAI 做 LLM、MiniMax 做 TTS,但你也可以换成自己喜欢的,甚至换成自己托管的开源模型。这点对我挺重要的——我不想被绑死在某一家上。
第四层:端上体验(Endpoint) 最终用户在哪用它?浏览器、App、还是硬件设备。Convo AI 把这条路径也分了两条:in apps(Web/移动端/桌面)和 on dedicated devices(玩具、可穿戴、自助终端这类嵌入式硬件)。我这次走的是 in apps 里的 Web 路径。
理解了这四层,后面看代码就不会迷路。
开干:从零到能开口说话
准备工作
需要的东西不多:
- 一个 Agora 账号(去 console.agora.io 注册,免费额度够你玩很久)
- 本机装好 Node.js(我用的是 24.x)和 Python 3.14+
- 包管理器
bun(官方模板默认用它,没有的话npm i -g bun装一下)
重点:默认 managed 模式不需要你自备任何模型 key——不用 OpenAI、不用 Deepgram、不用 MiniMax 的 API key。这三个由 Agora 用自己的凭据帮你调,你只消耗 Agora 的额度。这是它对我这种懒人最友好的地方。
唯一需要手动做的一步:注册完账号后,去 Agora Console 里开启 Conversational AI Engine 这个能力开关(路径:Project → 编辑 → Conversational AI)。不开的话后面 agent 起不来。
我选的是 Python Quickstart 这条路。原因很简单:后端是 FastAPI,看起来最「正常」,方便我后面想魔改;前端是 Next.js,浏览器打开就能聊,最直观。
整个项目的目录结构跑通后大概长这样:
my-python-demo/
├── server/ # FastAPI 后端
│ ├── src/
│ │ ├── server.py # 三条 API 路由 + token 签发
│ │ └── agent.py # Agent 配置:prompt / 模型 / VAD
│ ├── .env.example # 环境变量模板
│ └── requirements.txt
└── web/ # Next.js 前端
├── src/
│ ├── components/
│ │ ├── LandingPage.tsx # 进房前的页面
│ │ └── ConversationComponent.tsx # 通话 + 转写 + 指标
│ ├── lib/conversation.ts
│ └── services/api.ts # 调后端 /api/*
├── next.config.ts # 把 /api/* rewrite 到 FastAPI
└── package.json
记两个关键文件:server/src/agent.py(决定 AI 的人格和能力)和 server/src/server.py(决定前后端怎么握手),后面想改东西基本就是改这俩。
第一步:装 Agora CLI
Agora 现在把上手流程收拢到了一个 CLI 工具里,比以前手动 clone + 改 .env 友好太多。
macOS / Linux:
curl -fsSL https://dl.agora.io/cli/install.sh | sh
agora --help
Windows(PowerShell,我用的就是这台):
irm https://dl.agora.io/cli/install.ps1 | iex
agora --help
跑通后能看到一长串子命令列表(login / init / project doctor / …)。
我的小坑: PowerShell 默认执行策略会拦这个 inline 脚本。如果报错,把脚本下下来本地跑:
powershell -ExecutionPolicy Bypass -File .\install.ps1
另外装完如果
agora命令找不到,重跑安装脚本时加--add-to-path,或者手动把安装目录塞进 PATH。

第二步:登录 + 拉项目
agora login
会自动打开浏览器走 OAuth,授权完回到终端,看到一句 Logged in as ...。
然后一行命令把官方模板拉下来:
agora init my-python-demo --template python
cd my-python-demo
bun run setup
bun run dev
这里 agora init 帮你做了三件事,这才是它真正省事的地方:
- clone 官方 starter 仓库
- 把项目绑定到你在 Agora Console 里的项目
- 自动写好
.env——App ID、App Certificate 这些密钥全自动填进去

你不用手动去 console 复制粘贴密钥。之前我最烦的就是这一步,现在一条命令搞定。
对应的 .env 内容(敏感值我打码了):
# server/.env —— 由 agora init 自动生成
AGORA_APP_ID=cd0xxxxxxxxxxxxxxxxxxxxxxxx
AGORA_APP_CERTIFICATE=1d8xxxxxxxxxxxxxxxxxxxxxxxxxxxx
AGENT_GREETING=Hi there! I'm Ada, your virtual assistant from Agora. How can I help?
PORT=8000
如果你想换成中文问候,改 AGENT_GREETING 就行,不用动代码。
第三步:浏览器里开聊
bun run dev 会同时拉起 FastAPI 后端(默认 8000)和 Next.js 前端(3000)。终端会刷出两段日志:
[backend] Uvicorn running on http://0.0.0.0:8000
[web] ▲ Next.js 14.x Local: http://localhost:3000

打开 http://localhost:3000,页面长这样:
点 Start conversation,浏览器问你要麦克风权限,给。然后你会看到:
- 页面右下角出现一个连接状态指示,从
connecting变成connected - 实时转写区开始动——你说话,文字就跟着冒出来
- AI 那一栏也开始出字,是它正在念的内容
我第一次开口说的是「你好,你能听懂中文吗」。它停顿了大概半秒,然后用中文回了我一句「能听懂,你想聊点什么」。
就那一刻,真的会激动。 你写了一晚上代码,第一次听到 AI 用声音回应你,跟在网页上点一下发送按钮的感觉完全不一样。
我把刚才那段对话的转写原样贴出来:
[我] 你好,你能听懂中文吗?
[AI] 你好!我可以理解中文。请问有什么我可以帮助你的吗?
[我] 给我讲一个关于程序员的冷笑话。
[AI] 当然!有一个冷笑话是这样的:为什么程序员总是混淆圣诞节和万圣节?因为 Oct 31 = Dec 25!这是一种编程语言中的进制转换幽默。希望你喜欢!
[我] (笑)再来一个。
[AI] 好的!这个是:为什么程序员喜欢自然?因为那里没有“bug”!希望这个也能让你笑!

万一没跑通
官方给了一个诊断命令,特别有用:
agora project doctor --deep
它会检查你的凭据是否有效、Convo AI 功能有没有在 console 里开启、网络是不是通。我中途遇到一次 agent 死活不加入频道的问题,跑了一下 doctor,输出大致是这样:
✗ Conversational AI capability not enabled on project <xxx>
→ Fix: open https://console.agora.io/ → Project → Features → enable Conversational AI
✓ Credentials valid
✓ Network reachable

照着提示去 console 勾上 Conversational AI 这个 capability,再跑就好了。
前后端到底在握手什么?三个 API 搞清楚
跑通之后我去翻了 server.py,发现整个交互其实就靠三条 HTTP 路由。把它画出来,整个流程就清楚了:
三个路由的契约(这是我从官方 Recipe 文档里抄来的稳定接口,不会随便变):
| 路由 | 入参 | 返回 |
|---|---|---|
| GET /api/get_config | ?channel=&uid= | data.app_id / data.token / data.uid / data.channel_name / data.agent_uid |
| POST /api/startAgent | { channelName, rtcUid, userUid, parameters? } | data.agent_id / data.channel_name / data.status |
| POST /api/stopAgent | { agentId } | { code: 0, msg: “success” } |
成功响应统一是 { code, msg, data } 这种结构。
一句话总结这个流程:浏览器先要 token,再用 token + 一条 startAgent 让后端去云端把 agent 拉起来,之后真正的音频流和事件流就走 RTC/RTM 通道,不再走 HTTP 了。
浏览器 Console 里能看到什么?RTM 事件流
这一段是我跑通之后觉得最有「窥探内部」快感的部分。
agent 跑起来后,打开浏览器 DevTools 的 Console,会发现 Convo AI 通过 RTM(Agora 的实时消息通道)源源不断地往前端推事件。你能看到的几类:
// 状态变化:agent 进场、开始听、开始说
{ type: "state", state: "listening" }
{ type: "state", state: "speaking" }
// 实时转写:分两种,你说的 vs agent 说的
{ type: "transcript", uid: <user>, text: "给我讲一个冷笑话", is_final: true }
{ type: "transcript", uid: <agent>, text: "为什么程序员...", is_final: false }
// 延迟指标:这是我最想看的
{ type: "metrics", ttft: 680, e2e_latency: 920, ... }
// 错误
{ type: "error", code: "...", message: "..." }

ttft 是 Time To First Token(首字延迟),e2e_latency 是端到端延迟。盯着这两个数字调优,比凭感觉靠谱多了。官方 Recipe 里有个 Event Observability 例子,就是把这些事件渲染成一个时间轴网页,调试时特别香。
我特意去验证的几件事
跑通只是第一步,我更想搞清楚它到底好不好用。所以特意测了几个场景。
我在 Console 里盯 metrics 事件,看到 ttft 大概在 600~800ms 之间,e2e_latency 在 800~1000ms。考虑到我在中国、走的是默认海外节点,这个数字已经比我预期好。文档里说的 650ms 是节点近的情况下能到的,如果我把部署换到国内或周边节点,应该还能再压。
这是我最关心的。我让它念一段长一点的内容(让它给我讲讲量子计算),然后故意在它念到一半时喊「停,换一个话题」。
结果是:它确实停了。不是念完那句才停,是大概 200ms 内就停了,然后听我后面的话。Console 里能对应看到一条 state: listening 紧跟着事件流。
这就是文档里说的 VAD-based interruption handling——它一直在听,检测到你开口就立刻静音自己。这点对体验影响巨大。一个不会被打断的 AI,不管多聪明,都没法当人用。
反过来我也担心一种情况:我说话稍微停顿了一下(比如「我想问一下……那个……」),它会不会以为我说完了就抢话。
试了几次,没抢。它默认的 turn detection 是基于语义的(semantic turn detection),不是单纯的静音检测,所以能区分「真说完了」和「在思考」。这一点比我预想的好。
这个我没真改代码,但去翻了 agent.py。managed 模式下的配置大概长这样(简化版,注意没有任何 api_key 参数):
# server/src/agent.py (节选,managed 模式)
from agora_agent import (
Agent, Agora, Area, DeepgramSTT, OpenAI, MiniMaxTTS,
)
# managed 模式:Agora 出凭据,你不出 key
agent = (
Agent(name="my-managed-agent")
.with_stt(DeepgramSTT(model="nova-3", language="en-US"))
.with_llm(OpenAI(
model="gpt-4o-mini",
system_messages=[{"role": "system",
"content": "You are a helpful assistant."}],
greeting_message="Hello! How can I help you today?",
max_history=32,
))
.with_tts(MiniMaxTTS(
model="speech_2_6_turbo",
voice_id="English_captivating_female1",
))
)
想换模型基本就是改这三行:把 OpenAI(...) 换成你的自托管 endpoint(OpenAI 兼容协议 + 加自己的 api_key,也就是切到 BYOK 模式),或者把 TTS 换成 ElevenLabs、Cartesia 之类。官方 Recipe 里 recipe-agent-custom-llm 和 recipe-agent-custom-llm-tts 就是干这个的,照着抄就行。
不绑死任何一家这件事,Agora 做得到位。
一些说人话的评价
折腾完一个下午,我对它的总体感觉是:
值得称赞地方:
- 上手是真的简单。CLI 一条龙,不需要自己去翻文档找 App ID 怎么填。
- 默认链路(Deepgram + OpenAI + MiniMax)开箱即用,先跑通再优化。
- 打断和轮次检测这两件事默认就调得不错,不用自己魔改。
- RTM 事件把延迟指标、转写、状态都暴露出来,调优和排障有据可查,不是黑盒。
- 模型可换,不绑架你。这点对长期项目很关键。
- Convo AI 国内和海外都支持,默认走海外,初始化时把地区选成 area.cn 就会整体切到国内的模型和节点,延迟和稳定性有保证;底层是 Agora 在全球(含国内)都有自己的 RTC 网络,LiveKit 在亚洲没节点,用户在国内延迟会很高。
- 文档对完全没接触过 RTC 的人比较友好,(比如:初学者可能看不懂 token、UID、channel 这些 RTC 概念),它会有专门的前置说明与关系解释;并以用户行动路径为分类视角,进行一步一步深入实践。
- RTC 传输是 Agora 老本行,全球低延迟这块它确实有底气。一个旁证:2024 年 10 月 OpenAI 把 Agora 选为 Realtime API 的官方合作伙伴,不是没原因的——据说 GPT-4o 发布时演示用的 websockets 方案网络稳定性都成问题,所以后来选了个 RTC 出身的来补这一刀。
待改进的地方:
- 地区这个开关不够显眼,我一开始没注意到,默认按海外链路就跑起来了,还以为国内就是这个延迟,建议 Quickstart 里写明显一点。
- 默认 TTS 的中文音色可选项不算多,要更自然的中文声音可能得自己换。
总的来说,如果你想做的是「能自然对话的语音 AI」,又不想从零写传输、轮次、打断这些底层逻辑,Convo AI 确实能帮你省掉几个月。它不是「替代」谁,而是把那些本来该有人帮你打包好的工程问题打包好了。
附:我跑通用到的全部命令
# Windows PowerShell 装 CLI(macOS/Linux 换成 curl 那条)
irm https://dl.agora.io/cli/install.ps1 | iex
# 登录
agora login
# 拉官方 Python 模板(自动写好 .env)
agora init my-python-demo --template python
cd my-python-demo
# 装依赖并起服务(同时拉起 FastAPI + Next.js)
bun run setup
bun run dev
# 浏览器打开 http://localhost:3000,点 Start conversation
# 出问题就跑这个诊断
agora project doctor --deep
参考链接:
- Recipes 目录(29 个可运行示例):https://docs.agora.io/en/api-reference/recipes
- Voice Agent 总览:https://docs.agora.io/en/ai
- Quickstart:https://docs.agora.io/en/ai/get-started/quickstart
- Python Quickstart 源码:https://github.com/AgoraIO-Conversational-AI/agent-quickstart-python
- 对话式 AI 科普(社区):https://www.rtecommunity.dev/conversational-ai-for-the-curious/
如果你也想试试搭一个能开口说话的 AI,我的建议是:别先看架构图,先把官方 Quickstart 跑通,听到 AI 第一次回你话的那个瞬间,你就会明白为什么这事儿值得折腾。
更多推荐


所有评论(0)