🤖 Agent 架构实战指南

从 20 个开源 Agent 项目的深度分析中,提炼出可落地的架构决策、设计模式和实现方案

§1 Agent 是什么?为什么需要专门的架构?

Agent 不是一个简单的 LLM 封装。它是一个自主决策系统——接收目标,规划步骤,调用工具,处理异常,持续迭代,直到目标达成。

与普通 LLM 调用的本质区别:

维度普通 LLM 调用Agent 系统
控制流单次请求-响应多步循环,自主决策下一步
工具无或固定动态选择、组合、创建
状态无状态需要记忆、上下文管理
错误处理抛异常自修复、重试、降级
终止条件响应完成目标达成或预算耗尽
核心洞察:在分析的 20 个项目中,9/20 采用 ReAct 循环作为核心控制流,12/20 使用 Function Calling 作为工具调用机制。这不是巧合——ReAct + Function Calling 已经成为 Agent 架构的事实标准。

§2 架构决策树:我该选什么架构?

❓ 你的任务需要多步推理和工具调用吗?
→ 不需要 Agent,直接 LLM 调用即可。用 LLM 集成方案
→ 继续判断 ↓
❓ 任务是否高度结构化(固定步骤、固定工具)?
Plan-Execute 架构状态机,见 主循环设计
→ 继续判断 ↓
❓ 需要多个 Agent 协作吗?
→ 继续判断 ↓
单 Agent ReAct,这是最简单的起点
❓ 协作模式是什么?
流水线(上游→下游)→ Orchestrator-Worker(如 MetaGPT SOP)
平等对话/协商 → Actor Model(如 AutoGen)
有向图/条件分支 → State Machine(如 LangGraph)
层级指挥 → Swarm + Handoff(如 AutoGen MagenticOne)
实战建议:从单 Agent ReAct 开始。80% 的场景不需要多 Agent。当你发现单个 Agent 的 prompt 太复杂、工具太多、或者需要不同角色时,再升级到多 Agent。

§3 六大核心架构模式

从 20 个项目中提炼出的六种架构模式,覆盖从简单到复杂的全部场景:

3.1 ReAct 循环 — 最小可行架构

ReAct(Reasoning + Acting)是 Agent 的"Hello World"。9/20 项目以此为核心。

┌─────────────────────────────────────────────┐ │ ReAct Loop │ │ │ │ User Input → [Think] → [Act] → [Observe] │ │ ↑ │ │ │ └──────────────────┘ │ │ │ │ Think: LLM 推理下一步该做什么 │ │ Act: 调用工具执行 │ │ Observe: 处理工具返回结果 │ │ │ │ 终止条件: LLM 输出 FINISH / 达到步数上限 │ └─────────────────────────────────────────────┘

谁做得最好:

Python 实现(Smolagents 风格):

class ReactAgent:
    def __init__(self, model, tools, max_steps=10):
        self.model = model
        self.tools = {t.name: t for t in tools}
        self.max_steps = max_steps

    def run(self, task: str) -> str:
        messages = [{"role": "user", "content": task}]

        for step in range(self.max_steps):
            # Think: LLM 决定下一步
            response = self.model.chat(messages)
            messages.append({"role": "assistant", "content": response})

            # 解析:提取动作和参数
            action = self.parse_action(response)
            if action is None:  # 没有动作 = 完成
                return response

            # Act: 执行工具
            tool_name, tool_input = action
            if tool_name not in self.tools:
                observation = f"Error: Tool '{tool_name}' not found"
            else:
                try:
                    observation = self.tools[tool_name].run(tool_input)
                except Exception as e:
                    observation = f"Error: {e}"

            # Observe: 把结果喂回 LLM
            messages.append({
                "role": "user",
                "content": f"Observation: {observation}"
            })

        return "Max steps reached"

# 使用
agent = ReactAgent(
    model=LiteLLM("gpt-4o"),
    tools=[WebSearch(), FileRead(), CodeRun()],
)
result = agent.run("查找 Python 3.13 的新特性并写一个摘要")
ReAct 的三大陷阱:
  1. 格式不稳定 — LLM 不一定按你期望的格式输出 Thought/Action/Observation。SWE-agent 的 8 种解析器就是为此而生
  2. 死循环 — Agent 反复执行同一个动作。OpenHands 的 StuckDetector 检测 5 种卡住模式
  3. 上下文爆炸 — 每步都追加消息,token 飙升。需要 Condenser(见 §5)

