Skip to content

参数、权限、会话与错误适配 ​

迁移不是工具改名 ​

旧调用可能把 prompt、cwd、sandbox 和审批策略同时传进 codex 工具。迁移 SDK 时分别放入 thread options 与 run 输入;迁移 App Server 时先 thread/start,再 turn/start。旧会话标识不能不经验证就作为新 thread ID。

基于第一章发现的 schema,如果当前版本提供 codex 且允许 prompt、cwd、sandbox、approval-policy,下面展示在已初始化 session 内的真实调用替换。它会启动模型任务,不属于离线发现实验:

python
result=await session.call_tool('codex',{
    'prompt':'读取 README.md 并总结,不修改文件。',
    'cwd':'/absolute/path/to/codex-lab',
    'sandbox':'read-only',
    'approval-policy':'never',
})
if result.isError:raise RuntimeError('Codex tool failed')
for block in result.content:
    if block.type=='text':print(block.text)

先把 cwd 换成自己创建的实验目录并确认 schema 字段一致。未知字段不要偷偷忽略,否则 read-only 策略可能根本没传到下层。本课程未执行该计费调用。

边界兼容的离线例子 ​

下面只演示应用自己的旧参数到新内部合同,不冒充所有版本 SDK 的完整字段。Python 3.12 保存 adapter.py:

python
def adapt(old):
    allowed={'prompt','cwd','sandbox'}
    if set(old)-allowed:raise ValueError('unsupported legacy field')
    if old.get('sandbox')!='read-only':raise PermissionError('only read-only migrated')
    if not old.get('cwd','').startswith('/'):raise ValueError('absolute cwd required')
    if not isinstance(old.get('prompt'),str) or not old['prompt'].strip():
        raise ValueError('prompt required')
    return {'thread_options':{'workingDirectory':old['cwd'],'sandboxMode':'read-only'},
            'input':old['prompt']}
new=adapt({'prompt':'read README','cwd':'/tmp/lab','sandbox':'read-only'})
assert new['thread_options']['sandboxMode']=='read-only'
try:adapt({'prompt':'read','cwd':'/tmp/lab','sandbox':'workspace-write'})
except PermissionError:pass
else:raise AssertionError('permission widened')
print('adapter preserves boundary')

必须知道旧策略含义后才能映射;不支持的审批模式返回错误,不能降成无需审批。环境变量采用白名单传递,避免兼容层继承宿主所有凭证。路径检查除绝对路径还要验证真实授权根与符号链接,此示例只验证字段映射。

MCP 工具返回失败、底层 CLI 退出和业务任务失败是不同层。统一错误时保留原层级与可重试性;把三者都返回普通文本会让上层 Agent 把“错误日志”当作任务成功结果。断线后先查询或恢复既有任务,不重复启动写任务。

练习 ​

给 adapt 输入未知字段 network=true,应拒绝;给 prompt 空字符串也应拒绝。写断言并说明为什么未知权限字段不能忽略。

先记录自己的输出与解释,再核对本章答案。

用心记录每一步成长