Agent-Native 架构完全指南:当代码终结之后,如何构建应用

原文标题: Agent-Native Architectures: How to Build Apps After Code Ends 作者: Dan Shipper & Claude(合著) 来源: Every.to 配套视频: YouTube 配套代码: Compound Engineering Plugin(7.5k Stars)


目录

  1. 引言:为什么是现在
  2. 五大核心原则
  3. 从原语到领域工具
  4. 文件作为通用接口
  5. Context.md 模式
  6. 文件与数据库的取舍
  7. 冲突管理
  8. Agent 执行模式
  9. 实现模式
  10. 产品层面的启示
  11. 移动端专属架构
  12. 高级模式
  13. 反模式(Anti-Patterns)
  14. 成功标准清单
  15. 配套工具:Compound Engineering Plugin

1. 引言:为什么是现在

"Software agents work reliably now."(软件 Agent 现在已经可以可靠地工作了。)

这篇指南的核心前提是:大语言模型(LLM)+ 工具访问能力 + 循环执行,这三者的结合使得 AI Agent 能够自主完成复杂的多步骤任务。

作者在开发 Reader(阅读应用)和 Anecdote(笔记/知识管理应用)的过程中总结出了这套架构思想。核心洞察来自 Claude Code 的实践:

"A really good coding agent is actually a really good general-purpose agent." (一个真正好的编程 Agent,实际上就是一个真正好的通用 Agent。)

这意味着 Claude Code 展示的能力——读取文件、编辑代码、执行命令、在循环中追求目标——可以推广到所有软件领域。Agent 不再是"附加功能",而应该成为应用架构的一等公民。


2. 五大核心原则

2.1 对等性(Parity)

定义: 用户通过 UI 能完成的所有操作,Agent 必须也能通过工具完成。

测试方法: 随便选一个 UI 操作——Agent 能完成它吗?如果不能,就是架构缺陷。

为什么重要:

  • 如果 Agent 无法执行某些操作,它就永远无法自主完成涉及这些操作的任务
  • 对等性是其他四个原则的基础
  • 用户看到 Agent 的能力边界时会失去信任

2.2 粒度(Granularity)

"Tools should be atomic primitives. Features are outcomes achieved by an agent operating in a loop." (工具应该是原子化的原语。功能是 Agent 在循环中运行所达成的结果。)

核心纪律: 要改变行为,应该修改 prompt(提示词),而不是重构代码。

举例:

  • ❌ 一个 processDocument() 工具,内部包含分类、摘要、标签、存储等所有逻辑
  • ✅ 分离的 classify()summarize()tag()store() 工具,由 Agent 根据 prompt 自行编排

2.3 可组合性(Composability)

"With atomic tools and parity, you can create new features just by writing new prompts." (有了原子工具和对等性,你只需编写新的 prompt 就能创建新功能。)

经典示例——"每周回顾"功能:

传统方式需要写一整套代码。Agent-Native 方式只需一个 prompt:

"回顾本周所有笔记和项目进展,总结关键进展,识别未完成的任务,
 生成一份简洁的周报并保存到 /reviews/ 目录。"

Agent 利用已有的文件读取、搜索、写入工具,在循环中自主完成这一切。

2.4 涌现能力(Emergent Capability)

Agent 能够通过组合现有工具,完成开发者从未预想过的任务。这揭示了"潜在需求"(latent demand)——通过观察用户向 Agent 提出什么请求来指导产品开发。

"You're discovering, not guessing."(你是在发现需求,而不是猜测需求。)

信号模式:

  • 成功信号: 用户请求 → Agent 成功完成 = 确认了功能需求
  • 失败信号: 用户请求 → Agent 失败 = 暴露了工具/对等性的差距

2.5 持续改进(Improvement Over Time)

Agent-Native 应用可以在不发布新代码的情况下持续改进:

维度 方式 示例
累积上下文 状态通过 context 文件持久化 Agent 记住用户偏好、项目进展
开发者级 prompt 优化 系统 prompt 迭代 改进指令措辞、增加示例
用户级 prompt 优化 用户自定义指令 用户设定个性化规则
自我修改(需谨慎) Agent 修改自身行为 自动调整偏好设置

3. 从原语到领域工具

3.1 演进路径

阶段1:原语阶段
  Agent 使用基础原语在循环中工作 → 灵活性最高,验证概念