3.2 Plan-Execute — 结构化任务的正确选择

先规划,再执行。适合步骤相对固定的场景,如数据处理流水线、代码生成。

┌────────────┐ ┌────────────┐ ┌────────────┐ │ Planner │ → │ Executor │ → │ Replan? │ │ (LLM 规划) │ │ (逐步执行) │ │ (必要时) │ └────────────┘ └────────────┘ └────────────┘ │ │ └───── Plan: [Step1, Step2, ...] ─────┘

谁做得最好:

# Plan-Execute 模式
class PlanExecuteAgent:
    def __init__(self, planner_model, executor_model, tools):
        self.planner = planner_model
        self.executor = executor_model
        self.tools = tools

    def run(self, task: str) -> str:
        # Phase 1: Plan
        plan = self.planner.chat(
            f"将以下任务分解为具体步骤:\n{task}\n"
            "输出 JSON 格式: {\"steps\": [...]}"
        )
        steps = json.loads(plan)["steps"]

        # Phase 2: Execute
        results = []
        for i, step in enumerate(steps):
            result = self.executor.run(step, self.tools)
            results.append(result)

            # Phase 3: Replan if needed
            if self.needs_replan(result, steps[i:]):
                updated_plan = self.planner.chat(
                    f"步骤 {i} 的结果与预期不符:{result}\n"
                    f"剩余步骤:{steps[i+1:]}\n"
                    "请更新计划:"
                )
                steps = json.loads(updated_plan)["steps"]

        return "\n".join(results)
何时用 Plan-Execute:任务可分解、步骤相对确定、需要全局视角。如果步骤高度依赖前一步的结果且不可预测,用 ReAct 更好。

3.3 状态机 — 复杂流程的精确控制

用显式状态转移替代隐式的 LLM 决策。适合需要严格流程控制的企业场景。

┌──────────┐ │ START │ └─────┬─────┘ ▼ ┌──────────┐ 条件A ┌──────────┐ │ ANALYZE │ ────────→ │ PLAN │ └─────┬────┘ └─────┬────┘ │ 条件B │ ▼ ▼ ┌──────────┐ ┌──────────┐ │ REJECT │ │ EXECUTE │ └──────────┘ └─────┬────┘ │ ┌───────┴───────┐ ▼ ▼ ┌──────────┐ ┌──────────┐ │ SUCCESS │ │ RETRY │──→ EXECUTE └──────────┘ └──────────┘

谁做得最好:

# LangGraph 风格的状态机
from langgraph.graph import StateGraph, END

class AgentState(TypedDict):
    messages: list
    next_action: str
    retry_count: int

def analyze(state):
    # 分析用户输入
    result = llm.invoke(state["messages"])
    return {"next_action": result.action, "messages": [result]}

def plan(state):
    # 生成计划
    plan = llm.invoke(f"制定计划:{state['messages'][-1]}")
    return {"messages": [plan]}

def execute(state):
    # 执行工具
    result = tool_executor.run(state["messages"][-1].tool_calls)
    return {"messages": [result], "retry_count": 0}

def should_plan(state):
    if state["next_action"] == "complex":
        return "plan"
    return "execute"

# 构建图
graph = StateGraph(AgentState)
graph.add_node("analyze", analyze)
graph.add_node("plan", plan)
graph.add_node("execute", execute)

graph.add_conditional_edges("analyze", should_plan)
graph.add_edge("plan", "execute")
graph.add_edge("execute", END)

app = graph.compile()
LangGraph 的杀手锏 — Checkpoint:每个状态转移都可以持久化。这意味着:① 人类可以审批后继续 ② 失败后可从检查点恢复 ③ 可以 Time Travel 回到任意状态。这是生产系统的必备特性。

3.4 Actor Model — 多 Agent 对话的正确姿势

每个 Agent 是独立的 Actor,通过消息传递通信。适合需要 Agent 间协商、辩论的场景。

┌─────────────┐ message ┌─────────────┐ │ Agent A │ ──────────────→ │ Agent B │ │ (Researcher)│ ←────────────── │ (Writer) │ └─────────────┘ message └─────────────┘ │ │ │ message │ message ▼ ▼ ┌─────────────┐ ┌─────────────┐ │ Agent C │ │ Agent D │ │ (Reviewer) │ │ (Editor) │ └─────────────┘ └─────────────┘

谁做得最好:

# AutoGen 风格的 Actor Model
from autogen import ConversableAgent, GroupChat, GroupChatManager

