2026 年最火的技术词是 Agent,但中文圈真正讲「怎么设计一个生产可用的 Agent 系统」的文章几乎没有。看完这篇,你会对 Agent 架构有一个完整的认知框架,末尾的 3-Agent 代码助手可以直接跑。
一、为什么你的 Agent 总是「跑偏」
用过 Agent 的开发者几乎都遇到过:
- Agent 执行了第一步就忘了目标,开始胡言乱语
- 工具随便乱调,明明该查数据库却去搜网页
- 上下文越跑越长,Token 费用直线上升
- 多个 Agent 之间互相等待、死锁、重复工作
问题不在模型,在架构。 本文把 Agent 架构从头到尾讲清楚------四种架构模式、工具调用设计、三层记忆系统、多 Agent 协作,每种都配了可运行的 Python 代码。
二、Agent 核心架构模式
2.1 ReAct(Reasoning + Acting)--- 最经典
ReAct 是所有 Agent 架构的起点:思考 → 行动 → 观察 → 再思考 → 直到目标达成。
python
class ReActAgent:
def __init__(self, llm, tools: dict):
self.llm = llm
self.tools = tools # {"tool_name": callable}
self.max_steps = 10
def run(self, goal: str) -> str:
context = [{"role": "user", "content": goal}]
for step in range(self.max_steps):
# 1. 思考 + 决策
response = self.llm.chat(context, tools_schema=self._tool_schemas())
# 2. 模型直接回复 → 结束
if response.content and not response.tool_calls:
return response.content
# 3. 执行工具调用
for tool_call in response.tool_calls:
tool_name = tool_call.name
tool_args = json.loads(tool_call.arguments)
result = self.tools[tool_name](**tool_args)
# 4. 观察结果加入上下文
context.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": str(result)
})
context.append(response.message)
return "达到最大步数,任务未完成"
适用场景:多步推理(代码审查、故障排查)、工具调用结果不确定(搜索、数据分析)
局限:没有全局规划,容易「走一步看一步」失去方向
2.2 Plan-Execute --- 先规划再执行
先让 LLM 制定完整计划,再逐步执行。某一步失败时自动重新规划。
python
class PlanExecuteAgent:
def __init__(self, llm, tools: dict):
self.llm = llm
self.tools = tools
self.executor = ReActAgent(llm, tools)
def run(self, goal: str) -> str:
# 1. 规划阶段
plan_prompt = f"""
为完成以下目标,制定详细步骤计划。
目标:{goal}
可用工具:{', '.join(self.tools.keys())}
返回 JSON:{{"steps": ["步骤1", "步骤2", ...]}}
"""
plan_response = self.llm.chat([{"role": "user", "content": plan_prompt}])
plan = json.loads(plan_response.content)
# 2. 逐步执行
results = []
for i, step in enumerate(plan["steps"]):
step_result = self.executor.run(step)
results.append({"step": step, "result": step_result})
# 某步失败?重新规划剩余步骤
if "失败" in step_result or "错误" in step_result:
remaining = plan["steps"][i+1:]
replan = self._replan(goal, step, step_result, remaining)
plan["steps"] = plan["steps"][:i+1] + replan
return self._summarize(goal, results)
适用场景:需求明确的开发任务、部署流水线、数据分析工作流
局限:初始规划可能不准,动态环境不适合静态规划
2.3 Router Agent --- 按任务类型路由
一个主 Agent 分类任务,分发给专业 Agent 处理:
markdown
┌──────────┐
│ Router │
│ Agent │
└────┬─────┘
┌────────┼────────┐
↓ ↓ ↓
┌─────────┐ ┌──────┐ ┌────────┐
│ Coder │ │Search│ │ Devops │
│ Agent │ │Agent │ │ Agent │
└─────────┘ └──────┘ └────────┘
关键:路由 Agent 本身可以是极轻量的(用 Haiku 甚至传统分类器),只在分发任务时调用一次,成本极低。
2.4 Multi-Agent Orchestra --- 多 Agent 编排
最复杂也最强大的模式。多个 Agent 串行/并行协作,由 Orchestrator 调度:
markdown
┌──────────────┐
│ Orchestrator │
└──────┬───────┘
┌────────────────┼────────────────┐
↓ ↓ ↓
┌──────────┐ ┌──────────┐ ┌──────────┐
│Architect │ │ Coder │ │ Reviewer │
│ Agent │ │ Agent │ │ Agent │
└──────────┘ └──────────┘ └──────────┘
具体实现见第五节。
四种模式选型建议:
| 场景 | 推荐模式 | 原因 |
|---|---|---|
| 简单单步任务 | 直接 Function Calling | Agent 反而是过度设计 |
| 需要多步推理 | ReAct | 最灵活,最通用 |
| 步骤明确可规划 | Plan-Execute | 更可控,更适合生产 |
| 多种任务类型 | Router | 减少单个 Agent 的复杂度 |
| 复杂完整流程 | Multi-Agent | 各司其职,可独立优化 |
三、工具调用系统:让 Agent 知道该用什么
3.1 工具描述工程 --- 比代码更重要
LLM 只能通过你的工具描述来决定何时调用、传什么参数。描述质量 = 调用准确率。
python
# ❌ 差
def search(query: str) -> list:
"""搜索"""
# ✅ 好
def search_knowledge_base(query: str, top_k: int = 5, filters: dict = None) -> list:
"""在内部知识库中搜索与 query 语义相关的内容。
返回 top_k 条最相关的结果,每项包含 {title, content, score, url}。
支持按 filters={"category": "技术文档", "date_range": "2026-01-01,2026-06-01"} 过滤。
当用户问到公司内部政策、技术方案或历史决策时优先使用此工具。
"""
三条黄金法则:
- 说清楚何时使用 --- 比「做什么」更重要,直接告诉 LLM 什么场景该调用
- 给参数示例和默认值 --- 减少 LLM 的决策负担
- 写明限制条件 --- 超时、最大返回数、权限要求
3.2 工具分组与权限控制
python
class ToolRegistry:
def __init__(self):
self._tools = {}
def register(self, name: str, func, group: str, risk_level: str):
self._tools[name] = {
"func": func,
"group": group,
"risk_level": risk_level, # "safe" | "write" | "dangerous"
}
def get_safe_tools(self) -> list:
"""只读操作,可以自动执行"""
return [t for t in self._tools.values() if t["risk_level"] == "safe"]
def get_dangerous_tools(self) -> list:
"""高危操作,需要额外审批"""
return [t for t in self._tools.values() if t["risk_level"] == "dangerous"]
生产环境必须分级 :读操作自动执行,写操作需要确认,危险操作(如 execute_sql)需要人工审批。
3.3 Function Calling vs MCP --- 什么时候用哪个
| 维度 | Function Calling | MCP |
|---|---|---|
| 标准化 | 厂商各自定义 | 开放协议,跨厂商通用 |
| 可移植性 | 绑定特定 LLM | 一次实现,所有 MCP 客户端可用 |
| 部署 | LLM 内部 | 独立进程,可远程 |
| 安全 | 依赖 LLM 厂商 | 进程隔离 + OAuth 2.1 |
建议:个人项目用 Function Calling 快速验证,团队项目用 MCP。
四、记忆系统:让 Agent 拥有「长期记忆」
4.1 三层记忆架构
scss
短期记忆 (对话上下文) ── 容量 ~100K tokens,生命周期:单次会话
↕
工作记忆 (Scratchpad) ── 容量 ~10K tokens,生命周期:单次任务
↕
长期记忆 (向量数据库) ── 容量无限,生命周期:永久
4.2 长期记忆 --- pgvector 实现
python
import psycopg2
from pgvector.psycopg2 import register_vector
class LongTermMemory:
def __init__(self, conn_string: str, embedding_model):
self.conn = psycopg2.connect(conn_string)
register_vector(self.conn)
self.embed = embedding_model
self._create_table()
def _create_table(self):
with self.conn.cursor() as cur:
cur.execute("""
CREATE TABLE IF NOT EXISTS agent_memory (
id SERIAL PRIMARY KEY,
content TEXT NOT NULL,
embedding vector(1536),
memory_type TEXT DEFAULT 'fact',
importance FLOAT DEFAULT 0.5,
created_at TIMESTAMP DEFAULT NOW(),
last_accessed TIMESTAMP DEFAULT NOW(),
access_count INT DEFAULT 0
);
CREATE INDEX IF NOT EXISTS agent_memory_embedding_idx
ON agent_memory USING ivfflat (embedding vector_cosine_ops);
""")
self.conn.commit()
def store(self, content: str, memory_type: str = "fact", importance: float = 0.5):
"""存储一条记忆"""
embedding = self.embed(content)
with self.conn.cursor() as cur:
cur.execute(
"INSERT INTO agent_memory (content, embedding, memory_type, importance) VALUES (%s, %s, %s, %s)",
(content, embedding, memory_type, importance)
)
self.conn.commit()
def recall(self, query: str, top_k: int = 5) -> list[str]:
"""语义检索相关记忆"""
query_embedding = self.embed(query)
with self.conn.cursor() as cur:
cur.execute("""
SELECT content, 1 - (embedding <=> %s) AS similarity
FROM agent_memory
ORDER BY embedding <=> %s
LIMIT %s
""", (query_embedding, query_embedding, top_k))
return [r[0] for r in cur.fetchall()]
def forget(self, days_inactive: int = 30):
"""遗忘不活跃且不重要的记忆"""
with self.conn.cursor() as cur:
cur.execute("""
DELETE FROM agent_memory
WHERE last_accessed < NOW() - INTERVAL '%s days'
AND importance < 0.3
""", (days_inactive,))
self.conn.commit()
关键设计:记忆不是越多越好------不重要的记忆需要「遗忘」,否则检索质量会下降。
五、从零构建多 Agent 系统:AI 代码助手
三个 Agent 协作完成代码任务:
markdown
用户需求
↓
Architect Agent → 分析需求,输出技术方案
↓
Coder Agent → 根据方案编写代码
↓
Reviewer Agent → 审查代码,提出修改意见
↓ (最多 3 轮修改)
最终结果
完整实现
python
import json
import asyncio
from dataclasses import dataclass
@dataclass
class AgentConfig:
name: str
role: str
model: str
temperature: float = 0.3
class BaseAgent:
def __init__(self, config: AgentConfig, llm, tools: dict = None):
self.config = config
self.llm = llm
self.tools = tools or {}
async def think(self, task: str) -> str:
system_prompt = f"你是 {self.config.name},{self.config.role}。请根据任务要求,输出工作结果。"
response = await self.llm.chat([
{"role": "system", "content": system_prompt},
{"role": "user", "content": task}
])
return response.content
class ArchitectAgent(BaseAgent):
"""需求分析 Agent"""
def __init__(self, llm):
super().__init__(AgentConfig(
name="Architect",
role="技术架构师,负责分析需求并输出技术方案",
model="claude-sonnet-4-6"
), llm)
async def design(self, requirement: str) -> dict:
prompt = f"""
请分析以下需求,输出技术方案。
需求:{requirement}
输出 JSON:
{{
"summary": "需求概述",
"architecture": "架构方案",
"tech_stack": {{"frontend": "...", "backend": "...", "database": "..."}},
"api_design": ["端点1", "端点2"],
"components": ["组件1", "组件2"],
"risks": ["风险1", "风险2"],
"implementation_steps": ["步骤1", "步骤2"]
}}
"""
result = await self.think(prompt)
return json.loads(result)
class CoderAgent(BaseAgent):
"""编码 Agent"""
def __init__(self, llm, tools: dict):
super().__init__(AgentConfig(
name="Coder",
role="高级软件工程师,根据技术方案编写代码",
model="claude-sonnet-4-6"
), llm, tools)
async def implement(self, design: dict) -> str:
prompt = f"""
根据技术方案编写完整代码:
架构:{design.get('architecture')}
技术栈:{json.dumps(design.get('tech_stack', {}), ensure_ascii=False)}
实施步骤:{json.dumps(design.get('implementation_steps', []), ensure_ascii=False)}
要求:编写完整可运行代码,包含类型注解和注释。
"""
return await self.think(prompt)
class ReviewerAgent(BaseAgent):
"""代码审查 Agent"""
def __init__(self, llm):
super().__init__(AgentConfig(
name="Reviewer",
role="资深代码审查者,检查 Bug、安全问题和规范",
model="claude-sonnet-4-6"
), llm)
async def review(self, code: str, design: dict) -> dict:
prompt = f"""
审查以下代码:
原始需求:{json.dumps(design, ensure_ascii=False)[:2000]}
代码:{code[:8000]}
输出 JSON:
{{
"approved": true/false,
"score": 1-10,
"issues": [{{"severity": "critical|major|minor", "description": "..."}}],
"suggestions": ["建议1", "建议2"]
}}
"""
result = await self.think(prompt)
return json.loads(result)
class CodeAssistantOrchestrator:
"""编排器:协调三个 Agent"""
def __init__(self, llm, tools: dict = None):
self.architect = ArchitectAgent(llm)
self.coder = CoderAgent(llm, tools)
self.reviewer = ReviewerAgent(llm)
self.max_review_rounds = 3
async def run(self, requirement: str) -> dict:
print(f"📋 需求: {requirement}\n")
# 1. 架构设计
print("🏗️ Architect Agent 分析需求...")
design = await self.architect.design(requirement)
# 2. 编码
print("💻 Coder Agent 编写代码...")
code = await self.coder.implement(design)
# 3. 审查(最多 3 轮)
for round_num in range(self.max_review_rounds):
print(f"🔍 Reviewer Agent 第 {round_num+1} 轮审查...")
review = await self.reviewer.review(code, design)
if review["approved"]:
print(f"✅ 通过!评分: {review['score']}/10")
return {
"design": design, "code": code,
"review": review, "status": "approved"
}
print(f"⚠️ 发现 {len(review['issues'])} 个问题,Coder 修复中...")
fix_prompt = f"""
根据审查意见修改代码:
问题:{json.dumps(review['issues'], ensure_ascii=False)}
建议:{json.dumps(review.get('suggestions', []), ensure_ascii=False)}
原代码:{code[:8000]}
"""
code = await self.coder.think(fix_prompt)
return {"design": design, "code": code, "review": review, "status": "max_rounds_exceeded"}
# 使用
async def main():
from anthropic import AsyncAnthropic
llm = AsyncAnthropic()
assistant = CodeAssistantOrchestrator(llm)
result = await assistant.run("实现一个用户注册和登录的 REST API,支持 JWT 认证")
if result["status"] == "approved":
with open("generated_code.txt", "w") as f:
f.write(result["code"])
if __name__ == "__main__":
asyncio.run(main())
六、生产环境考量
6.1 成本控制:模型分层策略
不要所有 Agent 都用最贵的模型:
python
class CostTracker:
def __init__(self, budget: float):
self.budget = budget
self.spent = 0.0
self.pricing = {
"claude-sonnet-4-6": {"input": 3.0, "output": 15.0},
"claude-haiku-4-5": {"input": 0.8, "output": 4.0},
"deepseek-v4-pro": {"input": 0.55, "output": 2.19},
}
def suggest_model(self, task_complexity: str) -> str:
"""根据任务复杂度和预算推荐模型"""
if self.spent > self.budget * 0.7:
return "claude-haiku-4-5" # 预算紧张
if task_complexity == "complex":
return "claude-sonnet-4-6"
return "claude-haiku-4-5"
策略:路由分派用 Haiku,核心推理用 Sonnet,简单文本处理用 DeepSeek。
6.2 安全
| 层面 | 措施 |
|---|---|
| 工具权限 | 三级分级(safe/write/dangerous) |
| 执行沙箱 | Docker 容器隔离:docker run --read-only --network=none |
| Prompt 注入防护 | 输入清洗 + 输出结构校验 |
| 审批流 | 危险工具调用前暂停等待人工确认 |
6.3 监控
python
class AgentMetrics:
def __init__(self):
self.tool_calls = []
self.llm_calls = []
def report(self) -> dict:
return {
"total_llm_calls": len(self.llm_calls),
"total_tool_calls": len(self.tool_calls),
"tool_success_rate": sum(
1 for t in self.tool_calls if t["status"] == "success"
) / max(len(self.tool_calls), 1),
}
七、框架选型
| 框架 | 理念 | 适合 |
|---|---|---|
| LangGraph | 状态图驱动 | 复杂工作流,需要精细控制 |
| CrewAI | 角色扮演式 | 快速原型,几行代码跑起来 |
| AutoGen | 对话驱动(微软) | 微软/Azure 生态 |
| 自研 | 完全定制 | 特殊需求,极致性能 |
建议:先用 CrewAI 或 LangGraph 验证想法,确认设计合理后再决定是否自研。不要一开始就自研------框架已经解决了 80% 的工程问题。
八、未来趋势
| 趋势 | 时间窗口 |
|---|---|
| MCP + A2A 深度融合 | 2026 H2 |
| Agent UI(AUI)替代 Chat UI | 2026-2027 |
| Docker/WASM 安全沙箱标准化 | 2027 H1 |
| Agent 市场(类似 App Store) | 2027 |
写在最后
Agent 架构不是什么魔法------它是 LLM、工具调用、记忆系统和多 Agent 协作的工程组合。
最重要的是想清楚三件事:
- Agent 在你的产品中解决什么问题?
- 它的失败模式是什么?(调错工具、忘记目标、死循环)
- 你怎么优雅地降级?(超时、预算耗尽、工具不可用)
回答好这三个问题,你就是 Agent 时代的合格架构师。
首发于 志趣 ZhiQu --- 一个 AI 开发者知识社区,欢迎来交流。