阶段2:领域工具阶段
  为常见操作添加领域特定工具 → 更快速,仍由 Agent 编排

阶段3:热路径优化阶段
  对高频路径用优化代码实现 → 最快速,确定性执行

3.2 领域工具的设计原则

一个领域工具 = 一个概念上的用户操作

  • 领域工具包含机械性验证(参数类型检查、格式校验等)
  • 判断应该留在 prompt 中,而不是硬编码在工具逻辑里
  • 始终保留原语的可用性——领域工具是快捷方式,不是大门(shortcuts, not gates)
# ❌ 错误:把判断逻辑编码在工具里
def process_email(email):
    if email.is_urgent:          # 工具在做判断
        priority = "high"
    category = classify(email)    # 工具在做分类
    store(email, priority, category)

# ✅ 正确:工具只做机械操作,判断留给 Agent
# 工具:store_email(email, priority, category)
# Prompt:"评估邮件紧急程度(1-5),进行分类,然后存储。紧急度 ≥4 时发送通知。"

3.3 何时添加领域工具

  • 某个操作模式反复出现(Agent 经常用 3-4 个原语完成同一件事)
  • 需要性能优化(原语组合太慢)
  • 需要原子性保证(多个操作要么全成功要么全失败)
  • 需要锚定"领域词汇",让 Agent 和用户有共同语言

4. 文件作为通用接口

"Design for what agents can reason about—what would make sense to a human."

Agent 天然擅长处理文件,原因有五:

优势 说明
已知 Agent 天然精通 bash/文件系统原语(ls, cat, mkdir, cp 等)
可检查 用户能直接看到、编辑、删除 Agent 的工作成果
可移植 导出/备份轻而易举;数据归用户所有
跨设备同步 iCloud 实现无服务器的多设备同步
自文档化 /projects/acme/notes/ 比数据库查询更易读

推荐目录结构

Documents/
├── AgentCheckpoints/          # 临时数据(Agent 会话检查点)
│   └── {sessionId}.checkpoint
├── AgentLogs/                 # 调试日志
│   └── {type}/{sessionId}.md
└── Research/                  # 用户的实际工作内容
    └── books/{bookId}/
        ├── full_text.txt      # 主要内容
        ├── notes.md           # 用户笔记
        └── agent_log.md       # Agent 操作记录

实体范围的命名规范

文件类型 命名模式 示例
实体数据 {entity}.json library.json
人类可读内容 {content_type}.md introduction.md
Agent 推理记录 agent_log.md 每个实体一个
主要内容 full_text.txt 下载的文本
多卷内容 volume{N}.txt volume1.txt
外部来源 {source_name}.md wikipedia.md
检查点 {sessionId}.checkpoint 基于 UUID
配置 config.json 功能设置

命名规范: 小写字母加下划线(my_file.md),不用驼峰命名。Markdown 用于人类可读内容;JSON 用于结构化数据。


5. Context.md 模式

Context.md 是 Agent 的可移植工作记忆。Agent 在每次会话开始时读取它,在状态变化时更新它。

推荐结构

# Context

## 我是谁(Who I Am)
[Agent 角色描述——我是什么类型的 Agent,我的职责是什么]

## 我对用户的了解(What I Know About This User)
- 兴趣画像
- 偏好设置
- 当前阅读/项目

## 现有资源(What Exists)
- 可用的资源清单
- 活跃的项目
- 用户配置

## 近期活动(Recent Activity)
- 最近操作的时间线

## 行为准则(My Guidelines)
- 行为约束
- 个性化规则

## 当前状态(Current State)
- 待处理任务
- 上次同步时间戳

为什么有效:

  • 可移植性: 纯文本文件,任何系统都能读取
  • 透明性: 用户可以直接查看和编辑 Agent "记住了什么"
  • 无代码修改: 改变 Agent 行为只需编辑这个文件
  • 跨会话连续性: Agent 在新会话中能"记住"之前的上下文

6. 文件与数据库的取舍

"Files for legibility, databases for structure. When in doubt, files." (文件用于可读性,数据库用于结构性。拿不定主意时,选文件。)

使用文件 使用数据库
用户需要阅读/编辑的内容 高频结构化数据
从版本控制中受益的配置 需要复杂查询的数据
Agent 生成的工作成果 临时状态(会话、缓存)
任何需要透明性的东西 关系型数据
大段文本内容 需要索引的数据