researcher = ConversableAgent(
    "researcher",
    system_message="你是研究员,负责收集信息",
    llm_config={"model": "gpt-4o"},
    human_input_mode="NEVER",
)

writer = ConversableAgent(
    "writer",
    system_message="你是写作者,负责根据研究结果写文章",
    llm_config={"model": "gpt-4o"},
    human_input_mode="NEVER",
)

reviewer = ConversableAgent(
    "reviewer",
    system_message="你是审稿人,负责检查文章质量",
    llm_config={"model": "gpt-4o"},
    human_input_mode="NEVER",  # 或 "TERMINATE" 需要人工终审
)

# 群组对话
group_chat = GroupChat(
    agents=[researcher, writer, reviewer],
    messages=[],
    max_round=10,
    speaker_selection_method="round_robin",  # 或 "auto" (LLM选择)
)

manager = GroupChatManager(groupchat=group_chat)
researcher.initiate_chat(
    manager,
    message="请研究 AI Agent 架构的最新进展并写一篇综述",
)

3.5 Orchestrator-Worker — SOP 驱动的协作

一个中心编排器分配任务给专业 Worker。适合流水线式的复杂任务。

┌──────────────────┐ │ Orchestrator │ │ (项目经理) │ └───────┬──────────┘ │ 分配任务 ┌────────────┼────────────┐ ▼ ▼ ▼ ┌────────┐ ┌────────┐ ┌────────┐ │Worker 1│ │Worker 2│ │Worker 3│ │(PM) │ │(Coder) │ │(QA) │ └────────┘ └────────┘ └────────┘ │ │ │ └────────────┼────────────┘ ▼ ┌──────────────┐ │ 结果汇总/投票 │ └──────────────┘

谁做得最好:

# MetaGPT 风格的 SOP 编排
from metagpt.roles import Role
from metagpt.schema import Message

class ProductManager(Role):
    name: str = "Alice"
    profile: str = "Product Manager"

    async def _act(self) -> Message:
        # 生成 PRD
        prd = await self._write_prd()
        return Message(content=prd, role=self.profile)

class Architect(Role):
    name: str = "Bob"
    profile: str = "Architect"

    async def _act(self) -> Message:
        # 根据PRD设计系统架构
        design = await self._design_system()
        return Message(content=design, role=self.profile)

class Engineer(Role):
    name: str = "Charlie"
    profile: str = "Engineer"

    async def _act(self) -> Message:
        # 根据设计写代码
        code = await self._write_code()
        return Message(content=code, role=self.profile)

# SOP:PM → Architect → Engineer
async def software_sop(requirement: str):
    pm = ProductManager()
    architect = Architect()
    engineer = Engineer()

    prd_msg = await pm.run(requirement)
    design_msg = await architect.run(prd_msg)
    code_msg = await engineer.run(design_msg)
    return code_msg

3.6 自进化架构 — Agent 的终极形态

Agent 不仅执行任务,还能反思自己的表现、修改自身行为。这是目前最前沿的方向。

谁做得最好:

┌───────────────────────────────────────────────┐ │ Self-Evolving Agent │ │ │ │ ┌─────────┐ ┌──────────┐ ┌────────────┐ │ │ │ Main │ → │ Memory │ ← │ Background │ │ │ │ Loop │ │ (FAISS) │ │ Reviewer │ │ │ └─────────┘ └──────────┘ └─────┬──────┘ │ │ │ │ │ │ │ ┌──────────────────┐ │ │ │ └──→│ Behavior Log │──────┘ │ │ │ (做什么/结果如何) │ 审计+优化 │ │ └──────────────────┘ │ │ │ │ │ ▼ │ │ ┌──────────────────┐ │ │ │ Self-Modification│ │ │ │ (改prompt/工具) │ │ │ └──────────────────┘ │ └───────────────────────────────────────────────┘
自进化的安全边界:Agent 修改自身行为是双刃剑。必须设置不可逾越的约束——核心安全规则不能被自进化修改。Agent Zero 的 LLM Infection Check 就是检测外部 prompt 是否"感染"了 Agent 的核心指令。

§4 工具系统设计

工具是 Agent 的"手和脚"。工具系统的设计直接决定 Agent 的能力边界。

4.1 工具定义的三个流派

📋 声明式 (OpenAI Function Calling)

JSON Schema 定义工具签名,LLM 输出结构化调用。

