雨天小六

读懂 Codex(5.5):请求身份、认证 Header 与客户端 Header

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

#Codex#Agent Runtime#Responses API#流式协议#软件架构

一个 Responses 请求同时需要认证、会话关联、Turn 归属、兼容投影和粘性路由,但这些字段不能由多个调用点各自拼装。Codex 先建立一份规范化 metadata 快照,再投影到 HTTP Header 与 WebSocket client_metadata。

具体问题与启用条件

本节关注请求身份和 Header 的所有权与优先级,不展开具体登录刷新算法;401 恢复归入 5.22。

条件来源决定字段或状态对本机制的影响
认证方式API Key、ChatGPT auth、Provider 自定义认证生成 Authorization/账户等 Header
请求种类Turn、Prewarm、Compaction、Memory决定 metadata 中是否包含 Turn 身份
Turn 状态已收到 x-codex-turn-state后续同 Turn 请求回送

协议、类型与状态所有权

状态或协议所有者生命周期关键不变量
CodexResponsesMetadataTurnContext metadata state一次请求快照规范事实源
认证 HeaderAuthProvider一次尝试,可刷新调用方不能伪造核心认证字段
兼容 HeaderModelClient 投影函数一次请求由规范 metadata 生成
turn_stateModelClientSession一个 Turn首次值写入后不变

机制调用链如下:

TurnContext/Session 身份
→ CodexResponsesMetadata 快照
→ 过滤调用方 reserved keys
→ AuthProvider 添加认证
→ Provider/default/extra headers 按优先级合并
→ HTTP Header 或 WS client_metadata 投影
→ 响应捕获 turn_state
规范请求身份投影到 Header 和 client_metadata
图 5.5-1:认证与 Turn 路由加入传输,但核心身份都来自同一快照。

机制怎样工作

规范快照包含 installation、session、thread、turn、window、request kind、父子 Agent、sandbox、workspace、Code Mode 工具名和开始时间。完整 blob 放入 client_metadata["x-codex-turn-metadata"];扁平 client_metadata 和直接 Header 只是兼容投影。调用方额外 metadata 会被过滤,不能覆盖 Codex 保留键。

HTTP 与 WebSocket 的承载不同,但来源相同。HTTP 可直接发送有界的兼容 Header;Code Mode 工具映射可能无限增长,因此只放 client_metadata,不塞进 Header。x-codex-turn-state 是响应给出的粘性路由值:第一次捕获进 OnceLock,后续同 Turn 同时进入请求 Header/WS metadata;新 Turn 创建新锁。Header 合并也有明确优先级,避免 Provider 默认值意外覆盖请求级兼容信息。

Python 风格伪代码

这段伪代码保留生产实现中会改变结果的状态、分支和异步边界;认证 SDK、遥测字段和 Rust 所有权样板被折叠为明确的领域对象。

RESERVED = {"session_id", "thread_id", "turn_id", "x-codex-turn-metadata"}

def build_request_identity(turn: TurnSnapshot, extra: dict[str, str]) -> Identity:
    safe_extra = {k: v for k, v in extra.items() if k not in RESERVED}
    canonical = canonical_turn_metadata(turn, safe_extra)
    return Identity(
        client_metadata=project_flat(canonical) | {
            "x-codex-turn-metadata": compact_json(canonical)
        },
        headers=project_bounded_headers(canonical),
    )

async def authorize_and_send(identity: Identity, turn_token: str | None):
    headers = await auth_provider.headers()
    headers.update(provider_headers)
    headers.update(identity.headers)
    if turn_token is not None:
        headers["x-codex-turn-state"] = turn_token
    return await transport.send(headers, identity.client_metadata)

失败、取消与恢复

请求身份构造和 turn_state 捕获时序
图 5.5-2:调用方扩展先过滤,认证后合并;服务端路由值只写一次。
故障或边界已发生的状态对上层的结果能否直接重试恢复动作
调用方覆盖 reserved key规范快照未改变额外值被过滤使用非保留扩展键
Header 值非法该投影字段未插入请求继续或缺兼容信息视字段而定修正编码
跨 Turn 回送 turn_state路由语义污染可能命中错误后端状态每 Turn 新建 session
401请求未被服务接受进入一次认证恢复有条件刷新认证并重建尝试

设计取舍与验证

单一 metadata 快照避免 Header 与 body 各维护一份事实,却需要维护兼容投影。把大型映射限制在 client_metadata 可防止 Header 尺寸失控。保留键过滤牺牲了调用方自由度,换来可相信的会话和审计身份。

可验证契约证据方式预期结果
额外 metadata 不能覆盖核心字段构造冲突键并捕获请求服务端看到 Core 值
HTTP 与 WS metadata 对齐双传输请求捕获规范 blob 内容一致
Turn state 只在同 Turn 回放连续请求 Header 测试首次无值、后续有值、新 Turn 清空

Mini Codex 对照

Mini Codex 应用不可变 RequestIdentity 保存规范字段,并只允许白名单扩展。认证适配器返回 Header,不应读取或修改对话 History。可以省略产品专用字段,但必须保留 session/thread/turn 与 request kind。

本节边界

身份信息已可安全投影到传输。5.6 将同一请求中的 Prompt、工具与输出控制编译成 JSON body。

评论


← 返回文章列表