7. 冲突管理

当 Agent 和用户(或多个 Agent)同时操作文件时:

策略 说明 优缺点
原子写入 最后写入者获胜 简单,但可能丢失修改
iCloud 冲突监控 监测同步冲突,生成 {filename} (conflict).md 可检测但需要处理逻辑
分离空间 Agent 写入草稿区,用户确认后合并 安全但增加复杂度
追加式日志 只追加不修改 永不冲突但文件会增长
文件锁定 操作前锁定文件 严格但可能造成死锁

实际建议: 日志和状态文件很少冲突。对于用户可编辑的内容,考虑将 Agent 输出与用户空间分开。


8. Agent 执行模式

8.1 完成信号(Completion Signals)

Agent 需要显式的完成机制,而不是启发式检测:

struct ToolResult {
    let success: Bool        // 操作是否成功
    let output: String       // 输出内容
    let shouldContinue: Bool // 是否继续循环
}

.success("结果")    // 操作成功,继续循环
.error("错误信息")   // 操作失败,Agent 可以重试
.complete("完成")   // 任务完成,停止循环

8.2 模型层级选择

任务类型 推荐层级 理由
研究 Agent 均衡型(Balanced) 需要工具循环和良好推理
聊天对话 均衡型(Balanced) 速度足够快
复杂综合分析 强力型(Powerful) 多来源分析需要强推理
快速分类 快速型(Fast) 高频量、简单任务

纪律: 根据任务复杂度显式选择层级;避免默认使用最强力的模型。

8.3 部分完成追踪

struct AgentTask {
    var status: TaskStatus  // pending, in_progress, completed, failed, skipped
    var notes: String?      // 失败原因、已完成的内容
}

var isComplete: Bool {
    tasks.allSatisfy { $0.status == .completed || $0.status == .skipped }
}

异常场景处理:

场景 处理方式
Agent 达到最大迭代次数 保存检查点,后续可恢复继续
Agent 在某个任务上失败 标记为失败并记录原因;其他任务可继续
网络错误 会话标记为失败;检查点保存到出错之前

8.4 上下文窗口限制

必须从一开始就为有限的上下文窗口做设计:

  • 迭代精炼工具: 支持"摘要 → 详情 → 完整"的分层访问
  • 中途整合: Agent 能在会话中期将已获取信息进行"压缩整合"
  • 检查点预期: 假设上下文终将被填满——从一开始就为此设计

9. 实现模式

9.1 共享工作空间(Shared Workspace)

Agent 和用户应该在同一个数据空间中工作,而不是分隔的沙箱。

UserData/
├── notes/           ← Agent 和用户都可以读/写
├── projects/        ← Agent 组织,用户可覆盖
└── preferences.md   ← Agent 读取,用户编辑

原则: 默认共享;仅在有具体安全需求时才使用沙箱隔离。

9.2 上下文注入(Context Injection)

系统 prompt 应包含:

类别 内容 示例
可用资源 数据清单 "你有 42 条笔记、3 个项目"
能力描述 可用操作 "你可以创建、编辑、标签、搜索、组织"
近期活动 用户操作时间线 "用户最近编辑了项目 A"

9.3 Agent 与 UI 的通信

enum AgentEvent {
    case thinking(String)         // 显示"思考中"指示器
    case toolCall(String, String) // 显示正在使用的工具
    case toolResult(String)       // 显示工具结果(可选)
    case textResponse(String)     // 流式输出到聊天界面
    case statusChange(Status)     // 更新状态栏
}

"Silent agents feel broken. Visible progress builds trust." (沉默的 Agent 让人觉得它坏了。可见的进展能建立信任。)

考虑使用 ephemeralToolCalls 标志——隐藏内部检查操作,只显示有意义的动作。


10. 产品层面的启示

10.1 渐进式披露(Progressive Disclosure)

"Excel is the canonical example: grocery list or financial model, same tool."

特征 说明
简单入口 基础请求无需学习曲线即可完成
可发现的深度 用户在探索中发现新的能力
无天花板 高级用户能把系统推到开发者未曾预想的方向

10.2 潜在需求发现(Latent Demand Discovery)

传统方式: 想象功能 → 构建 → 看是否正确