✅ 标准化,跨模型兼容
✅ LLM 理解成本低
✅ 12/20 项目采用
❌ 复杂参数嵌套时描述冗长
❌ 运行时验证需额外实现
{
  "name": "web_search",
  "description": "搜索互联网",
  "parameters": {
    "type": "object",
    "properties": {
      "query": {"type": "string"},
      "max_results": {"type": "integer"}
    },
    "required": ["query"]
  }
}

🔧 类型安全式 (PydanticAI)

Python 类型注解 → 自动生成 Schema + 运行时验证。

✅ 开发体验极佳
✅ 类型即文档
✅ 运行时自动验证
❌ 绑定 Python 生态
❌ 复杂工具需手动处理
from pydantic import BaseModel

class SearchArgs(BaseModel):
    query: str
    max_results: int = 5

@agent.tool
async def web_search(
    ctx: RunContext,
    args: SearchArgs,
) -> str:
    results = await search(args.query)
    return results[:args.max_results]

📦 Bundle 式 (SWE-agent)

Shell 脚本 + YAML 定义,容器内执行。

✅ 最灵活——任何 CLI 都是工具
✅ 沙箱隔离天然支持
✅ 无需写 Python 代码
❌ 类型安全差
❌ 调试困难
❌ 跨平台兼容性差
# search.yaml
name: search
command: ./scripts/search.sh
args:
  - name: query
    type: string
  - name: max_results
    type: integer
    default: 5

4.2 工具安全:三级审批机制

不同工具有不同的风险等级。好的工具系统不是一刀切,而是分级的:

级别描述示例项目
GREEN只读、无副作用web_search, file_read所有项目
YELLOW有副作用但可逆file_write, git_commitCodex CLI (需确认)
RED不可逆或有风险rm, deploy, send_emailOpenClaw (Policy Pipeline)

最佳实践组合(参考 安全机制):

# OpenClaw 风格的 Policy Pipeline
class ToolPolicy:
    def check(self, tool: str, args: dict) -> PolicyResult:
        tool_def = self.registry.get(tool)

        # 1. 静态规则检查
        if tool_def.risk_level == "RED":
            if not self.user_approved(tool, args):
                return PolicyResult(deny=True, reason="需要用户审批")

        # 2. 动态上下文检查(Hermes 风格)
        threats = self.threat_scanner.scan(args)
        if threats:
            return PolicyResult(deny=True, reason=f"检测到威胁: {threats}")

        # 3. 沙箱执行(SWE-agent/OpenHands 风格)
        if tool_def.requires_sandbox:
            return PolicyResult(sandbox=True)

        return PolicyResult(allow=True)

# Codex CLI 风格的三级 Profile
class ApprovalProfile:
    SUGGEST = "suggest"   # 建议但不阻止
    AUTO_EDIT = "auto-edit"  # 文件编辑自动通过
    FULL_AUTO = "full-auto"  # 全自动(危险!)

4.3 工具发现与推荐

当工具数量超过 10 个,LLM 选错工具的概率急剧上升。两个解决方案:

§5 记忆与上下文管理

这是 Agent 架构中最被低估的模块。上下文窗口有限,如何高效利用是核心挑战。

5.1 五级记忆架构

从无状态到自进化,记忆系统的 5 个层级:

级别名称特点代表项目
L0无状态每次调用全新开始最简单的 ChatGPT wrapper
L1对话历史保留最近 N 轮对话大多数项目的默认模式
L2摘要压缩历史对话压缩为摘要OpenHands (LLMSummarizingCondenser)
L3检索增强向量数据库 + 语义检索Agent Zero (3区域FAISS), GPT Researcher
L4自进化记忆经验累积 + 行为调整Hermes (HRR + 信任评分)

5.2 Context Condenser — 上下文压缩的艺术

OpenHands 的 LLMSummarizingCondenser 是目前最优雅的解决方案:

# OpenHands 风格的 Condenser
class Condenser:
    """上下文压缩器——把无限历史压缩进有限窗口"""

    def condense(self, events: list[Event], max_tokens: int) -> list[Event]:
        current_tokens = sum(e.token_count for e in events)

        if current_tokens <= max_tokens:
            return events  # 不需要压缩

        # 策略 1: 丢弃旧的观察结果(保留动作)
        events = self._drop_old_observations(events)
        if self._token_count(events) <= max_tokens:
            return events

        # 策略 2: 摘要压缩早期历史
        early, recent = self._split(events, ratio=0.4)
        summary = self.llm.summarize(early)
        return [SummaryEvent(summary)] + recent

    def _drop_old_observations(self, events):
        """只保留最近 N 次工具返回的完整结果,旧的结果截断"""
        obs_count = 0
        result = []
        for e in reversed(events):
            if e.type == "observation":
                obs_count += 1
                if obs_count > 5:  # 只保留最近5次
                    e = e.truncate(max_chars=200)
            result.append(e)
        return list(reversed(result))

