创建时间: 2026-08-12最后更新: 2026-08-12

1. 子 Agent

上一篇的天气子图已经会重试、校验和降级,但每条路线仍由开发者提前写死。给它相同状态,它总会走相同的条件边。它不会理解父流程交给它的任务,也不会决定这次应该调用哪个工具,更不会用自然语言解释领域结论。

我们只需要在子图基础之上增加独立目标、边界和模型选择,就可以让子图变成一个可以委派目标的天气 Agent 专家。

能力子图子 Agent
按状态执行固定路线有,可以把子图当工具
理解父 Agent 委派的目标没有有独立系统提示词
自己决定是否调用工具没有由模型进行工具选择
隔离领域上下文只隔离流程字段隔离消息、工具结果和模型调用
返回领域自然语言答案需要父图格式化自己生成后返回父 Agent

所以不能仅把 weatherSubgraph 重命名为 weatherAgent。真正的封装需要新的调用边界。

2. 三层封装

天气子 Agent 由三层组成。最内层仍是上一篇的 LangGraph 子图;中间层用 LangChain tool 把子图变成一个带名称、说明和 Zod 输入契约的工具;最外层用 createAgent 创建拥有独立目标的天气专家。

正在加载图示...

这三个边界不能混在一起:

  • StateGraph 管理可靠执行,擅长循环、分支、重试和恢复。
  • tool 定义外部可调用契约,隐藏内部状态并限制输入输出。
  • createAgent 管理目标、消息和工具选择,负责把结构化天气转成领域答案。

3. 工具契约

天气工具只接收一条完整问题。工具内部从头运行天气子图,再返回地点、天气、温度、降雨概率和来源。providerAttempts、坐标、主源错误等内部字段不会暴露给父 Agent。

weather-tool.ts
01
const weatherTool = tool(
02
async ({ question }) => {
03
const result = await runPackingWeather(question)
04
return JSON.stringify({
05
location: `${result.city}${result.district}`,
06
condition: result.condition,
07
temperature: result.temperature,
08
rainProbability: result.rainProbability,
09
source: result.provider,
10
})
11
},
12
{
13
name: 'query_reliable_weather',
14
description: '查询明天出门地点的可信天气',
15
schema: z.object({ question: z.string() }),
16
},
17
)

工具返回 JSON 字符串不是为了让用户阅读,而是给模型一份稳定、低歧义的观察结果。父 Agent 只会拿到天气 Agent 最终生成的领域回答,不会直接接触这份工具输出。

4. 独立目标和边界

createAgent 把模型、工具和系统提示词组合为一个可调用 Agent。提示词明确要求先查询可信天气,并禁止它推测个人习惯和陪同人。这种「不能做什么」与「要做什么」同样重要。

weather-agent.ts
01
const weatherAgent = createAgent({
02
name: 'weather_specialist',
03
description: '负责定位、天气查询和天气相关出门建议',
04
model,
05
tools: [weatherTool],
06
systemPrompt: [
07
'你是天气领域子 Agent。',
08
'必须先调用 query_reliable_weather。',
09
'只回答天气相关建议,不推测习惯或陪同人。',
10
].join('\n'),
11
})

本案例还为 DeepSeek 显式关闭思考模式。原因不是天气问题不需要思考,而是工具型 Agent 依赖 tool_choice,部分 DeepSeek 思考模式不接受这种参数组合。关闭思考模式后,模型仍可进行工具选择,但不会触发 Thinking mode does not support this tool_choice

订阅后可阅读剩余内容
AI 电子伴侣企业级项目实战
已发布239计划发布120目标已完成199%