KEEL · 龙骨 · A CURRICULUM FOR THE AI ERA

04. Registry 和 Executor 怎样形成白名单? — keel 龙骨

模型返回的工具名是不可信输入。程序不能按字符串寻找任意函数,只能从已经注册的能力中选择。

模型返回的工具名是不可信输入。程序不能按字符串寻找任意函数,只能从已经注册的能力中选择。

Registry 保存的是什么

name
description
version
effect
arguments_model
result_model
handler

handler 是实现,其他字段决定它怎样被描述、校验、授权和观察。Registry 同时是模型可见工具和执行器允许工具的来源,避免两边漂移。

Executor 的固定顺序

flowchart TD
    A[ToolCall] --> B{注册?}
    B -->|否| C[unknown_tool]
    B -->|是| D[输入 schema]
    D -->|失败| E[invalid_arguments]
    D -->|通过| F[业务与权限策略]
    F -->|拒绝| G[policy_denied/approval_required]
    F -->|允许| H[调用 handler]
    H --> I{业务成功?}
    I -->|否| J[结构化 ToolError]
    I -->|是| K[输出 schema]
    K -->|失败| L[invalid_tool_output]
    K -->|通过| M[ToolResult ok=true]

所有检查发生在模型之外。模型不能跳过注册、校验或权限。

运行确定性拒绝实验

python courses/foundation/tool-calling/course/project/examples/02_validated_dispatch.py

依次观察:

  1. 合法查询返回结构化结果;
  2. 未知名称被 Registry 拒绝;
  3. 错误事件编号被输入 schema 拒绝;
  4. 写工具没有审批记录时返回 approval_required;
  5. handler 返回缺字段时被输出 schema 拒绝。

这些测试不需要 Ollama,因为白名单和校验是程序不变量。

为什么不让函数自己处理所有错误

如果先执行 function(**arguments),再等函数崩溃,你无法稳定区分协议错误、业务错误和实现异常。Executor 应把预期领域错误转成稳定的 ToolError,把未预期异常转为内部错误并将堆栈留在受保护日志中。

本章自测

输入值格式正确但用户无权访问,应该在哪一步拒绝?不是 schema,而是策略。工具名称不存在,应该在哪一步拒绝?不是 handler,而是 Registry。

下一章:工具结果为什么要回到下一轮?

进入 keel 阅读