一、引言:Agent 不只是一个 Prompt
很多 Agent 示例把重点放在系统提示词和工具列表上:模型能调用几个 API,就被称为一个 Agent。但真正进入业务系统后,问题很快会变成另一组问题:工具调用是否有权限边界?模型能否引用没有见过的商品或记录?一次写操作能否回滚、审批和审计?同一套能力换成另一种运行时后,行为是否仍然一致?
commerce-agents 给出的答案是:把 Agent 当成一个可复用的执行系统,而不是一个聊天脚本。仓库围绕虚构的 ACME 商业体系实现了两个角色:面向消费者的 shopping agent,以及面向运营人员的 merchant agent。两个角色共享安全、记忆、工具执行、流式事件和提示词组装机制,同时通过各自的领域核心接入不同的业务后端。
本文以仓库当前源码为依据,重点分析以下问题:
- 目录如何把公共机制、角色核心、运行时和垂直示例分层;
Messages API、Claude Agent SDK和Managed Agents为什么可以复用同一套工具契约;- 购物代理的 provenance gate 与商户代理的 staged change 如何把模型行为约束在可审计边界内;
- 这个项目使用了哪些工程设计模式,以及从参考实现走向生产还需要补什么。
先说明一个重要边界:仓库中的品牌、商品和人物都是虚构的。购物侧不会下单或扣款,checkout 只是把购物车交给宿主应用;商户侧的写操作默认只生成待审批的变更,只有宿主完成批准后才会应用到业务系统。
二、项目概览:两个角色、三条路径、四个垂直示例
2.1 两个角色解决两类问题
| 角色 | 面向对象 | 主要能力 | 写操作边界 |
|---|---|---|---|
shopping-agent |
消费者 | 搜索、比较、规划、购物车、订单与政策问答、个性化记忆 | 只修改购物车;结账由宿主应用完成 |
merchant-agent |
商户运营人员 | 经营指标、商品与库存、定价促销、营销活动、分析委托 | stage_* 先生成变更,预览后等待人工批准 |
这不是把一个 Agent 复制成两个 Prompt。两个角色拥有不同的领域类型、后端接口、工具注册表、grounding 规则和安全闸门,但它们都建立在 commerce-common/commerce_common/ 的同一执行框架上。
2.2 三种运行路径
同一个角色可以通过三种方式运行:
- Messages API:仓库的参考运行时。
ShoppingAgent和MerchantAgent自己负责轮次、流式响应、工具调用和事件输出。 - Claude Agent SDK:通过
ClaudeAgentOptions启动 Agent SDK,工具以进程内 MCP server 的形式挂载,宿主负责预取上下文并收集结果。 - Managed Agents:平台负责 Agent 循环,仓库提供
agent.yaml、派生出的system.md、Skills、MCP server 和宿主侧自定义 UI 工具。
三条路径并不是完全相同的部署形态。Messages API 和 Agent SDK 能运行仓库中的 grounding 与部分分析逻辑;Managed Agents 的工具选择和确认由平台负责,因此 grounding.py 的运行时逻辑不在这条路径上,商户分析委托也没有写进 Managed Agent manifest。仓库通过公共工具契约、MCP server 和跨路径测试尽量把差异收敛在边界内。
2.3 四个可运行垂直
examples/ 目录提供了四个完整示例:
retail/:常规商品、购物车、库存和 listing 操作;travel/:日期约束的库存与行程展示;telecom/:账户上下文、套餐比较和受保护的费用字段;entertainment/:限时 hold、候补、场馆座位图和全价费用披露。
四个示例都复用 examples/demo_common/ 的 FastAPI 宿主代码和 examples/web-shared/ 的前端协议、流式 Hook 与组件框架,只把垂直数据、后端实现、配置和领域 UI 留在自己的目录中。
三、目录结构:公共内核与角色边界
仓库的目录组织比单体 Agent 项目更接近一个小型平台:
commerce-agents/
├── commerce-common/
│ └── commerce_common/ # 两个角色共享的执行与安全机制
├── shopping-agent/
│ ├── core/ # 购物领域类型、后端、Prompt、工具与 gates
│ ├── runtime-messages-api/ # Messages API 轮次循环
│ ├── runtime-agent-sdk/ # Agent SDK 运行时与控制台
│ ├── managed-agents/ # manifest 与 storefront MCP server
│ └── skills/ # 五个购物流程
├── merchant-agent/
│ ├── core/ # 商户领域类型、后端、变更与 guardrails
│ ├── runtime-messages-api/ # Messages API 轮次循环与分析委托
│ ├── runtime-agent-sdk/ # Agent SDK 运行时与审批控制台
│ ├── managed-agents/ # manifest、merchant MCP、定时 digest
│ └── skills/ # 五个运营流程
├── examples/ # 四个垂直的 FastAPI + Next.js 应用
├── plugins/commerce-builder/ # Claude Code 构建与评估插件
├── docs/ # safety、backend、deployment 文档
├── tests/ # 跨包、跨角色、跨运行时测试
└── scripts/ # 安装、demo、smoke、检查和部署脚本
3.1 commerce-common:把容易重复的机制抽出来
公共包的 README 明确采用“一种机制一个模块”的组织方式,核心模块如下:
| 模块 | 职责 |
|---|---|
config.py |
BaseAgentConfig,统一身份、模型、预算、能力开关、记忆与长度上限 |
fencing.py |
清洗不可信文本,移除隐藏字符、伪造角色边界和特殊标签,再包裹固定 fence |
memory.py |
MemoryStore 协议、事实校验、写入过滤、提取、保留期和 purge |
skills.py |
从 SKILL.md 目录加载流程,在 Prompt 中生成技能索引 |
prompt_assembly.py |
静态系统块、工具列表、动态上下文和 rolling cache breakpoint |
grounding.py |
根据用户消息决定是否必须先调用某个读取工具 |
presentation.py |
UI payload 校验、服务端 enrichment、ui 和 ui_partial 事件 |
execution.py |
BaseToolExecutor,统一分发、失败梯度、Skills、UI、delegate 与 memory |
streaming.py |
AgentEvent、ToolOutcome 和 SSE 序列化 |
turn.py |
流式轮次、并发工具调度、历史压缩、工具结果和 usage 统计 |
agent_sdk.py / mcp_server.py |
Agent SDK 和 MCP 的公共适配层 |
这层抽象的价值不在于减少 import,而在于把安全规则放到所有运行路径都会经过的位置。docs/safety.md 也明确说明:Messages API、SDK toolset 和 MCP server 都通过同一个执行器执行工具,因此写在工具调用内部的规则可以跨路径生效。
3.2 角色核心:后端接口是业务系统的端口
shopping-agent/core/shopping_agent/backend.py 定义了 StorefrontBackend,覆盖目录搜索、商品详情、购物车、偏好、订单、政策和履约选项,并提供账户上下文、披露和 checkout handoff 等可选扩展。
merchant-agent/core/merchant_agent/backend.py 定义了 MerchantBackend,覆盖经营快照、指标序列、活动表现、listing、库存告警、订单问题、定价上下文,以及 stage_*、apply_change、discard_change 等变更接口。
两个接口都遵守同一个边界:凭证和真实业务调用只在服务端发生,模型只能看到方法返回的数据。后端接口因此既是业务适配层,也是模型与企业系统之间的反腐层(Anti-Corruption Layer):平台内部的商品、订单、仓库、数据仓库等复杂模型,被收敛成 Agent 可以理解的 Pydantic 领域对象。
四、架构主线:一次请求如何穿过系统
4.1 静态 Prompt 与动态上下文分离
两个角色的 prompt.py 都把请求拆成两部分:
- 静态系统块:身份、长期规则、工具使用方式和 Skills 索引。它在 Agent 构造时生成,并设置缓存断点;
- 动态上下文块:当前小时、用户或商户上下文、购物车、记忆事实、当前页面等,每个 turn 预取后生成。
工具列表也按固定顺序构造,并通过 with_tool_cache_control() 给最后一个工具设置缓存断点。build_request_messages() 只在发给模型的副本上移动 rolling breakpoint,不修改宿主保存的历史。
这种拆分解决了两个经常被忽略的问题:
- per-request 数据不会让静态系统 Prompt 和工具定义每轮失去缓存;
- 动态上下文的变化是可解释的:购物车写入、页面切换、保存记忆或小时变化,才会导致对应上下文重新计算。
4.2 Skills 采用渐进式披露
每个角色有五个 SKILL.md 流程。静态 Prompt 只放技能名称和描述,模型通过 load_skill 在请求匹配时读取具体流程。工具描述负责“什么时候调用”,Prompt 负责高频通用规则,Skill 负责某条业务流程的步骤与边界。
这种分工避免了把所有流程细节塞进系统 Prompt,也让一个垂直应用可以通过新增目录扩展能力,而不必复制整个 Agent。
4.3 stream_turn 的核心循环
以 shopping_agent_runtime/orchestrator.py 为例,一次 turn 的主流程可以概括为:
async def stream_turn(messages, session, state):
# 1. 并行预取 profile、cart、account、memory
context = build_dynamic_context(...)
system = build_system_blocks(static_system, context)
for round_index in range(max_tool_iterations + 1):
# 2. 首轮可以被 grounding 规则固定到某个读取工具
# 3. 最后一轮强制 tool_choice = none
response = await stream_model(system, messages, tool_choice)
# 4. 工具输入闭合后立即执行,和模型剩余输出重叠
outcomes = await dispatcher.collect(response.tool_uses)
messages.append(tool_results(outcomes))
# 5. 干净的 presentation round 可以直接结束 turn
if round_closes_turn(outcomes):
break
yield turn_complete(...)
源码中的实现还处理了几个生产中很容易遗漏的细节:
EagerDispatcher在流式content_block_stop后就启动工具,减少模型生成与后端等待的串行时间;StreamedRound支持 presentation 工具的ui_partial,卡片可以在输入逐渐生成时更新;- 流式工具输入不是合法 JSON 时,
salvage_round()会保留已生成的轮次,并让模型重新发送调用,而不是把半截输入当成真实请求; finally会为未完成的 tool use 补上结果或错误,避免宿主把一个无法继续的对话历史保存下来;- 达到
max_tool_iterations后,最后一轮不再提供工具,防止 Agent 无限循环。
4.4 共享执行器与失败梯度
BaseToolExecutor.execute() 是跨角色、跨路径的关键收敛点。它把模型输入分成 status 行和真正的工具参数,再按固定顺序执行:能力开关、Skill、presentation、delegate、领域 handler。
其失败处理可以抽象为:
async def execute(name, raw_input):
try:
return await dispatch(name, raw_input)
except InvalidArguments as error:
return ToolOutcome.error(format_invalid_arguments(error))
except Exception as error:
if domain_outcome := domain_error(error):
return domain_outcome
log_exception(name, error)
return ToolOutcome.error(unavailable_text(name))
结果不会简单地把异常抛给模型或宿主,而是区分 ok、error 和 blocked。例如 provenance 或 approval gate 产生的是正常工具结果,但状态为 blocked 并带有 gate 名称;后端暂时不可用则返回安全的 unavailable 文案。这样一来,模型可以继续完成当前 turn,宿主也可以用统一的事件协议渲染工具轨迹。
4.5 事件协议连接后端与前端
commerce_common/streaming.py 定义的事件包括:
| 事件 | 用途 |
|---|---|
text_delta |
增量文本 |
tool_call / tool_result |
工具开始、结束和状态 |
ui_partial / ui |
流式或最终 UI 组件 |
cart_update |
购物车写入后的完整购物车 |
change_update |
商户变更状态变化后的完整记录 |
progress |
分析 delegate 的进度信息 |
turn_complete |
stop reason、usage、耗时和历史压缩信息 |
examples/web-shared/ 的 TypeScript protocol.ts 镜像这套协议,前端不需要理解模型的原始响应,只需要消费 Agent 事件。对于 UI 工具,模型只负责选择记录 id、布局和解释;商品名称、价格、指标和变更 diff 由服务端根据 session provenance 再次关联。
五、两个角色的核心机制
5.1 Shopping Agent:把“推荐”限制在已见过的记录
购物侧最值得注意的不是搜索工具,而是购物车写入前的 provenance 约束。shopping_agent/gates.py 中的 check_provenance() 要求 product_id 必须来自本 session 的目录或订单工具结果;购物车已有的行可以作为更新和删除的例外。
添加商品还要经过第二层 options gate:如果搜索返回的是带 options 的 family,而不是具体 variant,add_to_cart 会被 hold,并要求模型从详情中的 variants 选择一个具体 id。这样模型不能凭空拼出一个尺寸、颜色或 SKU。
真正写购物车时还有三道限制:
- 单行数量被
max_quantity_per_item截断; - 购物车行数被
max_cart_lines限制; - 同一 session 的购物车读改写使用异步锁串行化,避免同一轮并发工具调用产生覆盖。
但仓库没有把这些 gate 当成完整业务规则。StorefrontBackend 的文档明确要求后端仍然原子地检查库存、资格和平台限制,因为进程内锁不能覆盖多 worker 或外部服务。
购物侧的 checkout 也体现了“最小权限”原则:它只生成订单摘要并让宿主渲染自己的结账页面。若使用平台 hosted checkout,URL 在模型调用结束后由 checkout_handoff() 加到 UI payload,模型永远看不到支付 URL,也没有支付凭证或下单方法。
5.2 Merchant Agent:把写操作设计成提案生命周期
商户侧把写操作建模为一个小型状态机:
STAGED ── operator approval ──> APPLIED
│
└──────── operator/agent ────> DISCARDED
merchant_agent/changes.py 的 ChangeLedger 为示例后端提供了 stage()、apply() 和 discard()。StagedChange 记录 change_id、变更类型、字段级 before/after、创建者、批准者、时间戳、guardrail notes 和利润影响。
check_guardrails() 在 stage 时检查:
- 单次变更的条目数;
- 价格变化幅度和促销折扣深度;
- 补货数量与活动预算;
- 受保护字段;
- listing update 不允许携带的 price/stock 字段;
- 同一个 target + field 在一次变更中重复出现。
这些限制不是只在提案阶段检查一次。check_apply_change() 在应用前按当前配置重新执行 guardrail,然后按顺序检查:
known = state.seen_changes.get(change_id)
if known is None:
return held("provenance")
if check_guardrails(known.kind, known.items, config):
return held("guardrail")
if config.require_host_approval and change_id not in state.approved_change_ids:
return held("approval")
return None
因此,“模型说 approve”不等于“系统已经批准”。默认模式下,只有宿主 Portal 的批准按钮或 SDK toolset 的 host_approve() 会写入 approved_change_ids。在 Managed Agents 路径上,平台的 always_ask 确认就是批准面,所以 MCP server 使用与该平台确认机制相匹配的配置。
5.3 分析 delegate:把复杂查询隔离成只读子任务
商户 Agent 可选地注册 run_analysis delegate。它不是把 SQL 直接暴露给主模型,而是把简短分析目标交给一个独立的 delegate,delegate 再使用只读读取工具或受限 SQL 查询,最终返回经过 schema 校验的 AnalysisResult。
merchant_agent/analysis.py 和 runtime 层共同约束了这条路径:
- 查询必须是单条只读
SELECT,并经过check_analysis_sql(); - 行数、字符数、查询超时和 delegate 次数都有上限;
- 分析结果不能增加可用于写操作的 provenance;
- delegate 的进度通过
progress事件流向 Portal,而不是让主模型输出冗长过程。
这是一个很实用的职责切分:主 Agent 负责和运营人员沟通与做出行动建议,分析子任务负责在受限数据面上计算结果,写操作仍然只能走 merchant executor 的变更闸门。
5.4 Presentation Extension:垂直 UI 的扩展点
公共包把 UI 组件抽象为 PresentationComponent,其核心步骤是:
- Pydantic 校验模型传入的 payload;
- 根据 session state 检查 id 是否有 provenance;
- 通过
enrichhook 从后端补全真实数据; - 生成
ui事件交给宿主渲染。
垂直应用可以通过 PresentationExtension 增加自己的日历、地图、费用明细或行程组件,但不能覆盖内置组件名。这个扩展点让领域 UI 与核心 Agent 解耦:旅游只增加行程展示,票务只增加座位图和费用披露,不需要 fork 整套 Agent。
六、依赖关系:七个 Python 包加一个前端工作区
根目录的 requirements.txt 通过 editable install 安装七个仓库内包:
commerce-common
shopping-agent-core
shopping-agent-runtime
shopping-agent-sdk
merchant-agent-core
merchant-agent-runtime
merchant-agent-sdk
它们的依赖关系可以概括为:
| 包 | 依赖重点 | 作用 |
|---|---|---|
commerce-common |
anthropic、pydantic、PyYAML |
公共执行、安全、事件和适配机制 |
shopping-agent-core |
commerce-common、pydantic |
购物领域模型、后端接口、工具和 gates |
shopping-agent-runtime |
common、shopping core、anthropic |
Messages API turn loop |
shopping-agent-sdk |
common、shopping core、claude-agent-sdk、mcp |
Agent SDK toolset 与控制台 |
merchant-agent-core |
commerce-common、pydantic |
商户领域模型、变更、guardrails |
merchant-agent-runtime |
common、merchant core、anthropic |
Messages API turn loop 与分析 delegate |
merchant-agent-sdk |
common、merchant core、claude-agent-sdk、mcp |
Agent SDK toolset 与审批控制台 |
仓库还把运行时依赖锁在 requirements.txt 中,例如 Python 3.11+、anthropic、pydantic、claude-agent-sdk、mcp、FastAPI 和 Uvicorn。每个角色的 core/runtime 是独立 pyproject.toml,但 sibling package 使用同一个 0.1.0.dev0 版本并从本地目录安装,避免误解析到公共包索引。
前端部分则是 examples/package.json 管理的 npm workspace:八个 Next.js 应用共享 web-shared,每个垂直保留自己的 storefront 和 merchant portal 组件。这样形成了“Python 负责 Agent 与后端协议、TypeScript 负责事件消费和视觉呈现”的边界。
七、设计模式:六个模式的落点与分工
前面几节按“怎么运行”展开,这一节把散落其中的设计模式收敛成一张表:
| 设计模式 | 代码落点 | 解决的问题 |
|---|---|---|
| Ports and Adapters | StorefrontBackend / MerchantBackend + 四个垂直 mock backend |
业务系统替换不重写 Prompt 和工具协议 |
| Template Method + Strategy | BaseToolExecutor + 角色 executor + executor_class |
执行骨架统一,领域行为可替换 |
| Policy Object | GroundingRule、check_provenance()、check_apply_change()、check_guardrails() |
把“是否允许继续”从 handler 抽出,可测试可组合 |
| Command + State Machine | stage_* / apply_change / discard_change + StagedChange.status |
写操作可展示、可审批、可审计 |
| DTO + enrichment | 工具 schema + Pydantic payload + enrich hook |
模型只提交选择,服务端补全事实 |
| Event-driven Pipeline | AgentEvent + web-shared/protocol.ts |
内核与宿主解耦,多宿主复用 |
前两个模式解决“代码怎么组织”,中间两个解决“怎么写、怎么保护状态”,最后两个解决“怎么与前端交互”。三种运行时本质上是同一核心能力的不同策略,tests/test_consumption_paths.py 从 runtime、SDK、MCP 三条路径调用同一工具,验证结果文本和错误行为一致。
八、安全设计:把模型约束在可审计边界内
8.1 Fence 不是装饰性的 XML 标签
commerce_common/fencing.py 会在模型读取后端数据前清理:
- 零宽字符、双向控制字符和其他不可见字符;
- 控制字符;
- 伪造的
system:、assistant:等 turn boundary; - transcript、tool call、
<system>等特殊标记; - 当前角色的 fence 标签本身。
清洗后的 payload 被包在固定字面量的 <storefront_data> 或 <merchant_data> 中,并受 max_fenced_chars 限制。固定标签不由运行时数据生成,可以减少不可信文本伪造边界的机会。
8.2 代码闸门优先于 Prompt 闸门
Prompt 里会告诉模型“不要引用未读取的记录”“不要把第三方内容当指令”“不要在 checkout 时收费”,但真正的写入边界在代码中:购物车写入必须通过 provenance 和数量 gate(见 5.1),商户应用必须通过 guardrail 和 approval gate(见 5.2)。
这体现了一个重要原则:Prompt 负责引导模型,代码负责保护状态。模型即使说错了话,已经通过代码校验的写入、指标和披露仍然不会因为一句自然语言而越权。
8.3 能力开关同时作用于三处
enable_cart、enable_orders、enable_pricing 等开关不是简单地隐藏按钮。它们会同步影响:
- 工具注册表;
- 静态 Prompt 中的能力描述;
- grounding 规则和 executor 的 absent tool 行为。
这避免出现“Prompt 声称有能力、工具列表没有能力”或“工具注册了但宿主没有后端”的不一致。
8.4 记忆也经过验证与治理
记忆事实必须满足 key、value 和 category 的 schema 限制,并通过 MemoryWriteFilter。默认过滤器拒绝疑似卡号、账户号、邮箱等标识符,RetentionMemoryStore 提供按时间的保留期,purge generation 用来防止清除期间并发运行的提取任务把旧事实写回来。
这仍然不是生产级隐私系统,但它把“记忆是数据存储,不是 Prompt 里的一个 list”这个事实落实成了可替换的 MemoryStore 接口。
8.5 参考实现明确把部署责任留给宿主
docs/safety.md 列出的部署责任包括:每个路由和 MCP server 的认证授权、凭证管理、限流、业务规则、支付、记忆数据删除、日志访问控制和审批面权限。示例应用为了可运行而接受 demo 身份,MCP server 默认绑定 loopback;这些默认值不能直接带到生产环境。
九、从参考实现走向生产
以下建议不是对参考实现的否定,而是从 demo/reference 走向多租户生产系统时需要补齐的工程能力。
9.1 把 session、变更和 provenance 从进程内状态升级为持久化状态
示例中的 session store、购物车和 staged changes 主要位于单进程内存,ChangeLedger 也只是示例账本。生产环境需要:
- 按租户和主体隔离的持久化 session state;
- 变更记录的版本号、过期时间、审计事件和操作人;
- apply/discard 的幂等键;
- 多 worker 下的乐观锁或分布式锁。
当前购物车 gate 的进程内锁只能防同一进程内的并发,真正的一致性仍应由后端事务和幂等接口保证。
9.2 建立统一的路径能力矩阵
三条运行路径有意保留差异:Managed Agents 由平台控制 tool choice 和确认,Messages API 执行 runtime grounding,SDK 的分析路径也不同。随着自定义工具增加,最好生成一张机器可校验的 capability matrix,明确每个工具在三条路径上的:
- 注册方式;
- 参数 schema;
- 是否需要确认;
- 是否有 server enrichment;
- 是否支持 partial event;
- 是否受哪个 gate 保护。
这样可以把现在依赖 scripts/check.py 和跨路径测试维护的知识,提升为显式的发布契约。
9.3 增强可观测性与 Agent Eval
项目已经有 FakeClient、跨路径 contract tests、smoke chat、verify_all.py 和插件中的 eval 能力。生产环境还可以在此基础上增加:
- OpenTelemetry trace,把一次 turn、模型轮次、工具调用、gate 结果和后端请求串起来;
- 按 tool、gate、租户统计延迟、失败率、blocked 次数和 token/cache 命中;
- 对“模型说了什么”和“系统实际改变了什么”分别评分;
- 记录可脱敏的 replay fixture,用于 Prompt、schema 和模型版本升级回归。
9.4 为后端适配层增加可靠性策略
目前 backend 接口已经把“未提供”“暂不可用”“业务拒绝”区分开,但真实外部服务还会有超时、限流、部分成功和版本漂移。可以在宿主层补充:
- per-backend timeout、重试和 circuit breaker;
- 读操作的短时缓存与 stale-while-revalidate;
- 写操作的幂等键和 outbox;
- 领域 schema 的版本号和兼容迁移;
- 对多平台 connector 的统一错误码。
9.5 把记忆、日志与写操作纳入完整治理
默认过滤器能挡住一部分标识符,但生产仍需要按业务定义敏感字段、同意与撤回、导出与删除、跨设备同步、加密和访问审计。尤其要谨慎处理 DEBUG 日志:源码文档已经提示,DEBUG 请求体可能包含整个购物车和注入的记忆事实。
商户写操作同理:check_guardrails() 已经覆盖数量、价格、预算和保护字段,但生产还应把库存冻结、价格生效窗口、税费、币种、市场/卖家范围和人工职责分离放到后端事务中。Agent 层的 guardrail 适合做第一道快速反馈,不能替代最终业务规则和审批系统。
十、总结:把模型能力放进一个可控的系统
commerce-agents 的核心价值不在于它演示了多少商品搜索工具,而在于它把一个业务 Agent 拆成了可以分别验证的层次:
commerce-common统一安全、记忆、执行器、事件和 Prompt 组装;- 两个 role core 通过
Backend接口隔离具体业务系统; - Messages API、Agent SDK、Managed Agents 三条路径共享工具契约与关键执行逻辑;
- presentation tool 让模型选择事实、服务端补全事实;
- shopping 的 provenance gate 限制“能写哪些商品”;
- merchant 的 staged change 和 host approval 限制“什么时候能写入真实系统”;
- 测试和派生文件检查则把跨路径一致性变成可执行约束。
如果要从这份源码提炼一条最值得复用的经验,可以概括为:把 Prompt 当作行为指南,把工具描述当作路由,把 Skill 当作流程,把后端接口当作业务边界,把代码 gate 当作最后的权限线。 只有这样,Agent 才不只是“能调用工具的模型”,而是一个可以被宿主接入、被测试、被审批和被审计的业务执行组件。
「真诚赞赏,手留余香」
真诚赞赏,手留余香
使用微信扫描二维码完成支付