雨天小六

读懂 Codex(3.22):Realtime、Review 与普通 Turn 生命周期的差异

· 更新于 2026-08-02 · 专栏:读懂 Codex

#Codex#Agent Runtime#生命周期#软件架构

Realtime、Review 和普通 Turn 共享同一个 Session,却不是三种相同 Task。普通 Turn 由 RegularTask 驱动 Responses 采样;Review 是父 Session 中的 ReviewTask 加受限子 Codex;Realtime 则是独立长连接状态机,只有 handoff 文本需要后台 Agent 时才进入普通 Turn 路径。

生命周期对照

维度普通 TurnReviewRealtime
主执行体RegularTaskReviewTask + one-shot childRealtimeConversationManager tasks
模型通道Responses stream子 Codex ResponsesRealtime WS/WebRTC sideband
公开开始TurnStarted当前父 Review 缺 TurnStartedConversationStarted/SDP/Realtime
输入追加Steer pending input拒绝 Steeraudio/text/speech queues
结束TurnComplete/AbortedExitedReviewMode + Turn terminalConversationClosed
与 Agent 连接本身就是 Agent Turn子线程结果投影handoff/delegation 可启动或 steer Agent
普通 Turn、Review 与 Realtime 的生命周期对照
图 3.22-1:三条路径只在 Session 和事件总线处汇合;不能用 TurnComplete 解释 Realtime 连接关闭,也不能把 Review 子线程直接暴露成父线程历史。

Review 是受限子会话的投影

Review 构造专用 TurnContext:可选 review model,禁用 WebSearch、Goals 等功能,MultiAgent disabled,developer instructions 置空,保留父环境、权限和 Skills snapshot。ReviewTask 再启动 one-shot 子 Codex,approval policy强制 Never并设置 REVIEW_PROMPT。

父 Task 消费子事件:普通事件选择性转发,隐藏 assistant delta,等子 TurnComplete 后解析结构化 ReviewOutput;解析失败则把纯文本放入 fallback explanation。最后发 ExitedReviewMode item。abort 同样发退出项,但 output 为 None。

async def run_review(parent, review_turn):
    child_cfg = constrain_for_review(parent.config)
    child_events = await start_one_shot_child(child_cfg, review_prompt)
    output = await project_until_child_terminal(child_events)
    if not cancelled():
        await emit_exited_review_mode(output)

源码 TODO 明确指出当前父 Review turn 依赖 spawn_task获得 TurnComplete,却没有对应公开 TurnStarted。这是现状,不应在文章中为“对称”而虚构事件。

Realtime 是 Session 级连接状态机

Realtime start准备认证、版本、voice/session config和 WebSocket/WebRTC transport,建立有界 audio/text/handoff/output channels、input task、fanout task和 stop token。Audio/Text/Speech Op 直接写 manager 的输入通道,不通过 ActiveTurn pending queue。

realtime_active 会在新 TurnContext 中取 manager running state,用 WorldState 告知 Responses 模型当前有实时会话。反方向上,普通 Agent 的 ItemStarted、text delta、ItemCompleted和 TurnComplete会被镜像到 realtime handoff,完成时清 active handoff。

Realtime 会话通过 handoff 与普通 Agent Turn 双向衔接
图 3.22-2:Realtime 输入平时留在长连接;handoff 才把文本路由到 Agent,Agent 的流式输出再镜像回该 handoff。
async def on_realtime_handoff(text):
    wrapped = render_realtime_delegation(text, transcript_tail)
    await session.route_realtime_text_input(wrapped)  # 新 Turn 或 steer

async def on_agent_event(event):
    if realtime.running and event.is_agent_text():
        await realtime.stream_handoff(event)
    if event.is_turn_complete():
        await realtime.handoff_complete()
        await realtime.clear_active_handoff()

Realtime close 取消 stop token,等待 input task,并根据结束原因选择等待或 detach fanout,再发 ConversationClosed。它不等于 Session Shutdown;后者会调用 manager.shutdown 后继续清 ActiveTurn、进程、MCP 和持久化。

共同点只在外围生命周期

三者都使用 Session 事件发送、trace和部分持久化设施,也都必须有明确停止路径。但输入协议、模型传输和终态事件不同。设计上让 Realtime 成为旁路连接、Review 成为特殊 Task,而不是把所有东西强塞进 run_turn,避免一个循环同时承担音频时序、审查投影和代码工具反馈。

评论


← 返回文章列表