5.3 Aider 的 RepoMap — 代码记忆的最佳实践

当 Agent 操作代码仓库时,如何把几千个文件塞进有限的上下文?Aider 的 RepoMap 用 PageRank 算法解决:

# Aider RepoMap 简化原理
class RepoMap:
    def get_repo_map(self, chat_files: list[str]) -> str:
        # 1. 解析所有文件的 AST,提取定义和引用
        tags = self._get_tags()  # {filepath: [(name, kind, line), ...]}

        # 2. 构建引用图:谁引用了谁
        G = self._build_graph(tags)

        # 3. PageRank 排序——被引用最多的定义最重要
        rankings = pagerank(G)

        # 4. 只保留 Top-K 重要的定义,用压缩格式输出
        top_tags = sorted(tags, key=lambda t: rankings[t], reverse=True)
        map_str = ""
        for tag in top_tags:
            if len(map_str) > MAX_MAP_TOKENS:
                break
            map_str += f"{tag.filepath}:{tag.line} {tag.name}\n"

        return map_str  # 几千文件 → 几百行摘要
实践建议:L2(摘要压缩)是性价比最高的选择。大多数场景不需要向量数据库。只有当 Agent 需要跨会话记忆、或知识库超过 10 万条时,才升级到 L3。

§6 提示词工程:组装与缓存

Agent 的 prompt 不是写一次就完事——它是动态组装的,每次调用可能不同。

6.1 Prompt 组装三层次(Hermes 风格)

Layer 1: Identity
角色/能力/约束
Layer 2: Context
记忆/工具描述/用户输入
Layer 3: Safety
注入防护/输出约束
# Hermes 风格的三层 Prompt 组装
class PromptComposer:
    def compose(self, agent, user_input, memory, tools):
        parts = []

        # Layer 1: Identity (静态,可缓存)
        parts.append(self._identity_block(agent))
        parts.append(self._capabilities_block(agent))

        # Layer 2: Context (动态,每轮变化)
        parts.append(self._memory_block(memory))
        parts.append(self._tools_block(tools))
        parts.append(self._user_input_block(user_input))

        # Layer 3: Safety (静态,可缓存)
        parts.append(self._safety_guardrails())
        parts.append(self._output_format_spec())

        return "\n\n".join(parts)

6.2 Cache Boundary — 省 90% Token 的秘密(OpenClaw)

OpenClaw 的 Cache Boundary 是提示词缓存的教科书级实现:

# OpenClaw Cache Boundary 原理
#
# LLM API 的 Prompt Cache 机制:
# - 前缀匹配的 prompt 只计算一次
# - 后续请求如果前缀不变,只计算新增部分
#
# 关键:把静态内容放在前面,动态内容放在后面!

COMPOSED_PROMPT = """
[SYSTEM - 静态,可缓存]          ← Cache Boundary
├── 角色定义                      ← 几乎不变
├── 工具描述                      ← 偶尔变
├── 安全约束                      ← 几乎不变
│
[CACHE BOUNDARY]                  ← 在此插入标记
│
[USER - 动态,不缓存]
├── 记忆检索结果                  ← 每轮变化
├── 当前对话                      ← 每轮变化
└── 用户最新输入                  ← 每轮变化
"""

# 实现效果:
# 第1轮: 计算全部 4000 tokens
# 第2轮: 只计算新增 ~500 tokens (前缀命中缓存)
# 节省: ~87% token 计算成本
Aider 的 ChatChunks 分区缓存:异曲同工——把 prompt 分为 systemrepo_mapcontextchat 四个 chunk,每个 chunk 独立缓存,只有变化的 chunk 重新计算。

§7 错误处理与容错

Agent 运行在不确定的环境中——LLM 输出不稳定、工具调用失败、网络超时。容错设计是生产系统的心脏。

7.1 四层容错架构

🔄 第1层:重试

最简单的容错。LLM 输出格式错误?重试。工具超时?重试。

关键参数:

  • 最大重试次数(通常 3)
  • 退避策略(指数退避)
  • 重试条件(哪些错误可重试)

简单 必须

