Agent-native 架构:代码终结之后,应用该如何构建
Agent-native 架构:代码终结之后,应用该如何构建
原文:Agent-native Architectures: How to Build Apps After Code Ends
作者:Dan Shipper(Every) & Claude
说明:以下为原文的忠实中文翻译,仅做语言转换与必要的技术术语规范,不引入任何原文之外的观点或补充说明。
为什么是现在(Why now)
软件代理(Agents)现在终于可以可靠运行了。
Claude Code 证明了一件事:当一个大型语言模型(LLM)可以访问 bash 和文件系统,并在一个循环中持续运行直到目标完成时,它可以自主完成复杂的多步骤任务。
一个出人意料的发现是:一个真正优秀的编码代理,本质上也是一个优秀的通用型代理。
同一套架构,既可以让 Claude Code 重构代码库,也可以让代理整理文件、管理阅读清单,或自动化工作流。
Claude Code SDK 让这种模式变得可构建。你可以构建一种应用:功能不再是你写在代码里的逻辑,而是你描述一个结果,由代理使用工具,在循环中不断判断和调整,直到结果达成。
这开启了一个新的软件领域:将 Claude Code 的工作方式,应用到编程以外的所有软件类别。
核心原则(Core principles)
1. 对等性(Parity)
用户通过 UI 能做到的任何事情,代理也必须能通过工具完成。
这是最基础的原则。如果没有对等性,其它一切都不成立。必须确保代理拥有能够实现 UI 所有能力的工具。
测试方法:任选一个 UI 操作,代理是否能完成?
2. 粒度(Granularity)
工具应当是原子能力。功能是代理在循环中实现的结果。
工具是一种原始能力。功能是通过 prompt 描述的结果,由代理使用工具,在循环中不断执行,直到结果达成。
测试方法:当你想改变行为时,是修改 prompt,还是重构代码?
3. 可组合性(Composability)
在原子化工具和对等性的前提下,你可以仅通过编写新的 prompt 来创建新功能。
例如,一个“每周回顾”功能,只是一个 prompt:
1 | |
代理会使用诸如 list_files、read_file 等工具,并依靠自身判断,直到结果完成。你描述的是结果,而不是过程。
4. 涌现能力(Emergent capability)
代理可以完成你没有明确设计过的事情。
循环过程如下:
- 构建原子化工具并保证对等性
- 用户提出你未预料到的请求
- 代理组合工具尝试完成(或失败)
- 你观察用户真实提出的需求
- 为常见模式添加领域工具或 prompt
- 重复这一过程
测试方法:代理是否能处理你这个领域中的开放式请求?
5. 随时间改进(Improvement over time)
Agent-native 应用可以通过上下文积累和 prompt 的不断调整而持续改进,而无需发布新的代码。
改进来自三个层面:
- 上下文积累:通过文件在会话之间保留状态
- 开发者级别的 prompt 更新
- 用户级别的 prompt 定制
原则的实践(Principles in practice)
以下细节使上述五项原则真正可操作。
对等性(Parity)
设想一个笔记应用,用户可以通过界面创建、组织和标记笔记。如果用户对代理说:“创建一条会议总结并标记为紧急”,而代理无法完成这一操作,那么代理就会被卡住。
解决方法是:确保代理拥有可以完成 UI 所有结果的工具。这不是要求 UI 按钮与工具一一对应,而是要求结果层面的能力对等。
纪律要求:每当添加一个 UI 能力,都要问:代理是否也能实现这一结果?如果不能,就补充相应的工具或原语。
粒度(Granularity)
关键转变在于:代理是在追求一个结果,而不是执行一个预先编排的步骤序列。它可以遇到意外情况、调整策略或提出澄清问题,循环会持续,直到结果达成。
工具越原子,代理的灵活性越强。如果你把判断逻辑写进工具中,实际上是把决策权又放回了代码。
可组合性(Composability)
这种方式既适用于开发者,也适用于用户。你可以通过添加 prompt 来发布新功能,用户也可以通过修改 prompt 或创建自己的 prompt 来定制行为。
前提是:工具足够原子,并且代理与用户具备对等能力。如果工具中封装了过多逻辑,可组合性就会被破坏。
涌现能力(Emergent capability)
示例:用户请求“将我的会议记录与任务列表交叉对照,告诉我有哪些已经承诺但尚未安排时间的事项”。即使你从未构建过承诺追踪功能,只要代理可以读取会议记录和任务,它就能完成。
这揭示了潜在需求。你不需要预先猜测用户需要什么,而是通过观察他们让代理做什么来发现需求。
随时间改进(Improvement over time)
代理可以维护跨会话状态,记录已存在的内容、用户行为以及哪些方法有效。
Prompt 的优化可以发生在多个层级:开发者级更新、用户级定制,以及更高级的代理自我调整(需要安全机制)。
工具:从原语到领域工具(From primitives to domain tools)
应当从最基础的原语开始,例如 bash、文件操作和基础存储。这可以验证架构是否成立,并揭示代理真正需要的能力。
当模式逐渐清晰时,可以有意识地添加领域工具,用于:
- 统一术语
- 添加必要的校验
- 提升效率
领域工具应当代表用户视角中的一个概念性动作,而不是封装判断逻辑。判断是否执行某事,应当由 prompt 决定。
文件作为通用接口(Files as the universal interface)
代理天生擅长处理文件。Claude Code 能成功的原因之一,是 bash 加文件系统构成了最成熟、最通用的代理接口。
文件具有以下特性:
- 代理天然理解
- 对用户可检查、可编辑
- 易于导出和备份
- 可在设备之间同步
- 具有自解释性
一个总体原则是:如果一个人类能够理解你的结构,代理大概率也能理解。
Agent 执行模式(Agent execution patterns)
完成信号(Completion signals)
代理需要一种显式的方式来表示“我已经完成”。不要通过启发式规则来判断完成状态。
1 | |
完成(completion)与成功 / 失败是两个正交的概念:
- 一个工具可以成功并停止循环
- 一个工具也可以失败,但仍然指示继续循环以进行恢复
目前仍未标准化的是更丰富的控制流信号,例如:
- pause —— 代理需要用户输入后才能继续
- escalate —— 代理需要超出自身权限的人类决策
- retry —— 瞬时错误,应由调度器自动重试
当前实践中,如果代理需要输入,通常会在文本响应中直接询问。还不存在正式的“阻塞等待输入”状态,这是一个仍在探索中的领域。
模型层级选择(Model tier selection)
并非所有代理操作都需要同等水平的智能。
| 任务类型 | 模型层级 | 原因 |
|---|---|---|
| 研究型代理 | 平衡型 | 工具循环 + 良好推理 |
| 对话 | 平衡型 | 对话速度足够 |
| 复杂综合 | 强模型 | 多来源分析 |
| 快速分类 | 快模型 | 高吞吐、低复杂度 |
纪律要求:在添加新代理时,应根据任务复杂度显式选择模型层级,而不是默认使用“最强模型”。
部分完成(Partial completion)
1 | |
对于多步骤任务,应在任务级别跟踪进度。UI 可以显示:
1 | |
部分完成的常见场景:
- 达到最大迭代次数:已完成的任务保留,保存 checkpoint,后续可继续
- 单个任务失败:该任务标记失败,其它任务是否继续由代理自行判断
- 网络错误:当前迭代抛出异常,会话标记失败,checkpoint 保留
上下文限制(Context limits)
代理会话可以无限延续,但上下文窗口不是。
设计原则:
- 工具应支持渐进式精化(先摘要,再细化,再全文)
- 给代理提供中途压缩知识的能力(例如“总结目前已知内容并继续”)
- 假设上下文终将填满,并从一开始就为此设计
实现模式(Implementation patterns)
共享工作区(Shared workspace)
代理与用户应当在同一数据空间中工作,而不是隔离的沙箱。
1 | |
好处包括:
- 用户可以检查并修改代理的工作成果
- 代理可以在用户创建的内容基础上继续工作
- 无需额外的同步层
- 完全透明
这是默认选择。只有在明确需求(安全、避免破坏关键数据)时才引入沙箱。
上下文注入(Context injection)
代理需要知道它正在处理什么。系统提示应包含:
可用资源
1 | |
能力范围
1 | |
近期活动
1 | |
对于长会话,应提供刷新上下文的机制,以保持代理状态最新。
Agent 与 UI 通信(Agent-to-UI communication)
代理的行为应立即反映在 UI 中。推荐的事件类型:
1 | |
关键原则:不允许静默行为。
实时反馈包括:
- 展示代理当前思考内容
- 展示正在执行的工具
- 流式输出文本
- 实时更新任务进度
通信方式:
- 共享数据存储(推荐)
- 文件系统监听
- 事件系统(更解耦,但更复杂)
部分工具调用较为嘈杂,可使用 ephemeralToolCalls 标志隐藏内部检查,同时保留关键动作可见。
沉默的代理会让人感觉“坏掉了”;可见的进展能建立信任。
产品层面的影响(Product implications)
Agent-native 架构不仅改变了软件如何构建,也改变了产品呈现给用户的方式。
渐进式揭示(Progressive disclosure)
产品应当上手即用,同时没有能力上限。
简单的请求无需学习成本即可完成,而高级用户可以不断向系统施加更复杂、出乎意料的要求。
Excel 是一个经典例子:
- 它既可以是一个简单的杂货清单
- 也可以是一个复杂的财务模型
Claude Code 也具有这种特性。界面始终保持简单,但能力会随着用户提出的请求而扩展。
这一模式包含三个特征:
- 低门槛入口:最基础的请求可以立即生效
- 可发现的深度:用户在探索中逐渐发现系统的能力
- 没有天花板:高级用户可以推动系统做出你从未预期的事情
代理在能力层面与用户保持同步,它不会要求用户先“学会如何使用它”。
潜在需求的发现(Latent demand discovery)
构建一个能力充足的基础系统,然后观察用户让代理去做什么。
传统的产品开发流程是:
- 设想用户需要什么
- 构建功能
- 验证是否命中需求
Agent-native 的流程是:
- 构建一个能力完备的基础
- 观察用户向代理提出的请求
- 将反复出现的模式正式化
当用户请求代理完成某件事并成功时,这是信号;当请求失败时,这同样是信号,它揭示了工具缺失或对等性不足。
随着时间推移,你可以:
- 为高频模式添加领域工具(更快、更可靠)
- 为常见请求创建专用 prompt(更易发现)
- 移除几乎无人使用的工具(简化系统)
在这种模式下,代理本身成为理解用户真实需求的研究工具。
审批与用户自主权(Approval and user agency)
Needs validation
以下框架来自 Claude 在构建过程中提出的观点,目前尚未经过充分验证,Dan 仍在形成自己的判断。
当代理开始主动采取行动(而非仅响应用户明确请求)时,你需要决定给予它多大的自主权。这取决于两个因素:风险等级(stakes) 与 可逆性(reversibility)。
| 风险等级 | 可逆性 | 模式 | 示例 |
|---|---|---|---|
| 低 | 易 | 自动执行 | 整理文件 |
| 低 | 难 | 快速确认 | 发布到信息流 |
| 高 | 易 | 建议后执行 | 代码修改 |
| 高 | 难 | 显式审批 | 发送邮件 |
注意:该框架仅适用于代理的主动行为。如果用户明确指示代理执行某事(例如“发送这封邮件”),那本身就构成了授权。
自我修改必须是可理解的(Self-modification should be legible)
当代理可以修改自身行为(例如更改 prompt、更新偏好或调整工作流)时,设计目标是:
- 用户能够看到发生了什么变化
- 用户能够理解这些变化的影响
- 用户能够随时回滚
审批流程是一种实现方式;带有回滚能力的审计日志是另一种。核心原则是:让变化是可理解、可追溯的。
移动端(Mobile)
移动端是 agent-native 应用的一等平台,它既有独特的限制,也有独特的机会。
一个文件系统
代理可以天然地使用文件进行工作,使用的仍然是与其它平台一致的原语。
丰富的上下文
移动端是一个“围墙花园”,但你可以访问到极其丰富的上下文:健康数据、位置、照片、日历等——这些在桌面或 Web 上并不存在。
本地应用
每个用户都有自己的一份应用副本。应用可以按用户分叉、自我演进。
应用状态自动同步
借助 iCloud,所有设备可以共享同一套文件系统。代理的工作成果会自动出现在所有设备上,而无需构建服务器。
挑战
代理通常是长时间运行的,而移动应用并不是。
一个代理任务可能需要 30 秒、5 分钟,甚至 1 小时才能完成。但 iOS 会在应用短时间不活跃后将其置于后台,并可能直接终止以回收内存。用户可能在任务执行过程中切换应用、接听电话或锁屏。
这意味着移动端 agent 应用必须认真处理以下问题:
- Checkpoint(检查点):保存状态,避免工作丢失
- Resume(恢复):中断后从上次位置继续
- 后台执行:高效利用 iOS 提供的有限后台时间
- 本地 vs 云端:决定哪些内容在本地执行,哪些需要服务器
iOS 存储架构
Needs validation
这是我们正在尝试的一种方案,效果令人兴奋,但它只是众多可能方案中的一种。该方案主要由 Claude 实现,更优解仍有待探索。
这种架构带来的好处包括:
- 无需构建基础设施即可实现设备间自动同步
- 无需用户操作即可完成备份
- 当 iCloud 不可用时可优雅降级
- 用户在必要时可以在应用外部访问自己的数据
一种实现方式是:iCloud 优先,本地兜底。
- iCloud 容器(优先)
1 | |
- 本地 Documents(兜底)
1 | |
- 迁移层
- 自动将本地数据迁移到 iCloud
1 | |
Checkpoint 与恢复(Checkpoint and resume)
Needs validation
该方案来自 Claude 在实际构建过程中的经验,目前运行良好,但并非最终答案。
移动应用随时可能被中断,代理必须具备生存能力。
需要保存的内容包括:
- 代理类型
- 消息记录
- 迭代次数
- 任务列表
- 自定义状态
- 时间戳
保存时机:
- 应用进入后台时
- 每次工具返回结果后
- 长时间操作过程中定期保存
恢复流程:
- 加载被中断的会话
- 根据有效期过滤(默认 1 小时)
- 向用户展示恢复提示
- 恢复消息并继续代理循环
恢复步骤:
loadInterruptedSessions()扫描 checkpoint 目录filter by isValid(maxAge:)- 展示恢复提示
- 恢复消息并继续代理循环
- 结束后删除 checkpoint
1 | |
架构取舍:可以存储完整的代理配置,也可以只存储 agentType 并从注册表中重建。后者更简单,但旧 checkpoint 可能因配置变更而失效。
关键差距在于:如果系统直接杀死应用,恢复能力取决于 checkpoint 的频率。为了最大鲁棒性,应在每次工具返回后保存。
云端文件状态(Cloud file states)
文件可能存在于 iCloud,但尚未下载到本地。在读取之前,应确保文件可用。
1 | |
存储抽象层(Storage abstraction)
不要直接使用 FileManager。应当构建一层存储抽象,屏蔽 iCloud 与本地文件系统的差异。
1 | |
这样可以保证其余代码无需关心底层存储位置。
后台执行(Background execution)
Needs validation
以下模式来自 Claude 的实践经验。
iOS 提供的后台执行时间非常有限(约 30 秒):
1 | |
这段时间应当用于:
- 尽可能完成当前工具调用
- 保存 checkpoint
- 平滑过渡到后台状态
对于真正需要长时间运行的代理,应考虑使用服务器端调度器运行,移动端仅作为展示与输入界面。
本地 vs 云端(On-device vs cloud)
| 组件 | 本地 | 云端 |
|---|---|---|
| 调度 | ✓ | |
| 工具执行(文件、照片、健康数据) | ✓ | |
| LLM 调用 | ✓(Anthropic API) | |
| Checkpoint | ✓(本地文件) | 可选(iCloud) |
| 长时间运行代理 | 受 iOS 限制 | 可行 |
应用在推理时需要网络,但在离线状态下仍可访问本地数据。工具设计应在网络不可用时优雅降级。
高级模式(Advanced patterns)
动态能力发现(Dynamic capability discovery)
Needs validation
以下模式来自 Claude 在构建过程中的实践探索,Dan 仍在形成自己的判断。针对不同用例,可能存在更优方案。
在与外部 API 集成时,一种常见做法是:为 API 的每一个端点构建一个对应的工具。但这种静态映射存在明显问题。
静态映射的问题
1 | |
这种方式限制了代理的能力范围,并增加了维护成本。
动态能力发现
1 | |
这是将“粒度”原则推向逻辑极限的结果:
- 工具足够原子
- 能够作用于构建时尚不存在的类型
何时使用动态能力发现
- 外部 API,希望代理拥有与用户等价的访问能力(如 HealthKit、HomeKit、GraphQL)
- 系统能力会随时间扩展
- 希望代理能够访问 API 支持的全部内容
何时静态映射已经足够
- 有意限制范围的代理
- 需要对访问内容进行严格控制
- API 简单、稳定、端点固定
该模式的核心是:
一个工具用于发现能力,一个工具用于访问任意已发现的能力。
将校验交给 API 本身,而不是在工具定义中通过枚举提前固化。
CRUD 完整性(CRUD completeness)
对系统中的每一种实体,都应确认代理具备完整的 CRUD 能力:
- Create:是否能创建?
- Read:是否能查看已有内容?
- Update:是否能修改?
- Delete:是否能删除?
审计方法
列出系统中的所有实体,并逐一检查这四种操作是否都对代理开放。
常见失败场景
你实现了 create_note 和 read_notes,但忘记了 update_note 和 delete_note。当用户让代理“修正我会议记录里的一个错别字”时,代理将无能为力。
从代理到代码(Graduating to code)
有些操作最终需要从“代理协调”升级为“优化后的代码实现”,以满足性能或可靠性要求。
一个常见演进路径是:
代理使用原语在循环中完成任务
灵活,用于验证概念为常见操作添加领域工具
更快,仍由代理主导将高频路径实现为优化代码
快速、确定性强
重要前提
即使某个操作已经“毕业”为代码实现:
- 代理仍然应该能够触发该优化路径
- 并在遇到边缘情况时,回退到原始原语
“毕业”只关乎效率,而不是能力限制。对等性原则仍然成立。
动态系统的设计直觉
随着系统复杂度的提升:
- 不要急于为每一种情况编写代码
- 先让代理通过原语探索问题空间
- 再将稳定、高频的模式固化为工具或代码
这样,你构建的是一个可生长的系统,而不是一组僵化的功能。
反模式(Anti-patterns)
以下做法并不一定是“错误”的,在某些场景下也可能是合理的选择。但它们并不符合本文所描述的 agent-native 架构,因此有必要明确区分。
将 Agent 作为路由器(Agent as router)
在这种模式下,代理的职责只是:
- 理解用户意图
- 选择并调用正确的函数
代理的智能仅用于分发请求,而不是执行任务本身。
这种方式是可行的,但你只使用了代理能力的一小部分。
先构建应用,再添加 Agent(Build the app, then add agent)
你先用传统方式实现功能(以代码形式),然后再把这些功能暴露给代理。
结果是:
- 代理只能做你已经明确构建过的事情
- 系统不会产生涌现能力
这种路径会让你错过 agent-native 架构的核心价值。
请求 / 响应式思维(Request/response thinking)
代理接收输入,执行一次操作,然后返回输出。
这种模式忽略了 循环(loop):
- agent-native 的核心是给代理一个“要达成的结果”
- 代理在过程中处理意外情况
- 直到结果完成
如果你的代理只是“一问一答”,那它仍然停留在传统范式中。
防御性过强的工具设计(Defensive tool design)
你因为习惯了防御性编程,而在工具中加入了大量限制:
- 严格的枚举
- 过度的输入校验
- 多层权限检查
这在传统系统中是安全的,但在 agent-native 架构中会:
- 限制代理处理未知情况的能力
- 阻断涌现行为
应当将判断权留给代理,而不是全部写进工具。
幸福路径在代码里,Agent 只是执行者(Happy path in code)
你在代码中处理了所有边界情况,代理只负责调用。
这意味着:
- 决策仍然在代码中
- 代理只是一个执行接口
agent-native 的思路是:
- 让代理处理边界情况
- 让代码提供原语能力
具体反模式示例
Agent 执行你的工作流,而不是追求结果
1 | |
1 | |
工作流形态的工具(Workflow-shaped tools)
像 analyze_and_organize 这样的工具,将判断逻辑封装进工具内部。
应当将其拆分为原语,让代理自行组合。
孤立的 UI 行为(Orphan UI actions)
用户可以通过 UI 完成某个操作,但代理无法完成同样的结果。
修复方式:维持 对等性(parity)。
上下文饥饿(Context starvation)
代理不知道系统中“已经存在什么”。
用户说:“整理我的笔记”,但代理甚至不知道有笔记存在。
修复方式:
- 向 system prompt 注入可用资源
- 注入能力范围
无理由的能力门控(Gates without reason)
某个领域工具是唯一可行路径,但你并没有真正打算限制访问。
默认原则应当是:开放。只有在安全或数据完整性确有需要时才引入门控。
人为制造的能力限制(Artificial capability limits)
出于模糊的安全担忧而限制代理能力。
正确做法是:
- 保留能力
- 通过审批流程控制高风险操作
而不是直接移除能力。
本可动态却静态映射(Static mapping where dynamic would work better)
当“发现 + 访问”模式可以带来更强灵活性时,却构建了大量静态工具。
这会降低系统的可扩展性和未来适应能力。
启发式完成判断(Heuristic completion detection)
通过以下方式判断代理是否完成:
- 连续几轮没有工具调用
- 检查是否生成了某个文件
这种方式极其脆弱。
修复方式:
- 要求代理显式发出完成信号
这些反模式的共同特征是:
将判断重新塞回代码,而不是交给代理。
成功标准(Success criteria)
以下清单用于判断你的系统是否真正符合 agent-native 架构。它既是设计时的自检表,也是实现后的验收标准。
架构(Architecture)
- 代理能够完成用户通过 UI 能完成的任何事情(对等性)
- 工具是原子能力;领域工具只是快捷方式,而不是唯一通路(粒度)
- 可以通过编写新的 prompt 来添加新功能(可组合性)
- 代理能够完成你未明确设计过的任务(涌现能力)
- 改变行为意味着修改 prompt,而不是重构代码
实现(Implementation)
- system prompt 中包含可用资源与能力说明
- 代理与用户在同一数据空间中工作
- 代理的行为能够立即反映在 UI 中
- 系统中的每一种实体都具备完整的 CRUD 能力
- 外部 API 在合适场景下使用动态能力发现
- 代理通过显式信号声明完成,而不是依赖启发式判断
产品(Product)
- 最简单的请求可以立即生效,无学习成本
- 高级用户可以将系统推向你未预期的方向
- 你通过观察用户让代理做什么来学习真实需求
- 审批与自主权设计与风险等级和可逆性相匹配
移动端(Mobile)
- Checkpoint / Resume 能够应对应用中断
- 采用 iCloud 优先、本地兜底的存储策略
- 后台执行能够高效利用有限时间
终极测试(The ultimate test)
向代理描述一个属于你应用领域内,但你从未为其构建过专门功能的结果。
问题只有一个:
它能否在循环中自行推理、组合工具,直到完成这个结果?
- 如果答案是 是 —— 你构建的是一个真正的 agent-native 系统。
- 如果答案是 否 —— 你的架构仍然过于受限。