在上一章中,我们通过 OpenAI Realtime API 建立了一条高性能的“语音-语音”交互管道,解决了“听得清”和“说得快”的问题。然而,真正的智能座舱不仅需要耳聪目明,更需要一个逻辑清晰、分工明确的“大脑”来处理复杂的车主需求。
本章将聚焦于 OpenAI Agents SDK 的应用。在车载环境中,试图用单一的 Prompt 和数百个工具(Tools)来解决所有问题是不可行的——这会导致上下文污染、高延迟和安全隐患。因此,我们需要构建一个 多代理(Multi-Agent)系统。
本章学习目标:
在车载场景中,我们推荐使用 星型(Star) 或 Hub-and-Spoke 拓扑结构,而不是网状结构。
[ User Audio Stream ]
|
v
+-------------------+
| OpenAI Realtime |
| API |
+---------+---------+
| (Function Call Event)
v
+---------------------------------------------------------------------------------+
| AGENTS SDK RUNTIME ENV |
| |
| +------------------+ Handoff (Transfer) +------------------+ |
| | | --------------------------------> | Vehicle Control | |
| | Supervisor | | Agent | |
| | (Router) | <-------------------------------- | (High Safety) | |
| | | Result / Handoff Back +------------------+ |
| +--------+---------+ |
| | |
| | Handoff +------------------+ |
| +-----------------------> | RAG Knowledge | |
| | | Agent | |
| | <---------------------- | (High Latency) | |
| | +------------------+ |
| | |
| | Handoff +------------------+ |
| +-----------------------> | GUI Service | |
| | Agent | |
| | (Stateful) | |
| +------------------+ |
+---------------------------------------------------------------------------------+
| 角色 | 职责 (Responsibilities) | 典型工具 (Tools) | 上下文策略 |
|---|---|---|---|
| Router (Supervisor) | 意图分类、全局状态维护、错误兜底 | transfer_to_car_control, transfer_to_rag, transfer_to_gui |
极简,仅保留最近几轮对话概要 |
| Vehicle Control Agent | 精确控制车辆硬件、参数校验 | set_seat_heat(level), open_window(pos), get_tire_pressure() |
严谨System Prompt 包含安全规范 |
| RAG Agent | 查询手册、故障解释、闲聊 | search_knowledge_base(query), format_citation() |
宽泛,包含大量检索到的文档片段 |
| GUI Agent | 操作屏幕 App、多轮业务流程 | click_element(id), scroll(direction), input_text(val) |
状态机,保留当前页面 UI 树信息 |
这是 Agents SDK 的核心。路由不仅仅是“分类”,更是“带参数的跳转”。
最简单的交接只是切换处理对话的 Agent 对象。
Rule of Thumb: Router Agent 不应该回答领域问题。如果用户问“胎压多少”,Router 必须 切换到车控 Agent,而不是自己尝试回答(哪怕它偶尔能猜对)。
为了避免用户重复说话,Handoff 函数必须定义参数 Schema。
transfer_to_climate(initial_intent: str, temperature: int | null)temperature=24 -> 调用 Handoff -> ClimateAgent 初始化 -> 检测到参数 -> 直接调用 set_temp(24)。专家 Agent 完成任务后,必须有明确的“出口”。
handoff_back_to_supervisor(result_summary="空调已调至24度")。handoff_back_to_supervisor(reason="off_topic", user_query="...")。在多代理系统中,记忆(Memory)需要分层管理。
存储 Agents SDK 的 runner 或顶层上下文中,所有 Agent 可读(部分可写)。
仅在当前 Agent 活跃期间有效。
当从 Agent A 切换到 Agent B 时:
task_stack。这是系统实现的难点:Realtime API 是流式的(WebSocket),而 Agents SDK 逻辑通常是同步或异步的函数调用。
我们需要一个适配层(Adapter)来桥接两者。
response.function_call_arguments.done 事件。call_id、name (工具名) 和 arguments (JSON)。AgentRunner。current_agent 指针,不向 Realtime API 返回结果,而是让新 Agent 生成新的回复指令。set_seat):执行 Python 函数,获取返回值。conversation.item.create (function_call_output) 将结果传回 Realtime API。response.create 让 Realtime API 基于工具结果成语音。在 Agent 执行耗时任务(如 RAG 搜索)时,用户可能会打断。
input_audio_buffer.speech_started。response.cancel 事件。kill 线程/协程。不要完全信任 Agent 的输出。在 Agent 和车辆底层 API 之间插入一个 确定性代码层。
open_trunk() -> Guardrail Interceptor 拦截 -> 检查 speed > 5km/h -> 拒绝执行并抛出 SecurityError -> Agent 捕获错误并向用户解释“行驶中无法打开后备箱”。对于高风险操作(如购买、恢复出厂设置),Agent 不直接调用执行工具。
stage_order(items)(暂存,不提交)。execute_payment()。
注意:必须在 System Prompt 中强制要求 Agent 遵循此“两步走”策略。
Q1: 为什么 Supervisor Agent 的 System Prompt 应该尽可能短,且不包含具体业务逻辑?
Q2: 请设计一个 transfer_to_music_agent 的工具定义(JSON Schema),要求能承接用户的模糊意图(如“我想听点放松的)。
Q3: 当 RAG Agent 发现用户的问题(如“轮胎气压怎么看”)在手册里找不到答案时,它应该怎么做?
Q4: 复杂场景设计:用户在与 GUI Agent 进行多轮对话(如筛选餐厅)时,Realtime API 突然断线重连。请设计一套恢复机制,确保用户不需要重新开始筛选。
Q5: 竞态条件(Race Condition):用户语速很快,说“打开空调”(指令A),紧接着又说“算了别开了”(指令B)。Realtime API 可能先后触发两次 Function Call。如何确保空调最后是关闭的?
Q6: 如何设计一个“主动关心”功能?例如监测到 DMS 疲劳信号时,Router 应该如何介入当前正在进行的对话(可能是音乐,也可能是航)?
history_routing 字段,记录 [Router, AgentA]。Tone & Voice 定义不一致。open_window(seat="driver"),因模型有偏见。enum 严格限制参数范围。