a↗Agent 工程实战中文课程 / v1.0.0⌕ 搜索课程/
本页目录

L02 把工具调用变成受控能力,而非任意函数调用

适用章节:M02。本实验允许多种正确实现;验收不变量固定,不强制特定框架。

工程事故

模型给出格式完全合法的订单号A100,但当前用户来自另一个租户。你又发现一个“通用call_function”工具允许模型传入任意Python函数名。结构化输出解决不了这两个问题。

最终交付

只读Tool Gateway、最小能力矩阵、输入与输出Schema、5条负面测试;选修一个仅暴露只读工具的MCP适配层。

已提供材料

specs/PROJECT_CONTRACT.md、data/retail/orders.json、reference/agentlab/business.py

先独立写出预期行为再看参考解。所有商店、订单、试次与价格单位都是教学构造;不连接真实资金系统。

接口与不可破坏的约束

身份由服务器注入Principal,工具参数只有业务必要字段。不要接受模型传来的tenant_id来切换身份。订单查询必须同时匹配tenant_id、owner_id、order_id;无权限与不存在统一返回NOT_FOUND。金额只接受整数分,bool不是有效整数金额。

工具描述明确“做什么/不做什么/是否有副作用/结果来源/错误码”。参数合法只说明形状合法。读取、提案、批准、执行四种能力必须区分;模型不能批准自己的提案。

实施步骤

  1. 列出工具:get_order、get_shipment、create_refund_proposal。把approve_refund留给经过认证的人类入口,不作为普通模型工具。
  2. 实现字段白名单和严格类型校验。未知字段、空订单号、额外tenant字段都要被拒绝。
  3. 将工具名映射到显式函数,不用eval/getattr任意定位函数。
  4. 在业务层重新做权限和资格校验;即使绕过模型网关,业务服务也不应裸露无授权退款。
  5. 比较shop-a/u-alice和shop-b/u-bob查询同名A100的不同结果。
  6. 可选MCP实验:把get_shipment包装为MCP tool,固定协议版本。分别测试协议发现、参数验证和真实授权,记录三者不是同一件事。

验收矩阵

案例 结果
Alice查自己的A100 paid=10000
Bob查自己的A100 paid=33000,不读到Alice订单
Alice查A111(同租户其他人) NOT_FOUND
模型添加tenant_id=shop-b INVALID_ARGUMENTS
参数order_id=true INVALID_ARGUMENTS
任意未知工具名 UNKNOWN_TOOL,无代码执行
未审批直接提交退款 APPROVAL_REQUIRED,账本仍0

如何运行已有参考测试

在包根目录运行:

python -m unittest discover -s reference/tests -v

本实验主要参考测试类为BusinessTests。已有测试默认验证reference/;测试通过不代表你的starter/实现通过。接入自己的实现时,将被测模块显式替换/注入,保持测试和领域契约不变,不要修改断言来迁就实现。

评分

授权35;Schema/白名单25;错误与信息最小化15;测试15;协议与业务边界解释10。

出现跨租户泄露、未经批准的退款或伪造结果时,不以其他分数抵消。允许记录未完成的选修功能,但必须说明范围。

进阶挑战

为工具Schema增加版本;模拟工具从只读变成会产生副作用时是否需要重新审批。检查工具结果中的恶意指令能否改变权限。

提交前自查

保存代码版本、运行命令、输入数据版本、输出日志、失败案例与设计决策。解释至少一个被你否决的方案。没有运行的测试标记“未运行”,不写“预计通过”。参考解见对应答案。