先补齐必要概念
适合:知道函数参数,第一次设计模型工具。
- Schema
- 描述字段形状、类型和约束的契约;字段合法不证明调用者拥有操作权限。
- 可信上下文
- 服务端认证后得到的身份与租户,不能直接相信模型填写的身份。
- 副作用
- 对外部世界的写入,例如付款、发布或删除。
- 状态版本
- 资源当前状态的版本,用于发现检查之后发生的变化。
原理怎样一步步成立?
- 模型
提出工具名、参数与 call_id;这些都是候选输入。
- 运行时
先查白名单、完整性与共享预算,再校验参数;未通过就停止该动作。
- 业务服务
从可信会话读取身份,核对资源归属与当前权限,在提交边界检查状态。
- 工具适配器
按 call_id 关联成功、失败或未知回执,保留已发生事实。
- 验收
回执进入下一轮输入;最终答案与事实核对,通过后才报告业务完成。
结构正确不授予权限;call_id 只关联本轮调用,不能代替跨恢复的业务操作键。
逐步解释原理
- 候选参数
模型提出动作与参数。
- 结构与语义
检查字段、类型、单位和关联约束。
- 身份与状态
核对真实权限与当前业务状态。
- 执行与回执
有条件地执行,并校验结果及业务证据。
入门 · 理解原理
为什么合法 JSON 仍然不能付款?
本层目标:能解释“格式正确”和“允许执行”的区别。
从普通函数调用理解工具
模型提出工具调用,本质上是生成一组候选参数。解析出 account 和 amount_cents 以后,程序还要决定是否执行。一个合法字符串可以是别人的账户,一个正整数可以大于余额。格式、资源归属和业务规则分别回答不同的问题。
把一个请求分成四层
结构层检查字段和类型;语义层检查金额单位、范围以及日期等字段关系;授权层用真实登录身份检查资源和动作权限;状态层检查当前余额、审批或资源版本。Schema 可以表达很多静态约束,但本身不提供登录身份,也不查询当前账户归属。
用反例找出缺口
请求 B 账户付款 100 分,B 属于另一个租户。所有字段都符合形状,仍必须拒绝。即便账户属于自己,也可能没有付款权限。这个反例说明,生成稳定参数是执行流程的一部分,服务端仍要承担业务决策责任。
运行实验,观察反例
特定工具的手动参数与授权检查;无真实付款、不实现完整 Schema、事务扣款或动态权限平台。
Python 3.10+ · 默认运行只使用标准库 · 在你的电脑运行
- 运行格式合法但跨租户的反例
- 改变可信身份和权限,比较错误分支
- 设计检查后状态变化的额外测试
python3 tool_contracts.py查看本入口脚本
"""A specific tool's manual validator, not a JSON Schema implementation."""
import json
def validate_shape(params):
if type(params) is not dict or set(params) != {"account", "amount_cents"}:
raise ValueError("shape")
if not isinstance(params["account"], str) or not params["account"]:
raise ValueError("account")
if type(params["amount_cents"]) is not int or params["amount_cents"] <= 0:
raise ValueError("amount")
def authorize(params, actor, accounts):
validate_shape(params)
account = accounts.get(params["account"])
if account is None or account["tenant"] != actor["tenant"]:
raise PermissionError("not allowed")
if "pay" not in actor["permissions"]:
raise PermissionError("not allowed")
if params["amount_cents"] > account["balance"]:
raise ValueError("balance")
def demo():
params = dict(account="B", amount_cents=100)
actor = dict(tenant="tenant-a", permissions=["pay"])
accounts = {"B": dict(tenant="tenant-b", balance=1000)}
validate_shape(params)
try:
authorize(params, actor, accounts)
except PermissionError:
return dict(shape_valid=True, authorized=False, business_writes=0)
raise AssertionError("cross-tenant request was accepted")
if __name__ == "__main__":
print(json.dumps(demo(), sort_keys=True))
本地运行的预期输出
{"authorized": false, "business_writes": 0, "shape_valid": true}- 结构与授权结果分别呈现
- 跨租户请求没有业务效果
- 线上业务竞态需要另行验证
本层验收任务
给同一份付款参数列出结构、单位、权限与状态四类检查。
正在读取此浏览器记录…
收起答案,检查理解
如果模型把 tenant_id 填成自己的租户,能当成认证依据吗?
展开参考推导
不能。模型参数是待校验输入,可信身份必须来自认证上下文,再与资源归属和动作权限核对。
延伸原理与知识练习
遇到不熟悉的原理,先阅读实现、连续追问和迁移案例,再独立说明前提与边界。作答与笔记保存到原有账号记录。
本专题的全部关联解析与练习(3 道)
依据与验证范围
原理依据来自公开资料;数字、案例和任务是本站教学设计。离线实验验证本页注明的范围,学习效果仍需通过独立任务与反馈判断。