🧪 第2层:多尝试 + 评审

SWE-agent 的 RetryAgent + Reviewer:生成多个方案,Reviewer 选最佳。

适用:高价值任务(如代码修复),一次失败代价高。

中等 推荐

🚨 第3层:卡住检测

OpenHands 的 StuckDetector:5 种卡住模式检测。

  • 重复同一动作
  • 输出无变化
  • 长时间无进展
  • 错误循环
  • 超出预期步骤

中等 推荐

🏗️ 第4层:检查点恢复

LangGraph 的 Checkpoint:每步持久化状态,失败后从检查点恢复。

适用:长时运行任务(>5 分钟),中断代价高。

复杂 推荐

# 综合:生产级容错 Agent
class ProductionAgent:
    def __init__(self, ...):
        self.retry_policy = RetryPolicy(max_retries=3, backoff="exponential")
        self.stuck_detector = StuckDetector(
            patterns=["repeat_action", "no_progress", "error_loop"],
            window_size=5,
        )
        self.checkpointer = FileCheckpointer("./checkpoints/")

    @checkpoint  # 自动保存检查点
    def run(self, task: str) -> str:
        for step in range(self.max_steps):
            # 卡住检测
            if self.stuck_detector.is_stuck(self.history):
                self.stuck_detector.intervene(self)  # 注入反思 prompt
                continue

            # 带重试的执行
            result = self.retry_policy.execute(
                lambda: self._step(task),
                retry_on=[OutputParseError, ToolTimeoutError],
            )

            if result.is_final:
                return result.output

        return "任务未完成(达到步数上限)"

§8 多 Agent 协作模式对比

当你确定需要多 Agent 时,选择哪种协作模式?

模式适用场景优点缺点代表
Round Robin 简单讨论/头脑风暴 实现简单,公平 无重点,容易跑题 AutoGen
Selector (LLM 选) 动态决定谁发言 灵活,有重点 额外 LLM 调用开销 AutoGen
Swarm + Handoff 层级指挥/接力 控制流清晰 需要精心设计 Handoff AutoGen/OpenAI
DAG/State Machine 有条件分支的流程 精确控制,可调试 定义复杂 LangGraph
SOP/Orchestrator 流水线式任务 角色清晰,可重复 不够灵活 MetaGPT/CrewAI
SocietyOfMind 嵌套团队(团队中包含子团队) 可组合,可扩展 调试困难 AutoGen
AutoGen 的 Handoff 创新点:把 Agent 间的转移建模为 Function Calling——每个 Agent 可以"调用"另一个 Agent,就像调用工具一样。这统一了工具调用和 Agent 协作的编程模型。

§9 完整架构蓝图

把以上所有模块组合起来,一个生产级 Agent 系统的完整架构:

┌──────────────────────────────────────────────────────────────────────┐ │ Production Agent Architecture │ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────────────┐ │ │ │ Input │ │ Router │ │ Agent │ │ Output │ │ │ │ Layer │→ │ Layer │→ │ Core │→ │ Layer │ │ │ └──────────┘ └──────────┘ └─────┬────┘ └──────────────────────┘ │ │ │ │ │ ┌───────────────────────────┼──────────────────────┐ │ │ │ │ │ │ │ ▼ ▼ ▼ │ │ ┌─────────────┐ ┌──────────────┐ ┌───────────────┐ │ │ │ Tool System │ │ Memory │ │ Safety │ │ │ │ │ │ │ │ │ │ │ │ • Registry │ │ • L1: Chat │ │ • Policy Pipe │ │ │ │ • Policy │ │ • L2: Cond. │ │ • Sandbox │ │ │ │ • Sandbox │ │ • L3: Vector │ │ • Audit Log │ │ │ │ • Approval │ │ • L4: Evolve │ │ • Threat Scan │ │ │ └─────────────┘ └──────────────┘ └───────────────┘ │ │ │ │ ┌──────────────────────────────────────────────────────────────┐ │ │ │ Infrastructure │ │ │ │ • Cache Boundary (Prompt 缓存) • Checkpoint (状态持久化) │ │ │ │ • LLM Failover (多 Provider) • Monitoring (可观测性) │ │ │ │ • Rate Limiter • Cost Tracker │ │ │ └──────────────────────────────────────────────────────────────┘ │ └──────────────────────────────────────────────────────────────────────┘

9.1 最小可行 Agent(3 个模块)

如果你想最快上线一个 Agent:

