5. 异步工具调用:不是写一个 async def 就实现了
5.1 四种容易混淆的“异步”
当前 API 通过函数或 custom 工具上的
async: true 表达最后一种语义;工具仍在应用侧执行,结果用原始 call_id 回传。它与 Background mode 不同,且当前文档不允许把此类 async 工具用于 PTC;多 Agent 模式还有额外组合限制。Async tool calling
5.2 一个具体例子
任务:“查询 CI 结果,并检查 README 是否说明了安装步骤。”5.3 为什么可能加速?
假设模型独立工作耗时M,工具耗时 T,协调成本 O:
5.4 Harness 必须补哪些实现?
一个最小 pending registry 需要记录:5.5 为什么要从流中尽早启动工具?
如果应用等responses.create() 收完整个响应后才启动工具,模型可能已经生成了独立回答,实际 I/O 与生成就没充分重叠。
流式实现应在完整工具调用项已生成时启动任务,不能拿尚未完成的 JSON 参数片段执行。附录 live_api.py async 在 response.output_item.done 上注册工作线程;流结束后把结果回传。这是一个真实 API 接线示例,但本次未调用付费模型。
call_id,同时接到最新 response 链上,避免丢掉工具执行期间新加入的对话。
5.6 Wait 与 yield 的关系
你可以让工具先返回可等待的任务标识,模型继续工作,等真正依赖结果时再 wait。这个机制在应用层也能实现,不一定要求 API 的 async 标志。 但是job_handle 和 API call_id 不是同一个东西:前者可能是你业务注册表的名字,后者是协议匹配结果的标识。不要把模型自定义的 handle 当成模型已经知道的底层 ID。
Codex Code Mode 源码里能看到启动 cell、初次输出、yield 后继续存活,以及后续 wait/terminate 的处理路径。这证明非阻塞运行需要完整生命周期管理,不是只改工具声明。execute handler、wait handler
5.7 本地 Demo 验证了什么?
runtime_demo.py 同时启动两个模拟工具,在它们结束前记录独立工作,并处理一次用户变更。测试不用不稳定的耗时阈值判断并行,而是验证第二个工具开始事件出现在第一个完成事件之前。
它没有调用 LLM,所以证明的是 Python 调度与状态管理机制,不是 Astra 推理能力。本次输出约 0.123 秒仅是模拟等待时间,不能写成“Codex 性能提升 xx%”。
6. Mid-turn steering:运行中改需求,怎样保持一致性?
6.1 为什么基础 Harness 难做?
基础循环往往只在“一轮结束后”读下一条用户输入。用户想说“不要提交,只分析”,但模型仍沿原计划执行。简单 cancel 再重启也有代价:丢失中间状态、重复工具、不能准确判断外部动作是否已经发生。 Steering 的目标是保留已完成工作,把新增要求接到正在运行的任务中。6.2 两层 steering,不要混用
App Server 的协议测试包含 turn ID 等行为验证;它的客户端接口与 Responses API 的模型服务接口不是同一份 schema。不能对普通 HTTP
/responses 随便发一个 turn/steer 字段。App Server steering 测试
App Server 示例:
expectedTurnId 相当于防误投校验:客户端认为仍在运行的 turn 可能已经结束,服务端不能悄悄把更新应用给下一轮。
6.3 Responses API 的生效点
当前官方 guide 说明 Astra 支持 WebSocket steering。请求被接受后,并不修改已经发出的输出,也不撤销已执行动作。它在适当边界衔接 successor response;successor 的response.created 才是更新提交点。依赖应用工具结果或审批时,会进入 pending。Steering guide
6.4 “边生成边改”不等于改写已经采样的 token
面试回答应是:服务端把新增输入纳入后续继续过程,在协议承诺的安全边界生效。你不能从交互现象断言它原地修改了 KV cache、当前神经网络激活值或已生成 token。6.5 已经发出去的写操作怎么办?
假设旧计划准备“修改配置并发布”,新要求是“只读分析”。合理设计是:- 收到新要求时增加业务 revision。
- 尚未派发的变更计划失效,重新判断。
- 已在运行的只读工具可保留结果,但检查适用范围。
- 未提交的写操作在执行前再次检查 revision 与权限。
- 已完成的外部写操作只能通过补偿或回滚处理,不能声称被 steering 撤销。
commit() 检查 revision;测试证明 revision 0 的旧方案不能在 revision 1 后被提交。它只记录教学方案,没有操作真实外部系统。
真正数据库写入应把版本校验和写入放在同一事务/CAS 边界;远端调用要使用幂等键和对账。应用内“先判断再调用 HTTP”仍有竞态窗口。
6.6 面试回答
Mid-turn steering 的难点不只是接收一条新消息,而是定义输入的接受点、生效点与已完成副作用的边界。我会使用活动 turn 校验、需求 revision 和执行前的授权检查,保留已完成工具结果;对断线后的未知状态先对账,不盲目重试。