第22章:主流框架实战
你已经读完了前 21 章,知道了 Agent 是什么、怎么用工具、怎么管记忆、怎么做规划、怎么保证安全。现在的问题是:在真实项目里,我到底用哪个框架?
这个问题没有唯一答案,但选错了会很痛。LangGraph 学习曲线陡峭,三天还没跑起来第一个 Agent;CrewAI 入门快,但到了需要精细控制的地方开始抓狂;OpenAI Agents SDK 极简,却默认绑定 OpenAI 生态。框架选型是一个工程决策,而不是"哪个更强"的竞技。
这一章的目标不是告诉你哪个框架最好,而是帮你理解每个框架背后的设计哲学——它试图解决什么问题、用什么抽象来解决、这个抽象在什么条件下会成为阻碍。明白了这些,选型才能落地。
框架到底买你什么
在展开每个框架之前,先建立一个前提:框架不会让 Agent 更智能,只会让你少写胶水代码。
一个没有框架的 Agent 需要你自己维护:工具注册和调用、LLM 交互循环、消息历史管理、状态持久化、错误重试、多 Agent 路由。这些代码不难写,但每个项目写一遍很烦。框架的价值就在于把这些重复模式封装成固定抽象,让你聚焦在业务逻辑上。
代价是:你的代码被框架的思维模型约束了。LangGraph 要求你用图来思考任务流;CrewAI 要求你用角色来组织 Agent;OpenAI SDK 要求你用 handoff 来理解控制权转移。如果你的任务天然符合这个思维模型,框架是放大器;如果不符合,框架会变成枷锁。
Anthropic 在官方文档中给出了一个务实建议 [1]:
当你首次使用框架时,建议先用原生 LLM API 实现相同的功能,这样你才能理解框架底层在做什么。
不是叫你不用框架,而是说别绕过框架直接学框架。
22.1 LangGraph
核心直觉
LangGraph 的核心思想只有一句话:把 Agent 的执行过程建模成一个有状态的有向图。
有向图里,节点是函数(每个节点做一件事),边是控制流(决定下一步去哪个节点),所有节点共享一个中央状态对象。每次节点执行完,把自己的输出合并回这个状态;下一个节点从这个状态里读自己需要的部分。
这个设计让 LangGraph 在两件事上特别擅长:
- 复杂的条件路由:根据当前状态动态决定走哪条边
- 持久化与中断恢复:每执行完一个节点就存一次状态,任意位置都可以暂停、恢复、回溯
关键概念
StateGraph:主体数据结构。你先定义状态的 schema(用 Python TypedDict),然后往图里添加节点和边。
Node(节点):一个 Python 函数,接收当前状态,返回一个字典(部分状态更新)。节点不需要返回完整状态,只返回它修改的字段。
Edge(边):连接两个节点的有向路径。分两种:
- 普通边:固定的下一个节点,
add_edge("node_a", "node_b") - 条件边:根据函数的返回值决定下一节点,
add_conditional_edges("node_a", router_fn, {"result_1": "node_b", "result_2": "node_c"})
Checkpoint(检查点):把图执行过程保存为可恢复的状态快照。LangGraph 的持久化层按 thread 组织 checkpoint,支持内存(MemorySaver / InMemorySaver)、SQLite(SqliteSaver)、PostgreSQL(PostgresSaver)等多种存储后端。开启 checkpoint 后,你可以做 human-in-the-loop、time travel 调试、失败恢复和跨轮次状态延续。
Reducer:控制状态字段如何合并。默认是覆盖(新值替换旧值),但对于列表类字段,你通常想追加而不是覆盖——用 Annotated[List[str], operator.add] 声明。
构建一个有状态的研究 Agent
下面是一个可运行的示例:Agent 接收查询,搜索互联网,判断结果是否充分,最终生成报告。
import operator
from typing import Annotated, TypedDict, List
from langgraph.graph import StateGraph, END
from langgraph.checkpoint.memory import MemorySaver
from langchain_anthropic import ChatAnthropic
from langchain_community.tools.tavily_search import TavilySearchResults
# 1. 定义共享状态
class ResearchState(TypedDict):
query: str
search_results: Annotated[List[str], operator.add] # 列表追加而非覆盖
search_count: int
final_report: str
# 2. 初始化工具和模型
llm = ChatAnthropic(model="<your-claude-model>")
search_tool = TavilySearchResults(max_results=3)
# 3. 定义节点函数
def search_node(state: ResearchState) -> dict:
"""执行搜索,返回结果追加到列表"""
results = search_tool.invoke(state["query"])
snippets = [r["content"] for r in results]
return {
"search_results": snippets,
"search_count": state.get("search_count", 0) + 1
}
def analyze_node(state: ResearchState) -> dict:
"""分析搜索结果,生成最终报告"""
context = "\n".join(state["search_results"])
response = llm.invoke(
f"基于以下搜索结果,为查询 '{state['query']}' 生成详细报告:\n\n{context}"
)
return {"final_report": response.content}
# 4. 路由函数:决定继续搜索还是进入分析
def should_continue_search(state: ResearchState) -> str:
# 超过 2 次搜索或结果足够多时停止
if state.get("search_count", 0) >= 2 or len(state["search_results"]) >= 6:
return "analyze"
return "search"
# 5. 构建图
builder = StateGraph(ResearchState)
builder.add_node("search", search_node)
builder.add_node("analyze", analyze_node)
builder.set_entry_point("search")
# 条件路由:search 节点之后,根据条件决定去哪里
builder.add_conditional_edges(
"search",
should_continue_search,
{"search": "search", "analyze": "analyze"} # 可以循环
)
builder.add_edge("analyze", END)
# 6. 编译图,启用持久化
checkpointer = MemorySaver()
graph = builder.compile(checkpointer=checkpointer)
# 7. 运行
config = {"configurable": {"thread_id": "research-001"}}
result = graph.invoke({"query": "LangGraph 最新特性"}, config=config)
print(result["final_report"])这里有几个值得注意的设计细节:
search_results用了Annotated[List[str], operator.add],这意味着每次搜索的结果会追加到列表,而不是覆盖。如果用默认的覆盖语义,只会保留最后一次搜索结果。thread_id是 Checkpoint 的键。同一个thread_id的多次调用会复用状态,实现多轮对话。- 图里有一个循环:search → search(条件边指向自己),LangGraph 天然支持这种循环,但你需要确保有退出条件,否则会无限循环。
Human-in-the-Loop(人工介入)
LangGraph 的 Checkpoint 机制天然支持人工介入。简单场景可以用 interrupt_before=["node_name"] 在某个节点前暂停;更复杂的生产场景通常会用动态 interrupt(),让节点把需要审批的 payload 返回给外部系统,再用 Command(resume=...) 恢复执行。下面先展示静态暂停的基本形态:
graph = builder.compile(
checkpointer=checkpointer,
interrupt_before=["analyze"] # 进入分析前暂停
)
# 第一步:执行到暂停点
state = graph.invoke({"query": "..."}, config=config)
# 此时图暂停在 analyze 节点之前
# 人工查看搜索结果,确认是否继续
print("搜索结果:", state["search_results"])
user_input = input("是否继续生成报告?(y/n): ")
if user_input == "y":
# 第二步:继续执行
result = graph.invoke(None, config=config) # None 表示继续而非重新开始真正上线时还要注意一个细节:从暂停点恢复时,暂停所在节点前面的代码可能会重新执行,因此有副作用的操作(发邮件、扣款、写数据库)必须做到幂等,或者放到 interrupt 之后执行。
优势与劣势
适合用 LangGraph 的场景:
- 任务流程有多个分支、循环、条件判断
- 需要在任意步骤插入人工审批
- 长任务需要可靠的中断恢复
- 需要精细控制每个节点的执行逻辑
不适合的场景:
- 简单的线性任务(3-5 步的 Sequential Agent,用 CrewAI、OpenAI SDK 或原生 API 更快)
- 快速原型验证(图的思维模型有额外概念负担)
- 团队不熟悉图论基础
LangGraph 的主要成本是学习曲线和工程纪律:State、Reducer、条件边、checkpoint、interrupt 组合在一起,一开始会比"写一个 while 循环调工具"重很多。但当任务需要长时间运行、可恢复、可审计、可人工介入时,这些概念会变成优势。
截至 2026.05,LangGraph 已进入 v1.x 文档体系,官方定位是面向 long-running、stateful agent 的底层编排基础设施。官方文档 [2]。
22.2 CrewAI
核心直觉
CrewAI 的核心思想是用角色扮演来组织 Multi-Agent 协作。你定义一个"研究员"、一个"作家"、一个"编辑",给他们各自的目标和工具,然后让他们按照某个流程(顺序、层级)协作完成任务。
它把 Agent 系统类比为一个职能团队:每个成员有自己的专长,有明确分工,通过任务传递协作。这个类比对非技术背景的团队来说非常直觉,是 CrewAI 快速普及的重要原因。
架构演进:从 Crew 到 Flows + Crews
CrewAI 的架构在 2025 年经历了一次重要演进,从单一的 Crew 概念演进为 Flows + Crews 双层架构(截至 2026.05,以官方文档 [3] 为准):
- Flow(工作流):应用的骨架。定义整体流程步骤、状态管理、条件逻辑和事件驱动执行。Flow 是确定性的编排层。
- Crew(团队):智能执行单元。在 Flow 的某个步骤里,当需要多个 Agent 协作处理复杂任务时,调用 Crew。Crew 是自主的 Agent 协作层。
用官方文档的话说:Flow 是"应用的管理者或流程定义者",Crew 是"完成繁重工作的团队"。
关键概念
Agent:一个角色化的 LLM 实例,有 role(角色)、goal(目标)、backstory(背景故事)和 tools(工具列表)。背景故事不是装饰——它是 System Prompt 的一部分,会影响模型的行为风格。
Task:分配给 Agent 的工作单元,包含 description(任务描述)、expected_output(期望输出格式)和 agent(负责执行的 Agent)。
Crew:Agent + Task 的组合,加上执行流程(Process.sequential 或 Process.hierarchical)。
sequential:任务按顺序执行,前一个任务的输出自动成为下一个任务的上下文hierarchical:有一个 Manager Agent 负责任务分配和质量把关,其他 Agent 是执行者
Flow:事件驱动的状态机,用 @start()、@listen() 等装饰器定义步骤。
快速构建内容生产流水线
from crewai import Agent, Task, Crew, Process
from crewai_tools import SerperDevTool
# 1. 创建工具
search_tool = SerperDevTool()
# 2. 定义 Agent(注意 backstory 会直接影响行为)
researcher = Agent(
role="资深研究分析师",
goal="发现关于 {topic} 最新、最重要的信息",
backstory=(
"你是一位经验丰富的研究分析师,擅长从海量信息中"
"提取关键洞察。你只引用可验证的来源,从不编造数据。"
),
tools=[search_tool],
verbose=True,
)
writer = Agent(
role="技术内容作家",
goal="将研究结果转化为清晰、准确的技术文章",
backstory=(
"你是一位技术写作专家,能将复杂概念转化为"
"工程师易读的内容。你重视准确性,不喜欢废话。"
),
verbose=True,
)
# 3. 定义 Task(expected_output 要具体,不要模糊)
research_task = Task(
description="研究 {topic},整理关键发现、技术细节和最新进展",
expected_output=(
"一份结构化的研究报告,包含:\n"
"- 核心概念解释\n"
"- 3-5 个关键技术点\n"
"- 引用来源列表"
),
agent=researcher,
)
write_task = Task(
description="基于研究报告,撰写一篇 1500 字的技术博客文章",
expected_output="完整的 Markdown 格式技术文章,包含标题、小节和代码示例",
agent=writer,
context=[research_task], # 明确声明依赖研究任务的输出
)
# 4. 组建 Crew
crew = Crew(
agents=[researcher, writer],
tasks=[research_task, write_task],
process=Process.sequential,
verbose=True,
)
# 5. 运行
result = crew.kickoff(inputs={"topic": "LLM Agent 评估方法"})
print(result.raw)Flows 的使用
对于需要跨步骤管理状态的复杂任务,新版 CrewAI 推荐使用 Flows:
from crewai.flow.flow import Flow, start, listen
from crewai import Agent, Task, Crew, Process
from pydantic import BaseModel
class ContentState(BaseModel):
topic: str = ""
research: str = ""
article: str = ""
class ContentCreationFlow(Flow[ContentState]):
@start()
def receive_topic(self):
# 从外部接收 topic(实际项目里可能来自 API)
self.state.topic = "AI Agent 框架对比"
return self.state.topic
@listen(receive_topic)
def research_topic(self, topic):
# 调用 Crew 做研究
researcher = Agent(role="研究员", goal="深入研究 {topic}", backstory="...")
task = Task(description="研究 {topic}", expected_output="详细报告", agent=researcher)
crew = Crew(agents=[researcher], tasks=[task])
result = crew.kickoff(inputs={"topic": topic})
self.state.research = result.raw
return result.raw
@listen(research_topic)
def write_article(self, research):
# 基于研究结果写文章
writer = Agent(role="作家", goal="将研究转化为文章", backstory="...")
task = Task(
description=f"基于以下研究写文章:{research}",
expected_output="完整文章",
agent=writer
)
crew = Crew(agents=[writer], tasks=[task])
result = crew.kickoff()
self.state.article = result.raw
return result.raw
# 运行 Flow
flow = ContentCreationFlow()
flow.kickoff()
print(flow.state.article)优势与劣势
适合用 CrewAI 的场景:
- 内容生产、研究报告、数据分析等有自然角色分工的任务
- 需要快速搭出 Multi-Agent 原型(入门时间以小时计)
- 团队背景多样,非工程人员也要能理解 Agent 配置
不适合的场景:
- 需要精细控制执行路径(比如在第 3 步里根据第 1 步结果做复杂分支)
- 对 Token 消耗敏感(角色背景故事会消耗 context,
verbose=True默认大量输出) - 需要强一致、可恢复的长事务状态管理(例如严格 checkpoint、exactly-once 副作用、细粒度 replay)
一个常见的踩坑:expected_output 写得太模糊会导致输出不稳定。"写一篇好文章"和"写一篇 1500 字的 Markdown 技术文章,包含标题、小节和至少一个代码示例",后者的结果可预期得多。
截至 2026.05,CrewAI 官方文档 [3] 仍在快速演进。选型时不要只看 GitHub Star 或教程数量,更应该看:Flows 是否满足你的状态管理需求、企业部署/观测能力是否符合团队要求、MCP 工具接入是否稳定、以及真实生产案例是否接近你的业务形态。
22.3 OpenAI Agents SDK
核心直觉
OpenAI Agents SDK 的设计哲学是用最少的原语解决最多的问题。它的核心团队来自早期的 Swarm 项目,那个项目证明了:三个原语——Agent、Handoff、Guardrails——足以描述绝大多数 Multi-Agent 场景 [4]。
和 LangGraph(图思维)、CrewAI(角色思维)不同,OpenAI SDK 用的是控制权转移的思维模型:系统里有多个 Agent,某一时刻只有一个 Agent 在"说话",Handoff 就是把控制权从一个 Agent 交给另一个 Agent。
三大原语
Agent:最基本的单元。一个 LLM + 一套 instructions + 一组 tools + 可选的 handoffs。
from agents import Agent
customer_service_agent = Agent(
name="客服助手",
instructions="你是一个友好的客服代表,帮助用户解决问题。",
tools=[get_order_status, process_refund],
)Handoffs(移交):把对话控制权交给另一个 Agent。移交后,那个 Agent 接管后续交互,前一个 Agent 退出。
Agents as Tools(Agent 作为工具):调用另一个 Agent 完成一个子任务,但调用 Agent 保留控制权,子任务的结果作为工具调用结果返回。
这两者的区别很关键,SDK 官方文档给出了清晰的对比 [4]:
| 模式 | 控制权 | 适用场景 |
|---|---|---|
| Handoff | 转移给目标 Agent | 路由式工作流,希望专家直接接管对话 |
| Agent as Tool | 保留在调用方 | 需要一个 Agent 协调多个专家、汇总结果 |
可以混用:一个分诊 Agent 用 Handoff 把用户转给专家,专家用 Agent as Tool 调用更小粒度的专项 Agent。
Guardrails(护栏):与主 Agent 并行执行的安全检查,输入校验或输出校验都可以。触发时抛出异常中断执行。第15章详细介绍了 Guardrails 的设计,这里专注 SDK 的使用方式。
构建一个多 Agent 客服系统
from agents import Agent, Runner, handoff, GuardrailFunctionOutput
from agents import input_guardrail, output_guardrail
from pydantic import BaseModel
import asyncio
# 1. 定义业务工具(实际项目里调用数据库/API)
def get_order_status(order_id: str) -> dict:
"""查询订单状态"""
# 模拟数据库查询
return {"order_id": order_id, "status": "已发货", "eta": "2026-05-03"}
def process_refund(order_id: str, reason: str) -> dict:
"""处理退款请求"""
return {"order_id": order_id, "refund_status": "退款已受理", "amount": 99.0}
def answer_faq(question: str) -> str:
"""回答常见问题"""
faqs = {
"配送时间": "标准配送 3-5 天,急速配送 1-2 天",
"退换货": "支持 7 天无理由退换货",
}
return faqs.get(question, "请联系人工客服")
# 2. 定义专业 Agent
order_agent = Agent(
name="订单专员",
instructions=(
"你专门处理订单相关问题:查询状态、处理退款。"
"处理完问题后,礼貌地询问是否有其他需要。"
),
tools=[get_order_status, process_refund],
)
faq_agent = Agent(
name="FAQ 专员",
instructions=(
"你负责回答常见问题:配送、退换货、优惠活动等。"
"用简洁准确的语言回答,避免废话。"
),
tools=[answer_faq],
)
# 3. Guardrail:检测恶意输入
class SafetyCheck(BaseModel):
is_safe: bool
reason: str
@input_guardrail
async def safety_guardrail(ctx, agent, input_text):
"""简单的安全检查:拦截明显恶意请求"""
dangerous_keywords = ["hack", "bypass", "injection", "ignore previous"]
is_safe = not any(kw in str(input_text).lower() for kw in dangerous_keywords)
return GuardrailFunctionOutput(
output_info=SafetyCheck(
is_safe=is_safe,
reason="检测到潜在恶意输入" if not is_safe else "输入安全"
),
tripwire_triggered=not is_safe,
)
# 4. 分诊 Agent(入口,根据用户意图转发)
triage_agent = Agent(
name="客服入口",
instructions=(
"你是客服入口,负责判断用户需求并转给合适的专员。\n"
"- 涉及订单、退款 → 转给订单专员\n"
"- 涉及配送、退换货政策等 FAQ → 转给 FAQ 专员\n"
"如果无法判断,直接回答用户,不要随意转发。"
),
handoffs=[
handoff(order_agent),
handoff(faq_agent),
],
input_guardrails=[safety_guardrail],
)
# 5. 运行
async def main():
result = await Runner.run(triage_agent, "我的订单 ORD-12345 到哪了?")
print(result.final_output)
asyncio.run(main())Sessions:跨轮次记忆
OpenAI SDK 的 Sessions 机制让 Agent 在多次运行间保持对话历史(截至 2026.05 [4])。注意:Session 是客户端侧的 conversation history 管理,不等于长期语义记忆;如果使用 OpenAI server-managed continuation(如 conversation / previous_response 机制),不要再叠加 SDK Session:
from agents import Agent, Runner, SQLiteSession
# SQLite 持久化 Session
session = SQLiteSession("user-123", "sessions.db")
agent = Agent(
name="助手",
instructions="你是一个记得用户偏好的助手。"
)
# 第一次对话
result1 = await Runner.run(
agent,
"我叫张三,我喜欢简洁的回答",
session=session
)
# 第二次对话(Agent 记得上次内容)
result2 = await Runner.run(
agent,
"我是谁?",
session=session # 同一个 session
)
print(result2.final_output) # "你是张三"Session 支持 SQLite,也可以通过 SDK 的自定义 Session 接口接入 Redis、PostgreSQL 等后端。多 Worker 生产部署时,不要用进程内内存 Session。
Sandbox Agents(沙箱 Agent)
对于需要在隔离环境运行代码的场景,SDK 在 2026 年 4 月新增了 Sandbox Agent 能力 [4][8]。截至 2026.05,这仍是 beta 能力,API 和默认行为可能继续变化。它提供受控工作区、文件系统、Shell / 代码执行和可恢复的 sandbox session,适合代码 Agent、数据分析 Agent、长任务文件处理。
from agents import Runner
from agents.run import RunConfig
from agents.sandbox import SandboxAgent, SandboxRunConfig
from agents.sandbox.sandboxes.unix_local import UnixLocalSandboxClient
sandbox_agent = SandboxAgent(
name="数据分析师",
instructions="你是一个数据分析专家,可以在受控工作区里读写文件并运行代码。",
)
result = await Runner.run(
sandbox_agent,
"分析工作区里的 data.csv,告诉我平均年龄",
run_config=RunConfig(
sandbox=SandboxRunConfig(client=UnixLocalSandboxClient())
),
)这里的重点不是"SDK 里有一个沙箱类"这么简单,而是执行边界:文件挂载、网络访问、持久化 workspace、外部存储(如 S3 / GCS / Azure Blob)、资源限制和审计都要按第 16、20 章的原则配置。默认本地 sandbox 不等于生产级隔离。
优势与劣势
适合用 OpenAI Agents SDK 的场景:
- 已经深入使用 OpenAI 生态(GPT 系列、Responses API)
- 快速构建 Multi-Agent 系统,不想学习图论
- 需要内置 Guardrails 一等公民支持
- Sandbox 执行是核心需求(代码 Agent、数据分析 Agent)
不适合的场景:
- 需要使用 Anthropic、Google 等非 OpenAI 模型作为主力(虽然 SDK 通过 LiteLLM 扩展支持其他模型,但默认优化是 OpenAI)
- 需要复杂的状态图和循环控制(Handoff 是有限状态机,不如 LangGraph 灵活)
- 需要对 Agent 执行轨迹进行精细 Replay 和调试
一个常见误解:Handoff 和函数工具是不同层次的抽象。函数工具是 Agent 在推理时调用外部 API;Handoff 是把整个对话上下文移交给另一个 Agent。前者类比打电话问信息,后者类比把客户转接给另一个客服。
22.4 其他框架速览
以下五个框架各有特定适用场景,了解它们的定位有助于在主流三个框架之外做出更合适的选型。
Google ADK
定位:Google 开源的 Agent 开发框架,深度绑定 Google Cloud、Vertex AI 和 Gemini 生态。截至 2026.05,ADK 2.0 处于 Alpha 阶段,官方明确提示不建议在需要向后兼容的生产环境中直接使用;但它展示了 Google 对图工作流、协作 Agent 和确定性编排的方向。
ADK 区分两种 Agent 类型 [5]:
- LLM Agent:由大模型驱动,动态决策,类似其他框架的 Agent
- Workflow Agent:确定性编排,包括 Sequential(顺序)、Loop(循环)、Parallel(并行)三种子类型
这个区分让 ADK 能优雅地混用 LLM 决策和确定性逻辑:
from google.adk import Agent
from google.adk.agents import SequentialAgent, LoopAgent
from google.adk.tools import google_search
# LLM Agent:动态决策
researcher = Agent(
name="researcher",
model="gemini-flash-latest",
instruction="You help users research topics thoroughly.",
tools=[google_search],
)
# Workflow Agent:确定性编排
pipeline = SequentialAgent(
name="research_pipeline",
agents=[researcher, writer_agent, reviewer_agent],
)ADK 的 A2A(Agent-to-Agent)协议支持(第14章有详细介绍)让它在多 Agent 互操作场景下有天然优势。但 A2A 仍在快速演进,跨组织互操作不能只看协议名,还要验证认证、授权、审计和数据边界。
适用场景:已使用 Google Cloud、Vertex AI 或 Gemini 的团队;需要混用 LLM 决策和确定性 Workflow 的系统;愿意跟进 ADK 生态变化、并能接受 Alpha / Preview 能力边界的团队。
Microsoft Agent Framework
定位:Microsoft Agent Framework 是 Microsoft 新一代 Agent 框架,融合了 AutoGen 的多 Agent 抽象和 Semantic Kernel 的企业能力。官方定位是 Semantic Kernel / AutoGen 在 Agent 场景下的后继方向,目前处于 public preview [6]。
它提供两类能力:
- Agents:单个 Agent 处理输入、调用工具 / MCP Server、生成响应
- Workflows:图式工作流,连接 Agent 和函数,支持多步骤任务、类型安全路由、checkpoint 和 human-in-the-loop
它还提供 session state、context providers、middleware、telemetry、MCP client 和多模型 provider,面向 Azure / Microsoft 生态里的企业应用。
# 简化示意,具体导入以 Microsoft Agent Framework 当前版本为准
from agent_framework.foundry import FoundryChatClient
from azure.identity import AzureCliCredential
client = FoundryChatClient(
project_endpoint="https://your-foundry-service.services.ai.azure.com/api/projects/your-project",
model="<your-model>",
credential=AzureCliCredential(),
)
agent = client.as_agent(
name="HelloAgent",
instructions="你是一个简洁的企业助手。",
)
result = await agent.run("帮我总结这个工单")
print(result)适用场景:已深度使用 Azure / Microsoft 生态;需要 .NET / Python 双栈;企业内部需要 Foundry、M365、Azure Functions、MCP、A2A、AG-UI 等平台集成;团队愿意接受 public preview 带来的 API 变化风险。
Claude Agent SDK
定位:Anthropic 面向 Claude Agent / Claude Code 能力开放的开发 SDK。它不是一个通用工作流框架,而是把 Claude Code 的 agentic loop、上下文管理、文件/命令行工具、权限控制和流式输出能力提供给开发者,用于构建代码 Agent、内部工程助手和自动化开发工具 [7]。
最需要区分的是两种形态:
- Claude Agent SDK:你在自己的进程或服务里运行 Agent,自己负责部署、权限、工具边界、审计和成本控制。
- Managed Claude Agents:Anthropic 托管 Agent 执行环境,适合希望少管基础设施、直接接入托管执行能力的团队。
一个最小示意:
import asyncio
from claude_agent_sdk import ClaudeAgentOptions, query
async def main():
options = ClaudeAgentOptions(
allowed_tools=["Read", "Edit", "Bash"],
permission_mode="acceptEdits",
)
async for message in query(
prompt="阅读这个仓库,修复 failing tests",
options=options,
):
print(message)
asyncio.run(main())Claude Agent SDK 的价值在于"把 Claude 当作能操作工程环境的 Agent",不是把任意业务流程都塞进代码 Agent。生产使用时尤其要控制:
- 工具白名单:
Bash、文件编辑、网络访问都要最小授权。 - 工作区隔离:每个任务最好有独立 workspace,避免跨用户/跨仓库污染。
- 审批点:写文件、执行破坏性命令、创建 PR、访问 secret 前要有策略或人工确认。
- 审计与回放:记录工具调用、diff、命令输出摘要和最终变更,方便复盘。
适用场景:代码库理解、测试修复、代码迁移、内部开发助手、CI 失败自动诊断;不适合拿来做纯客服、内容生成、强业务状态流转等通用 Agent 编排。
smolagents(HuggingFace)
定位:HuggingFace 出品的轻量级 Agent 框架,主打极简和快速原型。截至 2026.05 [9]。
smolagents 有一个独特的 CodeAgent:它不是把动作表示为 JSON 工具调用,而是让模型直接写 Python 代码来操作工具。Python 代码的组合能力(嵌套函数、循环、条件)比 JSON 工具调用更灵活:
from smolagents import CodeAgent, InferenceClientModel, DuckDuckGoSearchTool, PythonInterpreterTool
model = InferenceClientModel(model_id="meta-llama/Llama-3.3-70B-Instruct")
# CodeAgent:动作以 Python 代码形式表达
agent = CodeAgent(
tools=[DuckDuckGoSearchTool(), PythonInterpreterTool()],
model=model,
max_steps=10,
)
# Agent 会生成并执行 Python 代码来完成任务
result = agent.run("查找 LangGraph 的 GitHub star 数量,然后计算它和 CrewAI star 数的比值")
print(result)CodeAgent 的优势:代码可以自然地表达"先做 A,根据 A 的结果再决定做 B 还是 C",不需要框架提供特殊的条件路由机制。代价是安全风险更高——模型生成的代码需要在沙箱里执行(smolagents 支持 Modal、E2B 等沙箱)。
适用场景:研究和原型阶段,希望最快速地验证 Agent 想法;需要模型自主编写复杂计算逻辑;需要与 HuggingFace Hub 深度集成(从 Hub 加载模型、工具、Agent)。
框架能力横向对比
截至 2026.05,各框架核心能力对比如下。注意这张表是选型线索,不是采购清单:框架能力变化很快,真正选型前要用你的工具、权限模型、部署方式和 eval 套件做一次小型 PoC。
| 维度 | LangGraph | CrewAI | OpenAI Agents SDK | Google ADK | Microsoft Agent Framework | Claude Agent SDK | smolagents |
|---|---|---|---|---|---|---|---|
| 核心抽象 | 有状态图 | 角色 + 任务 + Flow | Agent + Handoff + Guardrails | LLM Agent + Workflow Agent | Agent + Workflow | Claude Code 式执行循环 | CodeAgent |
| 学习曲线 | 陡 | 平缓 | 平缓 | 中 | 中 | 中 | 极平缓 |
| 状态控制粒度 | 极高 | 中(Flow)/ 低(Crew) | 中 | 中 | 中高 | 低到中 | 低 |
| 持久化/Checkpoint | 内置多后端 | Flow 状态 | Sessions | Session / State | Checkpoint / session state | 依赖运行环境 | 无内置 |
| 人工介入 | 强 | 基础 | Guardrail / 应用层 | 需按平台设计 | Workflow / middleware | 权限确认适配代码任务 | 需自建 |
| 沙箱执行 | 需自建 | 需自建 | 内置 Sandbox | 需自建 | 需结合 Azure/容器 | 面向工程工作区 | Modal / E2B |
| 可观测性 | LangSmith | 基础日志 / Enterprise | Tracing | Google Cloud | Azure / OpenTelemetry | 工具轨迹 / 外部日志 | 基础日志 |
| MCP / 工具生态 | 通过适配器或自封装 | 文档支持 | 原生 MCP | MCP / A2A 生态 | MCP client | 内置工程工具 + MCP 扩展 | MCP / Hub 工具 |
| 最适合 | 复杂流程、长任务、审批 | 角色分工型任务 | OpenAI 生态内快速交付 | Google Cloud / Gemini | Azure / .NET / 企业集成 | 代码 Agent | 原型和研究 |
选型落地清单
真正的框架选型不要从"哪个框架最火"开始,而要从最小可验证问题开始。建议用 1-2 周做一个 thin slice:选一个真实任务、接入真实工具、跑真实权限边界,然后用第 18 章的 eval 方法看成功率和失败类型。
PoC 至少回答这些问题:
- 状态是否能解释清楚:失败时能不能知道卡在哪个节点、哪个 handoff、哪个工具调用?
- 副作用是否可控:发邮件、写数据库、改代码、扣款这类动作能否审批、幂等、回滚或补偿?
- 权限是否贴近生产:是否支持按用户、租户、工具、资源、时间窗口下发最小权限?
- 评估是否能接入 CI/CD:框架的 trace、工具调用和状态快照能否转成回归 eval 样本?
- 成本是否可观测:能否按任务、模型、工具、重试、缓存命中率拆分成本?
- 迁移成本是否可接受:业务层是否被框架 API 深度污染,是否能把工具、prompt、memory、eval 资产迁到另一个框架?
一个实用结论:如果你还说不清楚状态机,就先用简单框架或原生 API;如果你已经开始画流程图、审批点和失败恢复路径,LangGraph / Microsoft Agent Framework 这类 workflow-first 框架通常更合适;如果核心任务是改代码或操作仓库,Claude Agent SDK / OpenAI Sandbox Agent / smolagents + 沙箱才是更直接的起点。
常见误区
误区一:框架越功能强,Agent 越可靠
LangGraph 功能最强,不代表用 LangGraph 写出来的 Agent 就更可靠。可靠性来自:好的工具设计、充分的错误处理、完整的评估体系。一个用 OpenAI SDK 写的简单 Agent,如果工具描述清晰、错误处理完备、有完整的 eval,比一个用 LangGraph 写的大图但没有测试的 Agent 可靠得多。
误区二:Handoff 等于 LangGraph 的条件边
Handoff 是控制权完全转移——被 handoff 的 Agent 接管对话,之前的 Agent 不再参与。LangGraph 的条件边是执行路径的分支,所有节点都在同一张图里,共享同一个状态。前者是"转接客服",后者是"走不同流程分支"。
误区三:CrewAI 的 Crew 等于 Multi-Agent
一个 Crew 里的 Agent 是协作完成同一个整体任务,它们的角色是互补的。真正的 Multi-Agent 系统里,Agent 是独立的决策单元,可以相互委托、并行执行、有自己的上下文隔离。如果你的场景是独立任务并行,CrewAI 的 Process.hierarchical + Manager Agent 能处理,但不如 LangGraph 或 OpenAI SDK 的控制权转移模型直观。
误区四:选定框架就不能换
这是真实存在的风险,但不是无解的。诀窍是:在应用层做好抽象,不要让框架 API 直接散落在业务代码里。把 Agent 核心逻辑包在一个业务层类里,框架只出现在底层实现里。这样换框架时,改动范围局限在底层,业务逻辑不需要动。
面试高频题
问:你的项目选了哪个 Agent 框架?为什么选这个而不是其他的?
参考答案框架:
- 描述需求约束(任务类型、团队规模、技术栈、上线时间)
- 说明候选方案(至少比较两个框架)
- 说明决策依据(不是"哪个更强",而是"哪个更符合这个场景")
- 提及实际使用中遇到的问题和取舍
加分点:能说出框架的限制和踩过的坑,而不只是说优点。能讲出框架底层机制(比如 LangGraph 的 Reducer、OpenAI SDK 的 Handoff 原理)。
问:LangGraph、CrewAI、OpenAI SDK 分别适合什么场景?如果只能选一个,你选哪个?
简要框架:
- LangGraph:复杂状态流转、循环、人工介入点、精细 Checkpoint 需求
- CrewAI:有自然角色分工的多步任务、快速原型、非技术背景团队协作
- OpenAI SDK:简洁的 Multi-Agent 路由、深度 OpenAI 生态、需要一等公民 Guardrails
- "只能选一个":要反问具体场景,不存在跨场景最优解。如果真要默认选,先用 OpenAI SDK 或 CrewAI 跑通原型,如果状态控制需求超出它们的能力,再迁移到 LangGraph。
问:如果不用任何框架,你怎么实现 Agent 的多步推理?框架帮你省掉了哪些代码?
回答要点:原生实现需要手写工具注册、调用循环(while stop_reason != "end_turn")、消息历史管理、错误重试、状态持久化。框架封装了这些样板代码。理解框架底层机制的标志是:能在 30 分钟内用原生 API 写出一个基础 Agent(参考第25章)。
参考资料
[1] Building Effective Agents - Anthropic (https://www.anthropic.com/engineering/building-effective-agents)
[2] LangGraph 官方文档 (https://langchain-ai.github.io/langgraph/)
[3] CrewAI 官方文档 (https://docs.crewai.com/introduction)
[4] OpenAI Agents SDK 官方文档 (https://openai.github.io/openai-agents-python/)
[5] Google ADK 官方文档 (https://adk.dev/)
[6] Microsoft Agent Framework 官方文档 (https://learn.microsoft.com/en-us/agent-framework/)
[7] Claude Agent SDK 官方文档 (https://code.claude.com/docs/en/agent-sdk)
[8] OpenAI Agents SDK Sandbox 文档 (https://openai.github.io/openai-agents-python/sandbox/guide/)
[9] smolagents 官方文档 (https://huggingface.co/docs/smolagents/en/index)