名称: 代理原生架构 描述: 构建以代理为一等公民的应用程序。在以下情况下使用此技能:设计自主代理、创建MCP工具、实现自我修改系统,或构建应用程序,其中功能是由代理在循环中操作达成的结果。
<为什么现在>
为什么现在
软件代理现在工作可靠。Claude Code 展示了,一个具有访问bash和文件工具的LLM,在循环中操作直到目标达成,可以自主完成复杂的多步骤任务。
令人惊讶的发现:一个非常优秀的编码代理实际上是一个非常优秀的通用代理。 相同的架构让Claude Code重构代码库,也可以让代理组织您的文件、管理您的阅读列表或自动化您的工作流。
Claude Code SDK 使这变得可访问。您可以构建应用程序,其中功能不是您编写的代码——它们是您描述的结果,由具有工具的代理达成,在循环中操作直到结果达成。
这开启了一个新领域:以Claude Code方式工作的软件,应用于远超出编码的类别。 </为什么现在>
<核心原则>
核心原则
1. 对等性
用户通过UI能做的任何事情,代理应该能够通过工具达成。
这是基本原则。没有它,其他都不重要。
想象您构建一个笔记应用,具有创建、组织和标记笔记的美丽界面。用户要求代理:“创建一个总结我会议的笔记并标记为紧急。”
如果您为创建笔记构建了UI但没有代理的相同能力,代理就卡住了。它可能会道歉或请求澄清,但无法帮助——即使该操作对人类使用界面来说是微不足道的。
解决方案: 确保代理有工具(或工具组合)可以达成UI能做的任何事情。
这不是关于创建UI按钮到工具的1:1映射。这是关于确保代理可以达成相同的结果。有时这是一个单一工具(create_note)。有时是组合原语(write_file到笔记目录,具有适当格式化)。
纪律: 当添加任何UI能力时,问:代理能达成这个结果吗?如果不能,添加必要的工具或原语。
能力映射有助于:
| 用户动作 | 代理如何达成 |
|---|---|
| 创建笔记 | write_file到笔记目录,或create_note工具 |
| 标记笔记为紧急 | update_file元数据,或tag_note工具 |
| 搜索笔记 | search_files或search_notes工具 |
| 删除笔记 | delete_file或delete_note工具 |
测试: 选择用户在UI中可以采取的任何动作。向代理描述。它能达成结果吗?
2. 粒度
偏好原子原语。功能是代理在循环中操作达成的结果。
工具是原语能力:读文件、写文件、运行bash命令、存储记录、发送通知。
功能不是您编写的函数。它是一个您在提示中描述的结果,由具有工具的代理达成,在循环中操作直到结果达成。
更粗粒度(限制代理):
工具:classify_and_organize_files(files)
→ 您编写了决策逻辑
→ 代理执行您的代码
→ 要改变行为,您重构
更细粒度(授权代理):
工具:read_file, write_file, move_file, list_directory, bash
提示:“组织用户的下载文件夹。分析每个文件,
基于内容和最近性确定适当位置,
并将它们移动到那里。”
代理:在循环中操作—读文件、做判断、移动东西、
检查结果—直到文件夹组织好。
→ 代理做决策
→ 要改变行为,您编辑提示
关键转变: 代理以判断追求结果,不是执行编排好的序列。它可能遇到意外文件类型、调整其方法或请求澄清。循环持续直到结果达成。
您的工具越原子,代理使用它们就越灵活。如果您将决策逻辑捆绑到工具中,您已将判断移回代码中。
测试: 要改变功能行为,您编辑散文还是重构代码?
3. 可组合性
有了原子工具和对等性,您可以通过编写新提示创建新功能。
这是前两个原则的回报。当您的工具是原子且代理能做用户能做的任何事情时,新功能就只是新提示。
想要一个“每周回顾”功能,总结活动并建议优先级?那是一个提示:
“回顾本周修改的文件。总结关键更改。基于
未完成项目和接近的截止日期,建议下周
三个优先级。”
代理使用list_files、read_file及其判断来达成这个。您没有编写每周回顾代码。您描述了一个结果,代理在循环中操作直到达成。
这对开发者和用户都有效。 您可以通过添加提示发布新功能。用户可以通过修改提示或创建自己的来定制行为。“当我说‘归档这个,’总是移动到我的行动文件夹并标记为紧急”成为用户级别的提示,扩展应用程序。
约束: 这仅当工具足够原子以以您未预期的方式组合,且代理与用户对等时才有效。如果工具编码太多逻辑,或代理无法访问关键能力,组合就失效。
测试: 您能通过编写新提示部分添加新功能,而不添加新代码吗?
4. 涌现能力
代理可以完成您未明确设计的事情。
当工具是原子、对等性保持、且提示可组合时,用户会要求代理做您从未预料的事情。而且通常,代理能弄清楚。
“交叉参考我的会议笔记和我的任务列表,告诉我我承诺了什么但尚未安排。”
您没有构建“承诺跟踪器”功能。但如果代理能读笔记、读任务、并推理它们——在循环中操作直到有答案——它就能完成这个。
这揭示了潜在需求。 与其猜测用户想要什么功能,您观察他们要求代理做什么。当模式涌现时,您可以用领域特定工具或专用提示优化它们。但您不必预期它们——您发现了它们。
飞轮效应:
- 用原子工具和对等性构建
- 用户要求您未预期的事情
- 代理组合工具完成它们(或失败,揭示差距)
- 您观察被请求内容的模式
- 添加领域工具或提示以使常见模式高效
- 重复
这改变了您构建产品的方式。您不是试图预先想象每个功能。您创建一个有能力的基础,并从涌现中学习。
测试: 给代理一个与您领域相关的开放式请求。它能想出一个合理的方法,在循环中操作直到成功吗?如果它只是说“我没有那个功能”,您的架构太受限了。
5. 随时间改进
代理原生应用程序通过积累上下文和提示改进而变得更好。
与传统软件不同,代理原生应用程序无需发布代码即可改进:
积累上下文: 代理可以在会话间维护状态——存在什么、用户做了什么、什么有效、什么无效。代理读取和更新的context.md文件是第一层。更复杂的方法涉及结构化记忆和习得偏好。
多级提示改进:
- 开发者级别: 您发布更新提示,改变所有用户的代理行为
- 用户级别: 用户为其工作流定制提示
- 代理级别: 代理基于反馈修改自己的提示(高级)
自我修改(高级): 可以编辑自己提示甚至自己代码的代理。对于生产用例,考虑添加安全防护——批准门、自动检查点以便回滚、健康检查。这是事情的走向。
改进机制仍在被发现。上下文和提示改进是已验证的。自我修改是涌现的。清楚的是:架构支持以传统软件没有的方式变得更好。
测试: 应用程序在使用一个月后比第一天更好吗,即使没有代码更改? </核心原则>
<摄入>
您需要代理原生架构哪方面的帮助?
- 设计架构 - 从零开始规划新的代理原生系统
- 文件和工作区 - 使用文件作为通用接口,共享工作区模式
- 工具设计 - 构建原语工具,动态能力发现,CRUD完整性
- 领域工具 - 知道何时添加领域工具 vs 坚持原语
- 执行模式 - 完成信号、部分完成、上下文限制
- 系统提示 - 在提示中定义代理行为,判断标准
- 上下文注入 - 将运行时应用状态注入代理提示
- 动作对等性 - 确保代理能做用户能做的任何事情
- 自我修改 - 使代理能安全地自我进化
- 产品设计 - 渐进披露、潜在需求、批准模式
- 移动模式 - iOS存储、后台执行、检查点/恢复
- 测试 - 测试代理原生应用程序的能力和对等性
- 重构 - 使现有代码更代理原生
等待响应后再进行。 </摄入>
<路由>
| 响应 | 动作 |
|---|---|
| 1, “设计”, “架构”, “规划” | 阅读 architecture-patterns.md,然后应用下面的架构检查清单 |
| 2, “文件”, “工作区”, “文件系统” | 阅读 files-universal-interface.md 和 shared-workspace-architecture.md |
| 3, “工具”, “mcp”, “原语”, “crud” | 阅读 mcp-tool-design.md |
| 4, “领域工具”, “何时添加” | 阅读 from-primitives-to-domain-tools.md |
| 5, “执行”, “完成”, “循环” | 阅读 agent-execution-patterns.md |
| 6, “提示”, “系统提示”, “行为” | 阅读 system-prompt-design.md |
| 7, “上下文”, “注入”, “运行时”, “动态” | 阅读 dynamic-context-injection.md |
| 8, “对等性”, “ui动作”, “能力映射” | 阅读 action-parity-discipline.md |
| 9, “自我修改”, “进化”, “git” | 阅读 self-modification.md |
| 10, “产品”, “渐进”, “批准”, “潜在需求” | 阅读 product-implications.md |
| 11, “移动”, “ios”, “android”, “后台”, “检查点” | 阅读 mobile-patterns.md |
| 12, “测试”, “测试”, “验证”, “确认” | 阅读 agent-native-testing.md |
| 13, “审查”, “重构”, “现有” | 阅读 refactoring-to-prompt-native.md |
阅读参考后,将这些模式应用于用户的特定上下文。 </路由>
<架构检查清单>
架构审查检查清单
设计代理原生系统时,在实现前验证这些:
核心原则
- [ ] 对等性: 每个UI动作都有相应的代理能力
- [ ] 粒度: 工具是原语;功能是提示定义的结果
- [ ] 可组合性: 新功能可以仅通过提示添加
- [ ] 涌现能力: 代理能处理您领域的开放式请求
工具设计
- [ ] 动态 vs 静态: 对于外部API,代理应具有完全访问权限时,使用动态能力发现
- [ ] CRUD完整性: 每个实体都有创建、读取、更新和删除
- [ ] 原语非工作流: 工具启用能力,不编码业务逻辑
- [ ] API作为验证器: 当API验证时,使用
z.string()输入,非z.enum()
文件和工作区
- [ ] 共享工作区: 代理和用户在同一数据空间工作
- [ ] context.md模式: 代理读取/更新上下文文件以积累知识
- [ ] 文件组织: 实体范围目录,具有一致命名
代理执行
- [ ] 完成信号: 代理有明确的
complete_task工具(非启发式检测) - [ ] 部分完成: 多步骤任务跟踪进度以便恢复
- [ ] 上下文限制: 从一开始设计为有界上下文
上下文注入
- [ ] 可用资源: 系统提示包括存在什么(文件、数据、类型)
- [ ] 可用能力: 系统提示用用户词汇记录工具
- [ ] 动态上下文: 上下文为长时间会话刷新(或提供
refresh_context工具)
UI集成
- [ ] 代理 → UI: 代理更改反映在UI中(共享服务、文件监视或事件总线)
- [ ] 无静默动作: 代理写入立即触发UI更新
- [ ] 能力发现: 用户可以学习代理能做什么
移动(如果适用)
- [ ] 检查点/恢复: 优雅处理iOS应用挂起
- [ ] iCloud存储: iCloud优先,本地回退以进行多设备同步
- [ ] 成本意识: 模型层选择(Haiku/Sonnet/Opus)
设计架构时,在您的计划中明确处理每个复选框。 </架构检查清单>
<快速启动>
快速启动:构建代理原生功能
步骤1:定义原子工具
const tools = [
tool("read_file", "读任何文件", { path: z.string() }, ...),
tool("write_file", "写任何文件", { path: z.string(), content: z.string() }, ...),
tool("list_files", "列目录", { path: z.string() }, ...),
tool("complete_task", "信号任务完成", { summary: z.string() }, ...),
];
步骤2:在系统提示中写入行为
## 您的责任
当被要求组织内容时,您应该:
1. 读取现有文件以理解结构
2. 分析什么组织有意义
3. 使用您的工具创建/移动文件
4. 使用您的判断关于布局和格式化
5. 完成后调用complete_task
您决定结构。让它好。
步骤3:让代理在循环中工作
const result = await agent.run({
prompt: userMessage,
tools: tools,
systemPrompt: systemPrompt,
// 代理循环直到它调用complete_task
});
</快速启动>
<参考索引>
参考文件
所有参考在references/中:
核心模式:
- architecture-patterns.md - 事件驱动、统一编排器、代理到UI
- files-universal-interface.md - 为什么文件、组织模式、context.md
- mcp-tool-design.md - 工具设计、动态能力发现、CRUD
- from-primitives-to-domain-tools.md - 何时添加领域工具、过渡到代码
- agent-execution-patterns.md - 完成信号、部分完成、上下文限制
- system-prompt-design.md - 功能作为提示、判断标准
代理原生纪律:
- dynamic-context-injection.md - 运行时上下文、注入什么
- action-parity-discipline.md - 能力映射、对等工作流
- shared-workspace-architecture.md - 共享数据空间、UI集成
- product-implications.md - 渐进披露、潜在需求、批准
- agent-native-testing.md - 测试结果、对等测试
平台特定:
- mobile-patterns.md - iOS存储、检查点/恢复、成本意识
- self-modification.md - 基于Git的进化、防护措施
- refactoring-to-prompt-native.md - 迁移现有代码 </参考索引>
<反模式>
反模式
不完全代理原生的常见方法
这些不一定错——它们可能适合您的用例。但值得识别为不同于本文档描述的架构。
代理作为路由器 — 代理弄清楚用户想要什么,然后调用正确的函数。代理的智能用于路由,非行动。这可以工作,但您只使用了代理能做的部分。
先构建应用,然后添加代理 — 您以传统方式构建功能(作为代码),然后向代理暴露它们。代理只能做您的功能已经做的事。您不会得到涌现能力。
请求/响应思维 — 代理获取输入,做一件事,返回输出。这错过了循环:代理获取要达成的结果,操作直到完成,沿途处理意外情况。
防御性工具设计 — 您过度约束工具输入,因为您习惯于防御性编程。严格的枚举、每一层的验证。这是安全的,但它阻止代理做您未预期的事情。
代码中的快乐路径,代理只执行 — 传统软件在代码中处理边缘情况——您编写当X出错时发生什么的逻辑。代理原生让代理以判断处理边缘情况。如果您的代码处理所有边缘情况,代理就只是调用者。
特定反模式
主要罪恶:代理执行您的代码而不是弄清楚事情
// 错误 - 您编写了工作流,代理只执行它
tool("process_feedback", async ({ message }) => {
const category = categorize(message); // 您的代码决定
const priority = calculatePriority(message); // 您的代码决定
await store(message, category, priority); // 您的代码编排
if (priority > 3) await notify(); // 您的代码决定
});
// 正确 - 代理弄清楚如何处理反馈
tools: store_item, send_message // 原语
prompt: “基于可操作性评分1-5,存储反馈,如果>=4则通知”
工作流形状的工具 — analyze_and_organize将判断捆绑到工具中。分解为原语,让代理组合它们。
上下文饥饿 — 代理不知道应用中存在什么资源。
用户:“在我的提要中写一些关于叶卡捷琳娜大帝的内容”
代理:“什么提要?我不理解您指的是什么系统。”
修复:注入可用资源、能力和词汇到系统提示中。
孤立UI动作 — 用户可以通过UI做某事,但代理无法达成。修复:保持对等性。
静默动作 — 代理更改状态但UI不更新。修复:使用具有反应性绑定的共享数据存储,或文件系统观察。
启发式完成检测 — 通过启发式检测代理完成(连续迭代无工具调用,检查预期输出文件)。这是脆弱的。修复:要求代理通过complete_task工具明确信号完成。
动态API的静态工具映射 — 为50个API端点构建50个工具,当discover + access模式会给出更多灵活性时。
// 错误 - 每个API类型需要一个硬编码工具
tool("read_steps", ...)
tool("read_heart_rate", ...)
tool("read_sleep", ...)
// 当添加葡萄糖跟踪时...需要代码更改
// 正确 - 动态能力发现
tool("list_available_types", ...) // 发现可用的
tool("read_health_data", { dataType: z.string() }, ...) // 访问任何类型
不完整CRUD — 代理可以创建但不能更新或删除。
// 用户:“删除那个日志条目”
// 代理:“我没有那个工具”
tool("create_journal_entry", ...) // 缺失:更新、删除
修复:每个实体需要完整CRUD。
沙盒隔离 — 代理在与用户分开的数据空间中工作。
文档/
├── user_files/ ← 用户空间
└── agent_output/ ← 代理空间(隔离)
修复:使用共享工作区,两者操作相同文件。
无原因的闸门 — 领域工具是做某事的唯一方式,而您本不打算限制访问。默认是开放的。保持原语可用,除非有特定原因闸门。
人工能力限制 — 出于模糊的安全担忧而非特定风险限制代理能做什么。谨慎地限制能力。代理通常应该能做用户能做的事。 </反模式>
<成功标准>
成功标准
您已经构建了代理原生应用程序,当:
架构
- [ ] 代理能达成用户通过UI能达成的任何事情(对等性)
- [ ] 工具是原子原语;领域工具是捷径,非闸门(粒度)
- [ ] 新功能可以通过编写新提示添加(可组合性)
- [ ] 代理能完成您未明确设计的任务(涌现能力)
- [ ] 改变行为意味着编辑提示,非重构代码
实现
- [ ] 系统提示包括关于应用状态的动态上下文
- [ ] 每个UI动作有相应的代理工具(动作对等性)
- [ ] 代理工具在系统提示中用用户词汇记录
- [ ] 代理和用户在同一数据空间工作(共享工作区)
- [ ] 代理动作立即反映在UI中
- [ ] 每个实体有完整CRUD(创建、读取、更新、删除)
- [ ] 代理明确信号完成(无启发式检测)
- [ ] context.md或等效用于积累知识
产品
- [ ] 简单请求立即工作,无学习曲线
- [ ] 高级用户可以以意外方向推动系统
- [ ] 您通过观察用户要求代理做什么来学习他们想要什么
- [ ] 批准要求匹配风险性和可逆性
移动(如果适用)
- [ ] 检查点/恢复处理应用中断
- [ ] iCloud优先存储,本地回退
- [ ] 后台执行明智使用可用时间
- [ ] 模型层匹配任务复杂性
最终测试
向代理描述一个在您应用程序领域内但您未构建特定功能的结果。
它能弄清楚如何完成它,在循环中操作直到成功吗?
如果是,您已经构建了代理原生的东西。
如果它说“我没有那个功能”——您的架构仍然太受限了。 </成功标准>