Appearance
Tool 能力怎么扩展且不失控:Programmatic Calling 与 Evaluation
前置:Tool 失败后能不能重试:Retry Eligibility 与 Idempotency Contract
核心问题:当 Tool 调用从单次 function calling 扩展成程序化组合时,怎样限制调用范围并判断这套组合真的比简单调用更好?
为什么有时不应该“一次 Tool Call 回一次模型”
例如需要读取 100 个独立记录并做简单聚合:
text
LLM → get_record(1) → LLM
LLM → get_record(2) → LLM
...会产生大量模型 round trip,Context 也被重复 Tool Result 填满。
如果操作本身是确定性的,允许 Agent 在受控环境里表达:
python
records = [get_record(i) for i in ids]
return summarize_locally(records)可以把“循环和数据变换”交给程序,把真正需要语义判断的结果再交回模型。
Programmatic Calling 的适用条件
适合:
- 大量同构 read-only Tool calls;
- filter/map/reduce 等确定性数据变换;
- 需要根据中间结构化值做简单分支;
- 模型 round trip 明显成为成本/延迟瓶颈。
不适合默认开放:
- 高风险写操作批量执行;
- 需要逐步人工审批;
- Tool 之间存在复杂事务/补偿;
- 任意网络/文件/系统 API 都可被代码环境访问。
核心仍是 capability-limited execution,不是“模型会写 Python,所以给它完整 Python 权限”。
执行边界需要比普通 Tool 更严格
Programmatic layer 至少需要限制:
text
allowed API/tool set
argument/schema validation
max calls / loop iterations
wall-clock deadline
memory/output size
network/filesystem access
side-effect class
trace of each underlying call批量调用不能绕过 Tool Registry、approval 或 audit。底层每一次真实 Tool execution 仍然应产生可观察 record。
Tool Evaluation 不只测“最后任务做对了没”
End-to-end success 无法定位 Tool 设计问题。Component Eval 至少看:
- selection accuracy:该不该选这个 Tool;
- argument accuracy:参数/约束是否正确;
- unnecessary call rate:有没有多余调用;
- execution success:真实执行是否成功;
- result utilization:模型是否正确利用 Observation;
- confusion pairs:哪些相似 Tool 经常被选错;
- programmatic amplification:一次错误选择是否被循环放大几十次。
例如 search_code 与 search_issue 经常混淆,优先修 naming/description/schema,而不是在 System Prompt 再加五条规则。
Programmatic Calling 必须有单独 Eval
同一批任务比较:
text
normal tool loop
vs
programmatic batch calling记录:任务成功率、Tool calls、LLM turns、token、latency、错误放大、side-effect count。只有“更快”但失败时一次执行 100 个错误动作,不是有效优化。
Failure Modes
受控 Tool 变成任意代码执行逃逸口
处理: 只暴露 capability wrapper;默认无任意 network/filesystem/credential。
只看 Tool execution success
Tool API 全部 200,但模型可能一直选错 Tool。必须把 selection 和 result utilization 单独评估。
如何验证
构造易混淆 Tool 集和批量读取任务:既验证 normal loop,也验证 programmatic mode;故意让第一个 selection 错误,确认 call budget 能限制错误放大。
自测
- 允许模型生成一段程序自动组合多个 Tool 后,为什么 capability scope 和调用预算必须比单次 function calling 更明确?
- Programmatic calling 调用次数变少,但越权率上升。你会用哪些 trace/eval 指标判断它是否真的优于简单调用?