langgraph可构建具备多轮自我修正、条件跳转与人工干预能力的ai agent:需用typeddict定义状态、add_conditional_edges实现分支、add_edge构造循环,并通过human_review节点与stream调试确保可控性。
☞☞☞AI 智能聊天, 问答助手, AI 智能搜索, 多模态理解力帮你轻松跨越从0到1的创作门槛☜☜☜

你需要让Grok大模型驱动的AI Agent具备多轮自我修正、条件跳转和人工干预能力,而不是写一堆if-else硬逻辑去模拟流程。LangGraph提供的图结构恰好能承载这种动态行为,而Grok可通过LangChain适配器无缝接入。
准备Grok模型接入环境
第一步,安装支持Grok的LangChain组件。Grok-2和Grok-3均通过xai官方API提供服务,必须使用langchain-xai包而非通用openai兼容层:
pip install langchain-xai
第二步,设置环境变量。XAI要求显式声明API密钥与模型版本,不能省略model参数:
【XAI_API_KEY必须设为有效密钥,否则后续所有节点调用会静默失败】
export XAI_API_KEY="your_actual_xai_key_here"
export GROK_MODEL_NAME="grok-beta"
第三步,初始化Grok LLM实例。注意:必须传入model_name,且不能使用ChatOpenAI类——它会绕过xai专用认证流程:
from langchain_xai import ChatXAI
llm = ChatXAI(model_name="grok-beta", temperature=0.3)
定义带循环与分支的状态结构
LangGraph不接受普通字典作为状态容器,必须用TypedDict严格声明字段类型和合并策略。messages字段若未标注operator.add,新消息将覆盖旧消息而非追加:
from typing import TypedDict, Annotated
import operator
from langchain_core.messages import AnyMessage
class AgentState(TypedDict):
messages: Annotated[list[AnyMessage], operator.add]
retry_count: int
needs_human_review: bool
这一步漏掉Annotated和operator.add,会导致对话历史在节点间流转时丢失——你看到的“Agent突然忘记前文”问题几乎都源于此。
构建含条件边与循环边的图
方法一:用add_conditional_edges实现意图驱动分支
先注册基础节点:
graph.add_node("router", router_func)
graph.add_node("search", search_tool_node)
graph.add_node("analyze", analyze_node)
graph.add_node("human_review", human_review_node)
再添加条件边——注意返回值必须是字符串,且必须与已注册节点名完全一致:
graph.add_conditional_edges(
"router",
lambda state: "search" if "查" in state["messages"][-1].content else "analyze"
)
方法二:用add_edge实现强制循环回退
当分析结果置信度低于阈值时,需要回到router重新决策。此时不能用conditional edge(它只支持单次判断),而要用显式add_edge构造循环路径:
graph.add_edge("analyze", "router")
但必须配合状态更新逻辑:在analyze_node函数末尾手动设置state["retry_count"] += 1,并在router中检查该值是否超限,否则会无限循环。
方法三:插入人工干预节点并保留上下文
在关键决策点插入human_review节点后,必须确保其输出能被后续节点读取。LangGraph默认不自动传播状态,需显式返回完整state字典:
def human_review_node(state: AgentState) -> AgentState:
# 调用外部审批接口或等待人工输入
state["needs_human_review"] = False
return state # 必须return,否则状态丢失
编译并运行支持流式输出的Agent
第一步:调用compile()生成可执行图实例。不调用compile就直接run会抛出AttributeError:
app = graph.compile()
第二步:启用stream()进行单步调试。这是排查死循环最有效的手段——每步执行后立即打印当前节点名和状态快照:
for chunk in app.stream({"messages": [HumanMessage(content="帮我查上海今天天气")]}, stream_mode="values"):
print("→", list(chunk.keys())[-1])
第三步:传入config参数启用检查点持久化。没有这个参数,中断后无法恢复状态:
config = {"configurable": {"thread_id": "abc123"}}
result = app.invoke({"messages": [...]}, config=config)
第四步:验证循环退出机制。向router节点注入伪造的低置信度响应,观察是否在retry_count达到3时跳转至human_review节点——这是唯一能确认循环控制逻辑生效的操作。