Agent-Native 方式: 构建有能力的基础 → 观察用户请求什么 → 将涌现的模式正式化

"The agent becomes a research instrument for understanding what your users actually need."

迭代循环:

  1. 观察用户请求
  2. 对常见模式添加领域工具
  3. 为高频请求创建专用 prompt
  4. 移除未使用的工具
  5. 重复

10.3 审批与用户自主权

风险等级 可逆性 模式 示例
低风险 易逆转 自动执行 整理文件
低风险 难逆转 快速确认 发布到动态流
高风险 易逆转 建议+执行 代码修改
高风险 难逆转 明确审批 发送邮件

自我修改的可理解性原则: 当 Agent 修改自身行为时,必须确保可见性、可理解性、可回滚。


11. 移动端专属架构

11.1 独特优势与核心挑战

优势: 原生文件系统访问、丰富上下文(健康数据、位置、照片、日历)、本地应用个性化进化、iCloud 无服务器同步。

核心挑战:

"Agents are long-running. Mobile apps are not."

iOS 在应用进入后台后几秒钟就会暂停甚至终止它。必须有健壮的检查点、恢复和后台执行策略。

11.2 iOS 存储架构:iCloud 优先,本地兜底

if let url = fileManager
    .url(forUbiquityContainerIdentifier: nil) {
    return url.appendingPathComponent("Documents")
}
return fileManager.urls(
    for: .documentDirectory,
    in: .userDomainMask)[0]

推荐目录结构:

iCloud.com.{bundleId}/Documents/
├── Library/            # 用户的"图书馆"
├── Research/books/     # 研究资料
├── Chats/              # 聊天历史
└── Profile/            # 用户档案

11.3 检查点与恢复

struct AgentCheckpoint: Codable {
    let agentType: String              // Agent 类型
    let messages: [[String: Any]]      // 消息历史
    let iterationCount: Int            // 迭代计数
    let taskListJSON: String?          // 任务列表
    let customState: [String: String]  // 自定义状态
    let timestamp: Date                // 时间戳
}

func isValid(maxAge: TimeInterval = 3600) -> Bool {
    Date().timeIntervalSince(timestamp) < maxAge
}

恢复流程:

  1. 加载中断的会话 → 扫描检查点目录
  2. 过滤有效性 → 默认1小时窗口
  3. 向用户显示恢复提示
  4. 恢复消息并继续 Agent 循环
  5. 用户关闭时删除检查点

11.4 后台执行策略

iOS 只给约 30 秒后台时间:

func prepareForBackground() {
    backgroundTaskId = UIApplication.shared
        .beginBackgroundTask(withName: "AgentProcessing") {
            handleBackgroundTimeExpired()
        }
}

func handleBackgroundTimeExpired() {
    for session in sessions where session.status == .running {
        session.status = .backgrounded
        Task { await saveSession(session) }
    }
}

func handleForeground() {
    for session in sessions where session.status == .backgrounded {
        Task { await resumeSession(session) }
    }
}

策略优先级: 完成当前工具调用 → 保存检查点 → 优雅过渡到 backgrounded 状态。

长时间运行 Agent: 考虑服务端编排器(可运行数小时),移动应用只作为查看器/输入机制。

11.5 设备端 vs 云端

组件 设备端 云端
编排
工具执行(文件、照片、HealthKit)
LLM 调用 ✓(Anthropic API)
检查点 ✓(本地) 可选(iCloud)
长时间运行 Agent 受 iOS 限制 可行(需服务器)

12. 高级模式

12.1 动态能力发现(Dynamic Capability Discovery)

两个通用工具替代为每个 API 端点写专用工具:

list_available_types() → ["steps", "heart_rate", "sleep", ...]
read_data(type)        → 读取任意已发现类型的数据

适用场景: 外部 API 需要完整访问(HealthKit、HomeKit、GraphQL);系统会增加新能力;需要灵活性。

不适用: 需要严格约束的 Agent;稳定简单的 API。

12.2 CRUD 完整性审计

对每一个实体,验证四种操作都可用:

操作 检查问题
Create Agent 能否创建新实例?
Read Agent 能否查看已有实例?
Update Agent 能否修改实例?
Delete Agent 能否删除实例?

常见遗漏:create_noteread_notes,但忘了 update_notedelete_note


13. 反模式(Anti-Patterns)

