内容
# livekit-agent-simulator
<div align="center">
<img src="lk_sim_illustration.webp" alt="lks — livekit-agent-simulator: black-box LiveKit agent tests with WebRTC, Inbound, Outbound" width="720">
</div>
<div align="center">


[](https://opensource.org/licenses/MIT)
[](https://github.com/quangdang46/livekit-agent-simulator/actions/workflows/ci.yml)
[](https://github.com/quangdang46/livekit-agent-simulator/releases)
</div>
**使用 LiveKit 语音代理模拟器与 AI 模拟呼叫者对任何 LiveKit 语音代理进行模拟,并保持完整的法医日志。**
独立 MCP 服务器 + 命令行界面(`lks`,别名:`lk-sim`)。黑盒测试:无需导入被测试的代理,无需编辑其代码或 `.env` 文件。
<div align="center">
<h3>快速安装</h3>
```bash
curl -fsSL "https://raw.githubusercontent.com/quangdang46/livekit-agent-simulator/main/install.sh?$(date +%s)" \
| bash -s -- --verify
```
</div>
### 通过编码代理安装(复制粘贴)
将以下内容粘贴到 Claude Code、Cursor、Codex、AmpCode、Windsurf 或任何编码代理 **到您要测试的仓库中:**
```text
按照以下说明安装和配置 livekit-agent-simulator(命令行界面:lks):
https://raw.githubusercontent.com/quangdang46/livekit-agent-simulator/main/docs/guide/installation.md
目标项目根目录是当前工作空间。使用绝对 --root 路径。安装便携式命令行界面如果丢失,运行 lks init,帮助填充 .agent-sim/config.yaml 文件,使用本地环境或询问 LiveKit + Gemini + agent_name,确保 .agent-sim 被 gitignore,运行预飞行测试,并在语音代理工作器未运行时停止执行。不要在 .agent-sim/ 外编辑代理应用程序源代码。
```
同样的想法,一行命令:
```text
按照以下说明安装和配置 livekit-agent-simulator:https://raw.githubusercontent.com/quangdang46/livekit-agent-simulator/main/docs/guide/installation.md
```
---
## 快速概览
### 问题
语音代理在单元测试中无法发现问题:
| 问题 | 缺失内容 |
|-----|----------------|
| 没有真正的呼叫者 | 脚本永远不会中断、停滞或切换语言 |
| 仅限聊天评估 | 没有房间事件、音频时间或工具范围 |
| 手动 QA 调用 | 不具备 CI 可复制性,没有结构化的 PassCriteria |
| 代理耦合的测试框架 | 测试在重构工作器时会中断 |
### 解决方案
**livekit-agent-simulator** 通过三种传输模式(`Caller.mode`)驱动 Gemini Live 人格,从场景 JSONL 中观察转录 / 工具 / 流 / 房间事件,并编写带有时间戳的报告,您可以回放。
| 界面 | 您获得的内容 |
|---------|--------------|
| `lks` 命令行界面 | init → 预飞行测试 → 执行 → 报告 → 网页 |
| MCP 服务器 | 与 Claude Code、Cursor、Codex 等具有相同的操作 |
| 传输模式 | `webrtc_sim` · `inbound_sip` · `outbound_human_pickup` · `outbound_sim_callee` (可选 `agent_dials`) |
| 报告 | `events.jsonl`、`timeline.md`、`summary.json`,可选立体声 WAV |
| 评判器 | 可选的 LLM PassCriteria 评分 |
### 为什么使用 lks?
| 功能 | 它能做什么 |
|---------|--------------|
| **黑盒调度** | 只需要 `agent_name` + LiveKit 凭证 |
| **5 种传输模式** | WebRTC · 入站 SIP · 出站人机对接 · 出站模拟被叫 · agent_dials |
| **场景 JSONL** | 人格、呼叫者、电信、执行、脚本、PassCriteria、调度 |
| **法医日志** | 每回合事件存储在 SQLite + `reports/<run-id>/` |
| **报告播放器** | 本地网页 UI:音频 + 转录同步 |
| **命令行界面 ↔ MCP 对等性** | 一个 `ops` 层 — 无需重复运行路径 |
| **便携式软件包** | 下载安装程序;无需为用户安装 uv/pip |
---
### 快速示例
```bash
# 安装一次
curl -fsSL "https://raw.githubusercontent.com/quangdang46/livekit-agent-simulator/main/install.sh?$(date +%s)" \
| bash -s -- --verify
# 在要测试的仓库中(语音代理工作器必须已运行)
lks init --root /path/to/target
# 编辑 /path/to/target/.agent-sim/config.yaml(LiveKit + Gemini 密钥,agent_name)
lks preflight --root /path/to/target
lks execute smoke-hello --root /path/to/target
lks report <run-id> --root /path/to/target
lks web --root /path/to/target # Ctrl+C 停止
```
---
## 设计理念
1. **被测试的代理是一个黑盒。**
我们永远不会导入或修补目标应用程序代码。调度元数据是不透明的 JSON。
2. **通用核心,目标所有配置。**
语言、时区、主题和业务字符串属于目标的 `.agent-sim/` — 而不是硬编码在软件包中。
3. **命令行界面和 MCP 的操作层相同。**
`execute_*` 验证然后运行。没有“运行 vs 执行”的分叉。
4. **法医日志优先于印象。**
每次运行都会生成结构化事件,您可以 `比较`、`日志` 和回放。
5. **CI 友好型检查点。**
状态 / 断言 / 脚本严格失败;可选的严格评判器用于较软的 LLM 评分。
---
## 工作原理
```text
1. 读取 <target>/.agent-sim/config.yaml
2. 从场景 Caller.mode 中选择 SimLeg(webrtc_sim | inbound_sip | outbound_human_pickup | outbound_sim_callee | agent_dials)
3. 连接腿 → LiveKit 房间(s)/ SIP 交叉点(如果需要);Gemini 保留在模拟房间中的 WebRTC
4. 桥接音频;观察转录、工具、时间、打断
5. 写入 reports/<run-id>/ + runs.sqlite
6. 可选的 LLM 评判 vs PassCriteria
```
```text
Caller.mode(场景)
┌───────────────┬────────────────┬──────────────────┬────────────────────┐
│ webrtc_sim │ inbound_sip │ outbound_human_pickup │ outbound_sim_callee│
│ 房间音频 │ 模拟拨打 DID │ 人机对接 → │ Gemini SIP 被叫者 │
│ │ │ Gemini 共存│ (2 房间交叉点) │
└───────┬───────┴────────┬───────┴────────┬─────────┴─────────┬──────────┘
│ │ │ │
└────────────────┼────────────────┼───────────────────┘
▼
┌──────────────────────────┐
│ Gemini Live 人格 │
│ + LiveKit 代理(黑 │
│ 盒测试) │
└────────────┬─────────────┘
│ 观察
▼
reports/<run-id>/ · runs.sqlite · judge
```
模式详细信息和配置:[docs/telephony.md](docs/telephony.md)。模板:`inbound-caller-sim`、`outbound-human-pickup`、`outbound-callee-sim`。
---
## 比较
| 方法 | 真实房间 | AI 呼叫者 | 法医日志 | MCP | 黑盒 |
|----------|-----------|-----------|--------------|-----|-----------|
| 手动电话 QA | ✅ | ❌ | ❌ | ❌ | ✅ |
| 单元 / 模拟 STT | ❌ | ❌ | 部分 | ❌ | ❌ |
| 仓库内代理测试 | ⚠️ | ⚠️ | 变化 | ❌ | 通常耦合 |
| **lks** | ✅ LiveKit | ✅ Gemini Live | ✅ 完整 | ✅ | ✅ |
**何时使用 lks:**
- LiveKit 语音代理的回归测试套件
- 代理驱动的 CI / 编码代理工作流(MCP)
- 调试语音代理的转接、工具和沉默,无需阅读代理源代码
**何时可能不理想:**
- 没有 LiveKit 房间的纯文本聊天机器人
- 没有 LiveKit + Gemini API 访问的离线环境
---
## 安装
### 快速安装(推荐)
**仅下载 — 您的机器上无需 uv/pip/build。** CI 构建了一个便携式软件包(嵌入式 Python + 依赖项 + 报告播放器)。
```bash
# macOS / Linux
curl -fsSL "https://raw.githubusercontent.com/quangdang46/livekit-agent-simulator/main/install.sh?$(date +%s)" \
| bash -s -- --verify
```
```powershell
# Windows PowerShell
irm "https://raw.githubusercontent.com/quangdang46/livekit-agent-simulator/main/install.ps1" -OutFile "$env:TEMP\lk-sim-install.ps1"
powershell -NoProfile -ExecutionPolicy Bypass -File "$env:TEMP\lk-sim-install.ps1" -Verify
```
也可以从发布资产中获取:
```bash
curl -fsSL "https://github.com/quangdang46/livekit-agent-simulator/releases/download/v0.1.0/install.sh" \
| bash -s -- --verify
```
| 标志 | 用途 |
|------|---------|
| `--verify` | 校验和验证 |
| `--ref v0.1.0` | 固定发布标签 |
| `--no-mcp` | 跳过 MCP 注册到编码工具 |
| `--uninstall` | 删除安装 |
默认情况下,安装程序将 MCP 服务器 `livekit-agent-simulator`(`lks mcp`)注册到检测到的工具中:Claude Code、Cursor、Cline、Windsurf、VS Code Copilot、Gemini CLI、Amazon Q、OpenCode、Codex、Warp。
**面向代理的安装手册(长格式):** [docs/guide/installation.md](docs/guide/installation.md)
用于粘贴到代理中的原始 URL:
`https://raw.githubusercontent.com/quangdang46/livekit-agent-simulator/main/docs/guide/installation.md`
### 从源代码(维护者/贡献者)
```bash
git clone https://github.com/quangdang46/livekit-agent-simulator.git
cd livekit-agent-simulator
uv sync --extra dev
uv run lks --help
```
需要 **Python 3.10–3.13**。
### Web UI(维护者)
用户永远不会构建此内容 - CI 将 `web/dist` 打包到轮子中作为 `web_static`。源代码:`web/`。
```bash
pnpm --dir web install
pnpm --dir web build # → web/dist/ (由 Hatch 附加到 uv build)
pnpm --dir web dev # HMR;代理 /api + /runs → lks web :8765
```
参见 `web/README.md`。
---
## 快速入门
```bash
# 代理工作器必须运行并注册到 LiveKit
lks guide
lks init --root /path/to/target
# 填写 .agent-sim/config.yaml
lks preflight --root /path/to/target
lks scenario-init smoke-hello --root /path/to/target # 如果需要
lks validate smoke-hello --root /path/to/target
lks execute smoke-hello --root /path/to/target
lks runs --root /path/to/target
lks report <run-id> --root /path/to/target
lks web --root /path/to/target
```
### 最小场景(`smoke-hello`)
```jsonl
{"apiVersion":"agent-sim/v1","kind":"Scenario","metadata":{"id":"smoke-hello","locale":"en-US","tags":["smoke"]}}
{"kind":"Persona","spec":{"name":"Alex","brief":"首次通话者;确认您到达正确的位置,然后礼貌地结束。","goals":["听代理","说您将回电"],"style":"polite, brief"}}
{"kind":"Execute","spec":{"max_turns":2,"timeout_s":90,"first_speaker":"user"}}
{"kind":"PassCriteria","spec":{"criteria":["代理响应了呼叫者","代理用呼叫者的语言响应"]}}
```
可选的多裁判 PassCriteria:`judges[]` + `mode`(`all` \| `majority` \| `any`)。断言高亮显示(`tool_order`、`constraint_respected`,恢复/延迟):`lks guide`。
完整的脚手架 JSONL 中的单行 `//` 注释是指南 - 运行时忽略它们。
---
## 配置
目标数据存储在 `<target>/.agent-sim/`(**gitignored**)。由 `init` 创建。
| 部分 | 必须 | 用途 |
|---------|----------|---------|
| `livekit.url` | 是 | `wss://…` LiveKit 云或自托管 |
| `livekit.api_key` / `api_secret` | 是 | 服务器 API 凭证 |
| `livekit.agent_name` | 是 | 必须与调度器名称匹配 |
| `livekit.dispatch_metadata` | 否 | 默认不透明 JSON **字符串** 所有运行 |
| `simulator.google_api_key` | 是 | Gemini 模拟呼叫者(+ 评判器) |
| `simulator.voice.model` / `voice` / `language` | 否 | 默认值:flash-live,Puck,`en-US` |
| `judge.model` | 否 | 如果设置 + PassCriteria → 运行后 LLM 评判 |
| `observe.record_audio` | 否(默认 `true`) | 本地立体声 WAV(L=sim,R=agent);无 Egress |
| `observe.data_topics` | 否 | 空 = 所有主题 |
| `observe.tool_event_patterns` | 否 | 映射数据有效载体 → 工具启动/结束/错误 |
参见模板:[`templates/config.yaml`](templates/config.yaml)。消费者特定线路:[`docs/portability.md`](docs/portability.md)。
---
## 命令
CLI 和 MCP 共享相同的公共操作(`ops.py`)。首选 `execute`(验证然后运行)。
| CLI | MCP 工具 | 用途 |
|-----|----------|---------|
| `init` | `init_project` | 搭建 `.agent-sim/` + gitignore |
| `guide` | `guide` | 安装/操作指南(markdown) |
| `web` | `web` | 本地报告播放器 |
| `preflight` | `preflight` | 配置 + LiveKit 连接性 |
| `scenarios` | `list_scenarios` | 列出 `scenarios/*.jsonl` |
| `plugins` | `list_plugins` | 验证 plugins |
| `cues` | `list_cues` | 内置 + 本地 PCM 提示 |
| `validate` | `validate_scenario` | 模式 + 语法检查 |
| `export` | `export_scenario` | 解析场景 JSON |
| `scenario-init` | `init_scenario` | 搭建 JSONL 并附带 // 指南 |
| `execute` | `execute_scenario` | 验证然后运行一个场景 |
| `execute-all` | `execute_scenarios` | 批量(ID/标签) |
| `execute-dict` | `execute_scenario_dict` | 内存场景字典 |
| `status` | `get_run_status` | SQLite 运行状态 |
| `log` | `get_run_log` | 过滤 `events.jsonl` |
| `report` | `get_run_report` | 摘要 + 结果 + 路径 |
| `compare` | `compare_runs` | 差异对比两项运行; `--baseline` 严格失败延迟/断言/恢复 |
| `runs` | `list_runs` | 运行历史 |
| `mcp` | — | 启动 MCP 服务器(stdio) |
```bash
lks execute smoke-hello --root /path/to/target
lks execute-all --tag smoke --root /path/to/target
lks log <run-id> --root /path/to/target
lks compare <run-a> <run-b> --root /path/to/target
lks compare <baseline> <candidate> --baseline --root /path/to/target
lks web --port 8765 --root /path/to/target
```
每个 MCP 工具都需要 `project_root` **除了** `guide`。
### MCP 配置示例
安装程序在检测到工具时写入此内容。手动 Cursor:
```json
{
"mcpServers": {
"livekit-agent-simulator": {
"command": "lks",
"args": ["mcp"],
"env": {}
}
}
}
```
开发检查(软件包未全局安装):
```json
{
"mcpServers": {
"livekit-agent-simulator": {
"command": "uv",
"args": ["run", "--directory", "/abs/path/livekit-agent-simulator", "lks", "mcp"]
}
}
}
```
等效的一行命令:`lks-mcp`(别名:`lk-sim-mcp`; 与 `lks mcp`/`lk-sim mcp` 相同)。
---
## 架构
```text
src/livekit_agent_simulator/
├── cli.py / mcp_server.py # 薄表面
├── ops.py # 共享公共操作
├── run_orchestrator.py # 房间生命周期 + 运行
├── scenario.py # JSONL 解析/验证
├── config.py # .agent-sim/config.yaml
├── preflight.py
├── asserts.py / suite.py # CI 门控
├── gemini/ # 实时呼叫者 + 评判器
├── livekit/ # 房间,调度,观察
├── audio/ · script/ · plugins/
└── web/ # 报告播放器服务器
```
| 层级 | 角色 |
|-------|------|
| 目标 `.agent-sim/` | 配置,场景,报告,本地插件/提示 |
| 软件包 `templates/` | 脚手架默认值 + 内置提示 |
| LiveKit | 房间,调度,数据主题,转录 |
| Gemini Live | 模拟呼叫者语音 + 可选评判器 |
---
## CI / 发布
| 工作流 | 触发器 | 它执行的操作 |
|----------|---------|--------------|
| [CI](.github/workflows/ci.yml) | PR / 推送到 `main` | 网页 UI 构建,`pytest`(3.10 + 3.12),`lks --help` |
| [发布](.github/workflows/release.yml) | 标签 `v*` | pytest → 轮子 → 便携式软件包(win/linux/mac)→ GitHub 发布 |
```bash
# 本地检查
uv sync --extra dev
pnpm --dir web build
uv run pytest -q
# 发布(1.0 前可能强制重新标记单个 0.1.0)
git tag v0.1.0
git push origin v0.1.0
```
---
## 故障排除
### `preflight` 连接性失败
```bash
lks preflight --root /path/to/target
# 确认 livekit.url / api_key / api_secret 以及项目是否可达。
# 跳过 API 检查,同时编辑配置:
lks preflight --no-connectivity --root /path/to/target
```
### 代理从未加入房间
- 工作进程必须 **运行** 并使用相同的 `livekit.agent_name` 注册。
- 如果冷启动缓慢,请增加 `livekit.agent_join_timeout_ms`。
- 如果您的代理需要调度元数据,请检查调度元数据是否为有效的 JSON **字符串**。
### Gemini / 模拟器身份验证错误
在 `.agent-sim/config.yaml` 中设置 `simulator.google_api_key`。模拟呼叫者使用 Gemini Live(默认情况下为 `gemini-3.1-flash-live-preview`)。
### 报告播放器中没有音频
启用 `observe.record_audio`(默认 `true`):`reports/<run-id>/conversation.wav`
```bash
lks web --root /path/to/target
```
### MCP 工具未列出
```bash
lks mcp # 必须是主机启动的
# 或重新安装而不使用 --no-mcp
curl -fsSL "https://raw.githubusercontent.com/quangdang46/livekit-agent-simulator/main/install.sh?$(date +%s)" \
| bash -s -- --verify
```
### 场景验证错误
```bash
lks validate my-case --root /path/to/target
lks scenario-init my-case --root /path/to/target # 新建脚手架并附带 // 指南
```
---
## 限制
### lks 还不能做什么(尚无)
- **不是代理框架** — 它测试代理;它不实现业务工具
- **不是离线优先** — 需要 LiveKit + Gemini(或配置的后端)
- **不是负载生成器** — 每轮一个模拟呼叫者(批量通过 `execute-all`)
### 已知限制
| 功能 | 当前状态 | 备注 |
|------------|---------------|-------|
| 黑盒调度 | ✅ | 仅限不透明元数据 |
| 多呼叫者房间 | ❌ | 单个模拟参与者 |
| 非 Gemini 呼叫者后端 | ⚠️ | Gemini Live 是受支持的路径 |
| 像素级 ASR 评分 | ❌ | 使用 PassCriteria + 评判器/断言 |
| 配置中的机密 | ⚠️ 在 gitignored YAML 中粘贴 | 不要提交 `.agent-sim/` |
---
## 常见问题
### 它会修改我的代理仓库吗?
仅搭建 **`.agent-sim/`**(gitignored)。它不会编辑代理源代码。
### CLI 与 MCP — 我应该使用哪一个?
相同的操作。使用 CLI 在终端/CI 中;MCP 在编码代理中使用。更喜欢 `execute_*` 而不是 ad-hoc 运行路径。
### 如何传递项目特定的调度字段?
`livekit.dispatch_metadata` 或场景 `Dispatch.spec.metadata` 作为不透明的 JSON 字符串。核心不解析消费者键。参见 [`docs/portability.md`](docs/portability.md)。
### 我可以断言工具调用吗?
是的 — `Assert.spec.tools`、`**tool_order**`(需要 `tool.start` 子序列)、`observe.tool_event_patterns`、Script/assert 插件和/或 PassCriteria + judge。参见 [`docs/plugins.md`](docs/plugins.md) 和 `lks guide`。
### 报告存储在哪里?
`<target>/.agent-sim/reports/<run-id>/` 加上 `.agent-sim/` 下的 `runs.sqlite`。
### 报告播放器是独立的吗?
否 — `lks web` 从安装包中提供预建的播放器。维护人员从 `web/` 构建。
---
## 文档
| 文档 | 何时 |
|-----|------|
| [AGENTS.md](AGENTS.md) | 适用于此软件包的 AI 代理规则 |
| [docs/smoke-test.md](docs/smoke-test.md) | 第一次端到端运行 |
| [docs/portability.md](docs/portability.md) | 消费者调度 / 观察设置 |
| [docs/plugins.md](docs/plugins.md) | 验证插件 + Python API |
| [docs/telephony.md](docs/telephony.md) | SIP 模式 + outbound_sim_callee 预检 |
| [docs/interrupt-scenario-matrix.md](docs/interrupt-scenario-matrix.md) | Barge / backchannel / noise 编写 |
| `lks guide` | 按需设置/运维指南(Assert,比较 --baseline,PassCriteria) |
---
## 关于贡献
请不要误解,我不接受我任何项目的外部贡献。我没有精神空间来审查任何内容,而且我的名字与项目相关,所以我对它可能引起的问题负责;因此,从我的角度来看,风险回报高度不对称。我还必须担心其他“利益相关者”,对于我免费制作的工具来说,这似乎不明智。您可以提交问题,甚至如果您想说明拟议的修复程序,请提交 PR,但请知道我不会直接合并它们。相反,我会让 Claude 或 Codex 通过 `gh` 审查提交内容,并独立决定是否以及如何解决它们。特别是错误报告,欢迎提交。抱歉这可能会冒犯,但我想避免浪费时间和伤害感情。我理解这与寻求社区贡献的盛行开源精神不符,但这是我保持当前速度并保持理智的唯一方法。
---
## 许可证
[MIT](./LICENSE)
---
<div align="center">
**黑盒 LiveKit 代理测试。真实房间。法医报告。**
</div>
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器