# 最小可行 Agent: ReAct + Function Calling + 对话历史
from litellm import completion

TOOLS = [
    {"type": "function", "function": {
        "name": "web_search", "description": "搜索互联网",
        "parameters": {"type": "object", "properties": {
            "query": {"type": "string"}}, "required": ["query"]}
    }}
]

def run_agent(task: str, max_steps: int = 5) -> str:
    messages = [{"role": "system", "content": "你是一个有用的助手。"}, 
                {"role": "user", "content": task}]

    for _ in range(max_steps):
        resp = completion(model="gpt-4o", messages=messages, tools=TOOLS)
        msg = resp.choices[0].message
        messages.append(msg)

        if msg.tool_calls is None:
            return msg.content  # Agent 完成

        # 执行工具
        for tc in msg.tool_calls:
            result = execute_tool(tc.function.name, 
                                 json.loads(tc.function.arguments))
            messages.append({"role": "tool", 
                           "tool_call_id": tc.id, 
                           "content": str(result)})

    return "达到最大步数"

# 就这么简单。3 个函数,50 行代码。

9.2 生产级 Agent(7 个模块)

加上安全、缓存、容错、记忆:

# 生产级 Agent 配置
class ProductionAgentConfig:
    # 核心循环
    loop_type: str = "react"  # react | plan_execute | state_machine

    # LLM 配置
    model: str = "gpt-4o"
    fallback_model: str = "claude-sonnet"  # Failover
    cache_boundary: bool = True  # 提示词缓存

    # 工具系统
    tools: list[Tool] = []
    tool_policy: PolicyPipeline = PolicyPipeline()
    sandbox: bool = True  # 工具在沙箱中执行

    # 记忆系统
    memory_level: int = 2  # 0-4, 推荐 L2
    condenser: Condenser = LLMSummarizingCondenser(max_tokens=4000)

    # 安全
    human_approval_for: list[str] = ["RED"]  # 需要人工审批的风险级别
    threat_scanner: Scanner = ContextThreatScanner()
    audit_log: bool = True

    # 容错
    max_retries: int = 3
    stuck_detector: StuckDetector = StuckDetector()
    checkpointer: Checkpointer = FileCheckpointer()

    # 成本控制
    max_tokens_per_run: int = 100_000
    max_cost_per_run: float = 1.0  # USD

§10 框架选型指南

如果你不想从零构建,选择哪个框架?

框架最适合学习曲线灵活性生产就绪
LangGraph 复杂工作流、需要精确控制 ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐
AutoGen 多 Agent 协作、对话式 ⭐⭐⭐⭐ ⭐⭐⭐
CrewAI 团队协作、流水线任务 ⭐⭐⭐ ⭐⭐⭐
Smolagents 快速原型、学习 Agent ⭐⭐⭐ ⭐⭐
PydanticAI 类型安全、Pythonic ⭐⭐⭐⭐ ⭐⭐⭐
Agno 轻量级、快速开始 ⭐⭐⭐ ⭐⭐⭐
Google ADK Google 生态、A2A 协议 ⭐⭐⭐ ⭐⭐⭐⭐
自建 完全控制、特殊需求 ⭐⭐⭐⭐⭐ 看你
❓ 你该选哪个?
第一次做 Agent → SmolagentsPydanticAI(学习最快)
需要复杂工作流 → LangGraph(状态机 + 检查点)
需要多 Agent 对话 → AutoGen(5 种编排模式)
需要团队流水线 → CrewAI(最简单的 SOP)
需要完全控制 → 自建(参考本文的架构蓝图)

§11 反模式与常见坑

💀 坑 1:过度工程 — 一上来就多 Agent

80% 的任务单 Agent 就够。多 Agent 带来的协作复杂度(消息格式、状态同步、调试)远超想象。先用单 Agent 做,遇到瓶颈再加。

信号:如果你发现多个 Agent 之间频繁传大量上下文 → 可能应该合并为一个 Agent。

💀 坑 2:无上下文管理 — Token 爆炸

每一步都追加完整历史,5 轮后 token 就爆了。必须从第一天起就加入 Condenser 或摘要机制。

数据:一个 10 步的 ReAct 循环,不压缩约 20K tokens,压缩后 5K tokens。4 倍差距。

💀 坑 3:忽略工具错误 — Agent 崩溃

工具调用失败是常态,不是异常。每个工具调用都必须有 try-catch,返回错误信息给 LLM 让它重试,而不是直接抛异常终止。