架构级反模式

反模式 描述 问题
Agent 作为路由器 只识别意图然后调用函数 只用了 Agent 能力的一小部分
先建应用,再加 Agent 传统构建功能,Agent 只做已有的事 错失涌现能力
请求/响应思维 收到输入,做一件事,返回输出 错过循环追求目标的能力
防御性工具设计 过度约束(严格枚举、验证层) 阻止意外创新
代码编码快乐路径 代码处理所有边界情况 决策在代码中而非 Agent 判断中

最典型反模式——Agent 执行你的工作流而非追求结果

# ❌ 错误:你编写了工作流
def process_request(input):
    category = categorize(input)      # 你的代码在做决策
    priority = score_priority(input)   # 你的代码在做决策
    store(input, category, priority)
    if priority > 3: notify()          # 你的代码在做决策

# ✅ 正确:Agent 在循环中追求结果
# 工具:store_item, send_notification
# Prompt:"评估紧急程度1-5,用你的评估结果存储,紧急度 ≥4 时发送通知。"

完整反模式清单

  • 工作流形状的工具 — 将判断逻辑捆绑进单个工具
  • 孤立 UI 操作 — 用户能做但 Agent 不能做
  • 上下文饥饿 — Agent 不知道已有什么数据
  • 无理由的门控 — 不必要地限制访问权限
  • 人为能力限制 — 没有具体风险却限制能力
  • 该动态却用静态映射 — 硬编码而非动态发现
  • 启发式完成检测 — 用猜测而非显式信号判断完成(脆弱)

14. 成功标准清单

架构层面

  • Agent 能完成用户通过 UI 能完成的所有操作(对等性
  • 工具是原子化原语;领域工具是快捷方式(粒度
  • 新功能通过 prompt 添加(可组合性
  • Agent 能完成未预想的任务(涌现能力
  • 行为变更通过 prompt 编辑,而非代码重构

实现层面

  • 系统 prompt 包含可用资源和能力描述
  • Agent 和用户在同一数据空间中工作
  • Agent 操作立即反映在 UI 中
  • 每个实体都有完整的 CRUD 能力
  • 外部 API 适当使用动态发现
  • Agent 使用显式信号报告完成

产品层面

  • 简单请求无需学习曲线即可完成
  • 高级用户能将系统推向意想不到的方向
  • 通过观察请求来学习用户需求
  • 审批要求与风险等级和可逆性匹配

移动端

  • 检查点/恢复机制处理应用中断
  • iCloud 优先存储,本地兜底
  • 后台执行明智使用可用时间

终极测试

向 Agent 描述一个属于你应用领域内、但你没有为之构建特定功能的目标。它能在循环中自行找出实现方法直到成功吗? 如果能,你就构建了一个真正的 Agent-Native 应用。


15. 配套工具:Compound Engineering Plugin

核心理念: "Each unit of engineering work should make subsequent units easier—not harder."

工作流循环

Plan(计划)→ Work(执行)→ Review(评审)→ Compound(沉淀)→ 重复
命令 用途
/workflows:plan 将功能创意转化为详细实施方案
/workflows:work 使用 worktree 和任务管理执行
/workflows:review 多 Agent 代码审查
/workflows:compound 记录学习成果以备复用

工程哲学

80/20 分配: 80% 精力用于计划和评审,20% 用于执行。与传统比例恰好相反,目的是维持高代码质量并减少技术债务。

安装方式

Claude Code:

/plugin marketplace add https://github.com/EveryInc/compound-engineering-plugin
/plugin install compound-engineering

OpenCode:

bunx @every-env/compound-plugin install compound-engineering --to opencode

Codex:

bunx @every-env/compound-plugin install compound-engineering --to codex

总结:Agent-Native 的思维转变

传统思维 Agent-Native 思维
功能是代码编写的结果 功能是 prompt 描述的结果
工具面向用户设计 工具面向 Agent 设计
猜测用户需要什么 观察用户向 Agent 请求什么
每次更新都需要发版 改进通过 prompt 和上下文迭代
应用有固定功能边界 应用的能力边界是动态的、可涌现的
数据透明可选 数据默认透明

核心格言: "Features are outcomes you describe, achieved by an agent with tools." 功能是你描述的成果,由拥有工具的 Agent 来实现。


本文档基于 Every.to 原文整理。