从零构建AI Agent:目标驱动系统与LangGraph实战指南
上周一个刚接触大模型应用开发的朋友问我“现在到处都在说 AI Agent我看了很多文章感觉它就是一个能自动调用工具的聊天机器人这和我自己写个脚本调用 API 有什么区别”这个问题很典型。很多人对 Agent 的第一印象就是“能联网搜索的 ChatGPT”或者“能自动写代码的 Copilot”。这种理解没错但只看到了冰山一角。Agent 真正的价值不在于它能调用一两个工具而在于它代表了一种全新的、以目标为导向的、具备自主规划和执行能力的计算范式。它不是一个“更聪明的函数”而是一个“能自己想办法完成任务的小助手”。今天我们不谈那些宏大的概念就从最基础的认知和一次完整的实操开始带你亲手搭建并理解一个真正的 Agent。你会发现从“调用 API”到“构建 Agent”中间隔着一整套关于规划、记忆、工具使用和反思的工程化思维。1. 先拆解Agent 不是“自动脚本”而是“目标驱动系统”在动手之前我们必须先统一认知Agent 和传统程序或脚本的核心区别是什么很多人混淆了“自动化”和“自主化”。1.1 从“指令响应”到“目标驱动”一个传统的脚本或 API 调用程序是指令响应式的。你告诉它“去查一下北京的天气然后告诉我。” 程序会忠实地执行fetch_weather(Beijing)并返回结果。如果查询失败它就报错然后停止。一个 Agent是目标驱动式的。你告诉它“帮我规划一个周末的北京出游行程要考虑到天气和交通。” Agent 会自己分解这个目标理解目标需要行程、天气、交通信息。制定计划先查天气再根据天气推荐室内或室外活动接着查找活动地点和交通路线最后整合成行程表。执行计划调用天气查询工具 - 分析结果 - 调用地图/地点搜索工具 - 分析结果 - 调用路线规划工具 - 整合信息。评估与调整如果发现某个景点周一闭馆而行程是周日它会意识到矛盾重新调整计划。在这个过程中Agent 自己决定什么时候调用什么工具并根据中间结果动态调整后续步骤。这种“思考-行动-观察”的循环是 Agent 的灵魂。1.2 Agent 的核心组件一个都不能少要构建一个具备上述能力的系统它通常需要以下几个核心组件我们可以将其类比为一个项目团队组件类比作用如果没有会怎样规划 (Planning)项目经理将大目标拆解为可执行的任务序列并决定执行顺序。变成无头苍蝇要么一步都动不了要么胡乱调用工具无法达成复杂目标。工具使用 (Tool Use)专业技能员工Agent 的“手”和“脚”。用于获取信息搜索、查询数据库或执行操作发送邮件、写文件。空有想法无法落地。只能“空想”不能“实干”。记忆 (Memory)项目文档与会议纪要存储对话历史、工具调用结果、学到的知识。分为短期记忆当前会话和长期记忆跨会话知识。每次交互都像第一次见面无法进行多轮复杂协作也无法从历史中学习。反思 (Reflection)项目复盘会对自身行动和结果进行评估判断是否偏离目标是否需要调整策略。一条道走到黑即使结果明显错误或低效也不会回头优化。现在流行的 Agent 框架如 LangChain、LangGraph、AutoGen 等本质上都是在用不同的架构和范式来组织、协调这些组件让它们高效、稳定地协作。2. 再动手从零构建一个“旅游规划Agent”概念讲再多不如亲手做一遍。我们以“周末北京出游规划”为目标使用当前主流且对开发者友好的LangGraph框架来构建一个 Agent。选择 LangGraph 是因为它用“图”来定义工作流非常直观地体现了 Agent 的决策路径。环境准备提示以下示例基于 Python。请确保已安装 Python 3.8。我们将使用langgraph,langchain-openai,langchain-community等库。建议在虚拟环境中操作。2.1 第一步定义 Agent 的“手脚”工具Agent 需要通过工具与外界交互。我们先定义两个最基础的工具天气查询和地点搜索。# 示例工具定义 (tools.py) import requests from langchain.tools import tool from typing import Optional tool def get_weather(city: str) - str: 获取指定城市的当前天气信息。 # 注意这里使用一个模拟的天气API真实场景请替换为可靠的API如和风、OpenWeatherMap # 并妥善处理API Key和请求限制。 try: # 模拟API返回 mock_data { Beijing: 晴朗气温 15-25°C微风, Shanghai: 多云气温 18-28°C东南风3级, } weather mock_data.get(city, 暂未找到该城市天气信息) return f{city}的天气{weather} except Exception as e: return f查询天气时出错{e} tool def search_places(location: str, keyword: str) - str: 在指定城市搜索特定类型的地点如‘博物馆’、‘公园’。 # 模拟地点搜索真实场景可接入高德、百度地图API try: mock_places { (Beijing, museum): 1. 中国国家博物馆\n2. 故宫博物院\n3. 中国科学技术馆, (Beijing, park): 1. 颐和园\n2. 天坛公园\n3. 北海公园, } result mock_places.get((location, keyword), f在{location}未找到相关的{keyword}信息。) return f{location}的{keyword}推荐\n{result} except Exception as e: return f搜索地点时出错{e}关键点使用tool装饰器可以将一个函数转化为 LangChain 能识别的工具。清晰的文档字符串非常重要因为 LLM 会阅读它来决定是否以及如何调用这个工具。2.2 第二步为 Agent 配备“大脑”模型与提示词Agent 的“思考”能力来源于大语言模型LLM。我们需要定义模型和引导其行为的系统提示词。# 示例模型与提示词配置 (agent_core.py) from langchain_openai import ChatOpenAI from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder from langchain.agents import create_react_agent from langchain.agents.output_parsers import ReActSingleInputOutputParser # 1. 初始化LLM这里以OpenAI GPT-4为例你也可以使用其他兼容API的模型 # 请将 YOUR_OPENAI_API_KEY 替换为你的实际API Key或通过环境变量设置 llm ChatOpenAI(modelgpt-4-turbo-preview, temperature0, api_keyYOUR_OPENAI_API_KEY) # 2. 定义系统提示词设定Agent的角色和目标 system_prompt 你是一个专业的旅游规划助手。你的目标是根据用户的需求规划出合理的行程。 你可以使用以下工具来获取必要信息 - get_weather: 查询城市天气。 - search_places: 搜索某个城市内的特定类型地点。 请遵循以下步骤思考 1. 理解用户的请求明确目的地、时间、兴趣点等关键信息。 2. 根据需要有计划地调用工具获取信息如先查天气再根据天气推荐活动类型。 3. 综合所有信息生成一份详细、可行、包含时间安排的行程建议。 4. 如果信息不足请礼貌地向用户询问更多细节。 请始终以用户的体验和需求为第一考量。为什么提示词这么重要它设定了 Agent 的“性格”和“工作流程”。好的提示词能极大减少 Agent 的无效动作和逻辑混乱。这里我们采用了 ReActReasoning Acting模式的提示思路要求模型先“思考”再“行动”。2.3 第三步用 LangGraph 组装“工作流”图与状态这是最核心的一步。我们将使用 LangGraph 定义 Agent 的决策循环思考 - 决定行动 - 执行行动 - 观察结果 - 继续思考或结束。# 示例定义 LangGraph 工作流 (travel_agent_graph.py) from typing import TypedDict, Annotated, Sequence import operator from langchain_core.messages import BaseMessage, HumanMessage, AIMessage, ToolMessage from langgraph.graph import StateGraph, END from langgraph.prebuilt import ToolExecutor, ToolInvocation from langchain_core.tools import BaseTool # 1. 定义图的状态State # 状态记录了整个对话和任务执行过程中的所有信息 class AgentState(TypedDict): messages: Annotated[Sequence[BaseMessage], operator.add] # 消息序列会不断追加 # 可以在此添加其他状态如‘plan’ ‘current_step’等 # 2. 创建工具执行器 tools [get_weather, search_places] # 引入之前定义的工具 tool_executor ToolExecutor(tools) # 3. 定义节点函数 def should_continue(state: AgentState) - str: 判断工作流应该继续调用工具还是结束回复用户。 last_message state[messages][-1] # 如果上一条消息是 AI 消息且包含工具调用则继续执行工具 if isinstance(last_message, AIMessage) and last_message.tool_calls: return call_tools # 否则工作流结束将结果返回给用户 return end def call_model(state: AgentState): 调用LLM决定下一步做什么。 messages state[messages] # 将系统提示词和对话历史组合成完整的提示 prompt ChatPromptTemplate.from_messages([ (system, system_prompt), MessagesPlaceholder(variable_namemessages), ]) chain prompt | llm response chain.invoke({messages: messages}) # 将模型的响应添加到消息历史中 return {messages: [response]} def call_tools(state: AgentState): 执行AI决定要调用的工具。 last_message state[messages][-1] # 获取最新的AI消息 tool_calls last_message.tool_calls # 提取其中的工具调用指令 tool_invocations [] for tc in tool_calls: # 将模型输出的工具调用格式转化为ToolInvocation对象 tool_invocations.append(ToolInvocation(tooltc[name], tool_inputtc[args])) # 并行执行所有被调用的工具 tool_outputs tool_executor.batch(tool_invocations) # 为每个工具执行结果生成一条ToolMessage并添加到历史中 tool_messages [] for output, tc in zip(tool_outputs, tool_calls): tool_messages.append(ToolMessage(contentstr(output), tool_call_idtc[id])) return {messages: tool_messages} # 4. 构建图 workflow StateGraph(AgentState) # 添加节点 workflow.add_node(agent, call_model) # “思考”节点 workflow.add_node(tools, call_tools) # “行动”节点 # 设置入口点 workflow.set_entry_point(agent) # 添加条件边 workflow.add_conditional_edges( agent, should_continue, # 条件判断函数 { call_tools: tools, # 如果需要调用工具前往“tools”节点 end: END # 如果结束直接到终点 } ) # 从“工具”节点执行完后无条件回到“agent”节点进行下一轮思考 workflow.add_edge(tools, agent) # 编译图 app workflow.compile()理解这个图这个工作流形成了一个循环agent - (判断) - tools - agent - ...。Agent 思考后如果决定调用工具就执行工具并将结果带回给 Agent 进行下一轮思考直到它认为任务完成输出最终答案给用户。2.4 第四步运行与对话现在让我们启动这个 Agent 并与之对话。# 示例运行Agent (run_agent.py) from langchain_core.messages import HumanMessage # 初始化对话 initial_state {messages: [HumanMessage(content帮我规划一下这个周末在北京的行程我喜欢博物馆。)]} # 运行图 final_state app.invoke(initial_state, config{recursion_limit: 10}) # 限制递归深度防止死循环 # 打印最终结果 for msg in final_state[messages]: if isinstance(msg, AIMessage) and not msg.tool_calls: # 找到最终的非工具调用AI回复 print( 旅游规划助手 ) print(msg.content) break预期的执行流程你输入请求。agent节点LLM思考“用户要规划北京周末博物馆行程。我需要天气信息来安排室内外活动还需要具体的博物馆列表。”LLM 决定调用get_weather(Beijing)和search_places(Beijing, museum)。流程走向tools节点执行这两个工具调用获得结果。结果以ToolMessage形式返回流程回到agent节点。LLM 收到天气和博物馆信息开始整合“周六天气晴朗适合上午去户外公园下午参观博物馆周日可能转阴全天安排室内博物馆……”LLM 判断信息已足够生成最终行程建议流程结束。通过 LangGraph 的可视化工具你甚至可以清晰地看到这个“思考-行动”的循环图这对于调试复杂 Agent 逻辑至关重要。3. 深入思考从“跑通Demo”到“可用系统”的鸿沟恭喜你你已经构建了一个最基本的 Agent它能理解目标、调用工具、并给出规划。但如果你想把这样的 Agent 投入实际使用哪怕是个人使用都会立刻遇到 Demo 中不会体现的工程挑战。3.1 稳定性挑战当 Agent“卡住”或“跑偏”在测试中你可能会遇到逻辑循环Agent 反复查询同一个信息陷入死循环。例如查了天气又问“今天星期几”然后又去查天气。工具调用错误给工具传递了错误的参数类型或格式。目标漂移在多轮交互后忘记了最初的核心目标被细节带偏。应对策略设置递归/循环上限就像我们在app.invoke中设置的recursion_limit这是防止死循环的基本保障。优化提示词工程在系统提示中明确约束如“每个工具在同一会话中最多调用一次”、“请先明确最终目标再行动”。引入“反思”节点在 LangGraph 中你可以在agent节点后加入一个reflect节点让 LLM 评估当前进展是否偏离目标并决定继续、调整或终止。这才是 Agentic 中“反思”能力的体现。3.2 效率与成本挑战我们的 Demo 是顺序执行的。但在真实场景中工具调用应是并行的查询天气和搜索博物馆可以同时进行而不是先后。LLM 调用是主要成本每一次“思考”call_model都消耗 Token产生费用。不必要的思考步骤会显著增加成本。应对策略利用 LangGraph 的并行能力可以设计更复杂的图让多个工具调用节点并行执行。设计更高效的规划策略让 LLM 一次性规划出所有需要的工具调用然后批量执行减少“思考-行动”的轮次。这就是ReWOOReasoning Without Observation等范式想解决的问题。使用更小、更快的模型对于简单的工具调用决策可能不需要 GPT-4Claude Haiku 或本地小模型可能就足够了。3.3 记忆与上下文管理挑战我们的 Demo 使用了最简单的对话历史作为记忆。但当对话很长、任务很复杂时LLM 的上下文窗口会不够用且无关历史会干扰当前决策。应对策略分级记忆系统短期记忆当前任务相关的最近几次交互。长期记忆使用向量数据库存储重要的历史决策、结果和用户偏好在需要时通过检索增强生成RAG的方式召回。记忆摘要在对话轮次过多时让 LLM 自动对之前的对话进行摘要用摘要替代冗长的原始历史放入上下文。4. 进阶方向从单兵作战到团队协作Multi-Agent当单个 Agent 无法处理过于复杂的任务时我们就需要多智能体系统Multi-Agent System。这就像从“一个全能助手”升级为“一个专业团队”。角色化 Agent你可以创建“规划专家”、“信息搜集员”、“文案撰写员”、“审核员”等具有不同系统提示词和工具集的 Agent。协同工作流使用 LangGraph 或CrewAI、AutoGen等多 Agent 框架来编排它们。例如规划专家制定大纲信息搜集员并行获取天气和地点数据文案撰写员整合成文审核员检查合理性和格式。通信与协商Agent 之间可以通过共享的工作区黑板模型或直接的消息传递来交换信息和协调行动。构建多 Agent 系统的复杂度呈指数级增长但它能解决的单点问题也更多。它不仅是技术的叠加更是对复杂业务流程的数字化建模。5. 写在最后Agent 开发的本质是“工作流工程”通过这次从认知到实操的旅程你应该能感受到开发一个 Agent 远不止是调通一个 API。它更像是在设计一个数字员工的工作流程。明确职责系统提示词它是什么角色目标是什么授予权限工具集它能操作哪些系统权限边界在哪里设计流程图/工作流它接到任务后先做什么后做什么遇到问题怎么办建立考核评估与反思如何判断它做得好不好如何让它持续改进因此学习 Agent 开发最好的起点不是钻研最前沿的论文而是回到你手头最重复、最枯燥的工作流程。试着用 Agent 的思维去拆解它哪些步骤是信息获取哪些是决策判断哪些是执行操作然后用今天学到的组件规划、工具、记忆去尝试自动化它。从一个小而具体的任务开始亲手感受 Agent 如何“思考”和“行动”你才能真正理解这股正在重塑人机协作方式的技术浪潮究竟意味着什么。它不是一个万能魔法而是一套强大的、将人类意图转化为机器自主行动的工程学工具箱。