💀 坑 4:无限循环 — 忘了设置终止条件

必须有硬性上限:max_stepsmax_tokensmax_cost。加上 StuckDetector。

💀 坑 5:Prompt 注入 — Agent 被劫持

用户输入中可能包含"忽略之前的指令"之类的攻击。必须做 Context Threat Scanning(参考 Hermes 的 60+ 威胁模式扫描)。

💀 坑 6:缓存盲区 — 每次都重算全部 Prompt

不懂 Cache Boundary,每次 LLM 调用都重新计算完整 prompt。成本和延迟都是 10 倍差距。参考 OpenClawAider

§12 与其他模块的关联

Agent 架构不是孤立的,它与 SaaS 全栈知识库的其他模块紧密关联:

关联模块关联点
🧠 LLM 集成Agent 的大脑——Provider 选型、Failover、路由、成本控制
📚 RAG 架构Agent 的知识——检索增强生成,为 Agent 提供外部知识
🧮 向量数据库Agent 的 L3/L4 记忆的存储引擎
📝 提示词工程Agent 的语言——Cache Boundary、注入防护、输出控制
🦀 后端框架Agent 服务的宿主——FastAPI/Hono 提供 Agent API
📋 异步任务长时运行的 Agent 任务需要异步队列——Inngest/Temporal
💾 缓存策略Agent 结果缓存——相似任务避免重复计算
🔐 认证授权Agent 调用工具时的权限控制——RBAC/ABAC
📊 监控Agent 运行时可观测性——OpenTelemetry

§13 Agent 构建模块拆分(深度链接)

本文是从 20 个 Agent 项目研究中提炼的概览。每个子模块有独立深度分析页:

ReAct / Plan-Execute / State Machine 的实现细节与取舍

57KB 深度

定义、调用、安全、扩展机制

37KB 深度

从无状态到自进化的 5 级实现

52KB 深度

组装、缓存、注入防护

47KB 深度

🛡️ 安全机制

沙箱、审批、注入防护、Failover

41KB 深度

消息传递、状态共享、任务编排

37KB 深度

缓存、Failover、监控、多平台

53KB 深度

从 20 个项目中提炼的 Agent 构建方法论

初版 概览

§14 关键数据:20 个项目架构统计

特征项目数项目
ReAct 循环9/20Smolagents, Agent Zero, SWE-agent, OpenHands, AutoGPT, GPT Researcher, Goose, Codex CLI, Agno
Function Calling12/20LangGraph, PydanticAI, AutoGen, CrewAI, OpenClaw, Google ADK, Aider, Browser Use, ...
多 Agent 原生8/20AutoGen, CrewAI, MetaGPT, LangGraph, CAMEL, Google ADK, OpenClaw, Hermes
沙箱执行6/20SWE-agent, OpenHands, Codex CLI, OpenClaw, Goose, Agent Zero
检查点/恢复3/20LangGraph, OpenClaw, PydanticAI
自进化2/20Hermes, Agent Zero
Prompt 缓存优化3/20OpenClaw (Cache Boundary), Aider (ChatChunks), Hermes (三层组装)

§15 趋势与展望

趋势 1:混合架构 — ReAct 内核 + 外层编排

单一 ReAct 已经不够。趋势是 ReAct 作为核心执行单元,外层用状态机/Orchestrator 编排多个 ReAct Agent。LangGraph 的 Pregel 引擎就是这个思路。

趋势 2:ACI > HCI — 为 Agent 设计专用接口

SWE-agent 的核心洞察:不要让 Agent 复用人类接口,而是设计 Agent-Computer Interface (ACI)。Shell 命令的输出太冗长?设计精简的 Agent 专用命令。文件浏览太慢?提供 grep + 定位的一体化接口。

趋势 3:A2A 协议 — Agent 间通信标准化

Google ADK 的 A2A (Agent-to-Agent) 协议:让不同框架的 Agent 可以互相通信。就像 HTTP 统一了 Web 通信,A2A 可能统一 Agent 通信。

趋势 4:Background Review — 持续自优化

Hermes 的 Background Review Fork 是目前唯一的实现,但方向清晰:Agent 在后台持续审计自己的行为,发现可优化点并自动调整。这是 Agent 从"工具"到"同事"的关键一步。

一句话总结:Agent 架构的核心不是选择哪个框架,而是理解你的任务需求,选对架构模式,然后在每个模块(循环、工具、记忆、安全、容错)上做对关键决策。框架只是工具,架构思维才是核心。