雨天小六

读懂 Codex(4.18):Custom Tool、Local Shell 与 Tool Search 的配对修复

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

#Codex#Agent Runtime#Prompt#上下文工程#软件架构

Custom Tool、Local Shell 和 Tool Search 都有调用/结果关系,但结果类型与普通 Function 不完全相同。规范化器必须按调用种类选择正确的占位结果,不能用一个统一 FunctionCallOutput 覆盖所有协议变体。

四类配对矩阵

调用结果缺失时合成
FunctionCallFunctionCallOutput文本 aborted
LocalShellCallFunctionCallOutput文本 aborted
CustomToolCallCustomToolCallOutput文本 aborted
ToolSearchCallToolSearchOutputclient/completed、空 tools
Custom Tool、Local Shell 和 Tool Search 的不同配对结果
图 4.18-1:Local Shell 复用 Function output 是上游协议约定;Tool Search 则需要结构化空搜索结果,不能伪装成函数文本。
def synthetic_output_for(call):
    match call.kind:
        case "function" | "local_shell":
            return FunctionOutput(call_id=call.call_id, text="aborted")
        case "custom_tool":
            return CustomToolOutput(call_id=call.call_id, text="aborted")
        case "tool_search":
            return ToolSearchOutput(
                call_id=call.call_id,
                status="completed", execution="client", tools=[]
            )

Custom Tool 或 Local Shell 缺结果在源码中走 error_or_panic 记录不变量违例后仍补结果:生产构建尽量恢复 Prompt,严格测试配置可以让异常尽早暴露。

Tool Search 的 server output 是例外

客户端执行的 ToolSearchOutput 必须找到 ToolSearchCall;execution == "server" 的 output 可以独立保留,因为服务端可能返回一个不对应本地 call 的搜索项目。call_id=None 也按协议允许保留。

客户端和服务端 Tool Search output 的孤儿判断差异
图 4.18-2:是否删除孤儿不能只看 call_id;Tool Search 还要看 execution 来源,服务端输出属于协议允许的独立项目。
def keep_tool_search_output(output, client_call_ids):
    if output.execution == "server":
        return True
    if output.call_id is None:
        return True
    return output.call_id in client_call_ids

头部裁剪时 remove_corresponding_for 使用同一矩阵删除配对另一端。新增 ResponseItem 调用种类时,必须同时更新补缺、删孤儿、对应删除、token 估算和 API 可用项过滤;只改其中一处会产生隐蔽的不一致。

源码与测试锚点

  • codex-rs/core/src/context_manager/normalize.rs:完整配对矩阵。
  • codex-rs/protocol/src/models.rs:各 ResponseItem 结构。
  • codex-rs/core/src/context_manager/history_tests.rs:Custom、Shell、Tool Search 边界。

评论


← 返回文章列表