1. 本章目标 #
上一章讲清了 Agent = Model + Harness。本章目标:
跑通一个可调用工具的天气助手,并看懂它的执行轨迹。
学完你应能:
- 用
create_agent创建并调用 Agent - 看懂返回的消息轨迹(为何会调工具)
- 扩展成多工具助手
- 使用流式输出,并可选打开 LangSmith 追踪
参考文档:
2. 第一个 Agent:天气助手 #
核心路径是:定义工具 → create_agent → invoke。
2.1. 1.weather_agent.py #
# 创建智能体的工厂函数
from langchain.agents import create_agent
# 从 .env 加载密钥等环境变量
from dotenv import load_dotenv
load_dotenv(override=True)
def get_weather(city: str) -> str:
"""获取指定城市的天气信息。"""
return f"{city} 今天晴,气温 25°C。"
# model:provider:model 字符串;tools:普通函数也可;system_prompt:人设与约束
agent = create_agent(
model="deepseek:deepseek-v4-flash",
tools=[get_weather],
system_prompt="你是一个简洁、可靠的中文助手。需要天气信息时请调用工具,不要编造。",
)
# 输入是状态字典;messages 是对话消息列表
result = agent.invoke(
{"messages": [{"role": "user", "content": "北京今天天气怎么样?"}]}
)
# 最后一条通常是助手的最终回复
print(result["messages"][-1].content)预期类似:
北京今天晴,气温 25°C。2.2. 这段代码在做什么 #
用户:「北京今天天气怎么样?」
│
▼
create_agent 循环
│
├─ 模型判断:需要天气 → 调用 get_weather(city="北京")
├─ 工具返回:"北京 今天晴,气温 25°C。"
├─ 模型根据工具结果组织自然语言回答
└─ 结束循环,返回完整 messages要点回顾:
| 参数 | 含义 |
|---|---|
model |
"deepseek:deepseek-v4-flash" 或已初始化的模型实例 |
tools |
可调用对象列表;docstring + 类型注解帮助模型选对工具 |
system_prompt |
系统行为设定 |
invoke({...}) |
同步执行一轮(内部可能多步工具调用) |
3. 看懂返回的消息轨迹 #
只打印最后一句不够。调试时要看清中间发生了什么。
3.1. inspect_messages.py #
from langchain.agents import create_agent
from dotenv import load_dotenv
load_dotenv(override=True)
def get_weather(city: str) -> str:
"""获取指定城市的天气信息。"""
return f"{city} 今天晴,气温 25°C。"
agent = create_agent(
model="deepseek:deepseek-v4-flash",
tools=[get_weather],
system_prompt="你是一个简洁、可靠的中文助手。需要天气信息时请调用工具。",
)
result = agent.invoke(
{"messages": [{"role": "user", "content": "上海天气如何?"}]}
)
# 遍历完整消息轨迹,观察角色与是否含 tool_calls
for i, msg in enumerate(result["messages"]):
# 消息类型名:HumanMessage / AIMessage / ToolMessage 等
msg_type = type(msg).__name__
print(f"\n===== [{i}] {msg_type} =====")
# 文本内容(工具结果、最终回答等多在这里)
content = getattr(msg, "content", None)
if content:
print("content:", content)
# 模型发起的工具调用请求(若有)
tool_calls = getattr(msg, "tool_calls", None)
if tool_calls:
print("tool_calls:", tool_calls)典型轨迹(简化):
[0] HumanMessage → 用户问题
[1] AIMessage → 带 tool_calls:get_weather(city="上海")
[2] ToolMessage → 工具返回字符串
[3] AIMessage → 最终自然语言回答这就是 harness 帮你自动完成的「模型 ↔ 工具」循环。第 4 章会系统讲消息类型。
4. 多工具助手 #
真实项目中很少只有一个工具。下面加「天气 + 加法」,看模型如何按需选择。
4.1. multi_tools_agent.py #
from langchain.agents import create_agent
from langchain.tools import tool
from dotenv import load_dotenv
load_dotenv(override=True)
# 使用 @tool 装饰器,把下方函数注册为可供 Agent 调用的工具
@tool
# 定义获取天气的工具函数:参数 city 为城市名,返回值为字符串
def get_weather(city: str) -> str:
# 工具说明(docstring),会作为工具描述提供给模型
"""获取指定城市的天气信息。"""
return f"{city} 今天晴,气温 25°C。"
# 使用 @tool 装饰器,把下方函数注册为可供 Agent 调用的工具
@tool
# 定义整数加法工具:接收两个整数 a、b,返回它们的和
def add(a: int, b: int) -> int:
# 工具说明(docstring),会作为工具描述提供给模型
"""计算两个整数之和。"""
# 返回 a 与 b 的加法结果
return a + b
agent = create_agent(
model="deepseek:deepseek-v4-flash",
tools=[get_weather, add],
system_prompt=(
"你是办公助手。"
"查天气时调用 get_weather;"
"做整数加法时调用 add,不要心算。"
),
)
# 一次提问里同时触发两类工具
result = agent.invoke(
{
"messages": [
{
"role": "user",
"content": "北京天气怎么样?另外帮我算 128 + 256。",
}
]
}
)
print(result["messages"][-1].content)@tool 会把函数名、参数 schema、docstring 整理成模型可见的工具描述。
5. 流式输出 #
长回答时,用流式边生成边打印体验更好。Agent 也支持 stream。
5.1. stream_agent.py #
from langchain.agents import create_agent
from dotenv import load_dotenv
load_dotenv(override=True)
def get_weather(city: str) -> str:
"""获取指定城市的天气信息。"""
return f"{city} 今天晴,气温 25°C。"
agent = create_agent(
model="deepseek:deepseek-v4-flash",
tools=[get_weather],
system_prompt="你是一个简洁的中文助手。",
)
# stream_mode="updates":按节点更新推送;也可用 "values" 看完整状态快照
for chunk in agent.stream(
{"messages": [{"role": "user", "content": "深圳今天天气?"}]},
stream_mode="updates",
):
print(chunk)第一次看 updates 可能较碎:会看到模型节点、工具节点逐步产出。
若只想快速拿到最终文本,继续用 invoke 即可。
6. 常见问题排查 #
| 现象 | 可能原因 | 处理 |
|---|---|---|
| 模型直接编造天气、不调工具 | 系统提示太弱,或 docstring 不清晰 | 在 system_prompt 明确「必须调用工具」;补全工具说明 |
AuthenticationError / 401 |
密钥无效或过期 | 检查 .env 中的 DEEPSEEK_API_KEY |
create_agent 导入失败 |
LangChain 版本过旧 | pip install -U langchain |
| LangSmith 无数据 | 未开启追踪或 key 错误 | 确认 LANGSMITH_TRACING=true 与 API Key |
7. 练习 #
- 改城市:把用户问题换成「广州和杭州天气分别怎么样?」观察是否多次调用
get_weather。 - 加工具:再写一个
get_time(city: str) -> str(可返回固定字符串),让助手能回答「现在几点」。 - 收紧人设:把
system_prompt改成「只回答天气;其他问题礼貌拒绝」,测一句无关问题。 - 对照轨迹:用
inspect_messages.py打印完整 messages,标出哪一步是 tool_calls。
9. 本章小结 #
- 最小闭环:定义工具 →
create_agent→invoke。 - 工具可以是普通函数;写清 类型注解 + docstring。
- 调试看 完整 messages,不要只看最后一句。
- 多工具时靠系统提示 + 工具描述引导模型选择。
- 尽早打开 LangSmith,为后面复杂 Agent / RAG 打底。
下一章:Chat Models 聊天模型——统一用 init_chat_model 切换供应商、调参数、做流式输出。