入口 · 三家 agent loop 的骨架
用户的第一行调用——create_agent(...) / Runner.run(...) / agent.run(...)——下面到底发生了什么?三家代码并排,你会看到"同样的 ReAct loop,三种正交的复杂度策略"。
Core Curriculum
Level 3 · 源码迁移
阅读时间 · 24 分钟
练习 · 建议必做
中波动
Last reviewed · 2026-04-22
你将学会什么
- 理解《入口 / 三家 agent loop 的骨架》在 agent harness / coding agent 学习路径里的核心作用。
- 能用本页给出的判断法区分“概念、机制、边界、代价”。
- 知道这页内容之后会在哪一章被复用到源码阅读或动手实践里。
学习前提
建议先读《怎么读 Agent 源码 / 4 步法 + 8 维尺》;如果你是跳读,至少先看本章索引与本页 TL;DR。
这页在课程中的位置
进阶理解层,把抽象落实到真实代码与状态机。
本页 1 句话结论
用户的 第一行 调用—— create_agent(...) / Runner.run(...) / agent.run(...) ——下面到底发生了什么?三家代码并排,你会看到" 同样的 ReAct loop,三种正交的复杂度策略 "。
带走的判断法
先追 entry / state / extension points,再看 API 名字。
Source Policy
课程主线:源码 + 官方 docs + 版本上下文。
这一节的 3 个核心结论
- LangChain 把 agent loop 编译成 LangGraph 图——entry 函数本质是个 graph builder,运行时交给 LangGraph runtime 跑。结构化、声明式、重。
- OpenAI Agents SDK 把 agent loop 包成 async runtime——entry 函数挂上 trace context,把实际循环 delegate 给
AgentRunner。异步、可观测、中等复杂度。
- smolagents 把 agent loop 就是个 while 循环——entry 函数 ~20 行: 装 system prompt → for step in range(max_steps) → call LLM → parse → execute。极简、透明、所有抽象都直白。
- 这三种风格都对——选择取决于你的目标用户:要灵活组合 → LangChain;要可观测 + tool ecosystem → Agents SDK;要快速看穿 + 改造 → smolagents。不存在"最好的 agent loop 实现"。
LangChain create_agent 133K★
OpenAI Agents SDK Runner official
HuggingFace smolagents 26K★
用户视角的 entry call
from langchain.agents import create_agent
agent = create_agent(
model="anthropic:claude-sonnet-4-6",
tools=[get_weather],
system_prompt="You are a helpful assistant",
)
result = agent.invoke({"messages": [{"role": "user", "content": "sf weather?"}]})
signature 抽出来 · "用户能配什么"清单
# langchain/agents/factory.py · create_agent
def create_agent(
model: str | BaseChatModel,
tools: Sequence[BaseTool | Callable | dict] | None = None,
*,
system_prompt: str | None = None,
middleware: Sequence[AgentMiddleware] = (),
response_format: ResponseFormat | type | None = None,
state_schema: type[AgentState] | None = None, # ← TypedDict
context_schema: type | None = None,
checkpointer: Checkpointer | None = None, # ← LangGraph 持久化
store: BaseStore | None = None, # ← 跨 thread 长记忆
interrupt_before: list[str] | None = None, # ← HITL 注入点
interrupt_after: list[str] | None = None,
debug: bool = False,
name: str | None = None,
cache: BaseCache | None = None,
) -> CompiledStateGraph[AgentState, ContextT, _InputAgentState, _OutputAgentState]:
"""Creates an agent graph that calls tools in a loop until a stopping condition is met."""
...
看 signature 13 个参数 → 这是给 framework 集成商的 API,不是给 hello-world 用户。checkpointer / store / interrupt_* 等参数已经把"持久化 + HITL"作为 first-class 一等公民——这是 LangChain v1.0 把 LangGraph 嫁接进来的产物。
实现骨架 · 不到 200 行做了 4 件事
# 简化骨架(实际 ~180 行;完整代码见 GitHub link 顶部)
def create_agent(model, tools=None, *, system_prompt=None, middleware=(), state_schema=None, ...):
# ① 规整化输入
model = init_chat_model(model) if isinstance(model, str) else model
tools = _normalize_tools(tools or [])
state_schema = state_schema or _default_state_schema(response_format)
# ② 把 middleware 链合并成统一 state schema
merged_state = _merge_state_schemas([m.state_schema for m in middleware] + [state_schema])
# ③ 构造 LangGraph StateGraph,加节点:model 节点 + tools 节点
graph = StateGraph(merged_state)
graph.add_node("model", _build_model_node(model, tools, system_prompt, middleware))
graph.add_node("tools", ToolNode(tools))
# ④ 加边:model → conditional → (tools | END), tools → model
graph.add_edge(START, "model")
graph.add_conditional_edges("model", _should_continue, {"tools": "tools", "end": END})
graph.add_edge("tools", "model")
# ⑤ 编译,把持久化 / 中断 / 缓存挂上去
return graph.compile(
checkpointer=checkpointer, store=store,
interrupt_before=interrupt_before, interrupt_after=interrupt_after,
cache=cache, name=name, debug=debug,
)
call graph · invoke 一次会跳到这些文件
↓ user code
user.py → agent.
invoke(messages)
↓ langgraph runtime 接管
langgraph/pregel/__init__.py → Pregel.invoke()
langgraph/pregel/loop.py → PregelLoop.tick()
while True:
langgraph/_internal/_runnable.py → 跑当前节点
↓ 进入 model 节点(factory 里 _build_model_node 创建的闭包)
langchain/agents/factory.py → 跑所有
before_model middleware
→ 调 model.
bind_tools().
invoke()
langchain_anthropic/chat_models.py → HTTP request
→ AIMessage(tool_calls=[..
Members only
解锁完整课时
订阅会员后可阅读本课全部内容,并访问课程内所有章节。