Skip to content

案例:天气与旅行 Agent

目标

这个案例用两个小 Agent 展示如何从单一工具调用,扩展到带记忆和工作流的业务助手:

角色解决的问题核心能力
weatherAgent查询指定城市天气调用 weatherTool,把外部 API 结果转成中文回答
tripAgent根据天气规划旅行调用 weatherTool,结合 Memory 保留偏好
tripPlanningWorkflow生成可复现行程解析目的地、查询天气、生成分日计划

它们不是 Study Agent 主线的一部分,而是用来演示“一个工具如何被多个 Agent 和 Workflow 复用”。

文件位置

文件作用
apps/study-agent/src/mastra/tools/weather-tool.ts封装天气查询工具
apps/study-agent/src/mastra/agents/weather-agent.ts最小天气查询 Agent
apps/study-agent/src/mastra/agents/trip-agent.ts带 Memory 的旅行规划 Agent
apps/study-agent/src/mastra/workflows/trip-planning-workflow.ts确定性旅行规划 Workflow
apps/study-agent/src/mastra/index.ts注册 agents、tools、workflows

Weather Tool 的边界

weatherTool 是最底层能力。它只做三件事:

  1. 接收城市名。
  2. 调用 wttr.in 获取天气 JSON。
  3. 返回稳定结构:当前天气和未来三天预报。
ts
inputSchema: z.object({
  city: z.string().describe('要查询天气的城市名称,例如:北京、上海、Tokyo、London'),
})

输出结构保持稳定,方便 Agent、Workflow 或未来前端复用:

  • current.temperature
  • current.weather
  • current.humidity
  • current.windSpeed
  • forecast[].date
  • forecast[].minTemp
  • forecast[].maxTemp
  • forecast[].weather

设计重点:Tool 不负责写旅行建议,也不负责猜用户偏好。Tool 只负责“查天气”这个可验证动作。

Weather Agent 的设计

weatherAgent 是最小的工具调用案例。

mermaid
flowchart LR
  User[用户输入城市或天气问题] --> Agent[weatherAgent]
  Agent --> Tool[weatherTool]
  Tool --> API[wttr.in]
  API --> Tool
  Tool --> Agent
  Agent --> Reply[中文天气摘要]

它的 instructions 重点是让模型知道什么时候调用工具:

  • 用户问城市天气时,调用 weather 工具。
  • 用户只输入城市名时,也直接查询。
  • 工具失败时,提示用户检查城市名称。

这个 Agent 适合讲解 Tool description 和 Agent instructions 的关系:Tool 描述负责说明工具能力,Agent instructions 负责说明业务场景和回答格式。

Trip Agent 的设计

tripAgent 复用了同一个 weatherTool,但目标变成“旅行建议”。

mermaid
flowchart TB
  User[用户提出旅行需求] --> Agent[tripAgent]
  Agent --> Memory[Memory: 最近消息]
  Agent --> Weather[weatherTool]
  Weather --> Agent
  Agent --> Reply[天气总结 + 活动建议 + 追问]

它比 weatherAgent 多了两个教学点:

说明
复用工具同一个 weatherTool 可以服务不同 Agent,不需要复制 API 调用代码
使用 MemorylastMessages: 20 让 Agent 能在同一对话里引用用户偏好

例如用户先说“我喜欢轻松一点,不想赶景点”,后面再问“那杭州三天怎么安排”,tripAgent 应该把“轻松”作为偏好使用。

Trip Planning Workflow 的设计

如果要稳定地产出行程表,Workflow 比 Agent 自由发挥更合适。

mermaid
flowchart LR
  A[userMessage] --> B[parse-destination]
  B --> C[fetch-weather]
  C --> D[build-itinerary]
  D --> E[plan]

Step 1:解析目的地

parse-destination 从用户文本中提取:

  • city:目的地,默认北京。
  • days:天数,限制在 1 到 7 天。
  • style:旅行风格,目前支持 悠闲美食文化

这是一个教学版解析器,用正则和关键词完成,不依赖模型。

Step 2:查询天气

fetch-weather 根据目的地调用天气服务,并把结果拼进 workflow 数据流。

这一层和 weatherTool 逻辑相似,但放在 Workflow step 中,方便展示“工作流也能直接执行外部查询”。真实项目里可以进一步抽成共享函数,避免重复 API 逻辑。

Step 3:生成行程

build-itinerary 根据 style 选择活动池,并按每天的天气生成:

  • morning
  • afternoon
  • evening
  • weatherNote

如果天气描述包含“雨”,上午和下午会加室内备选提示。

Agent 和 Workflow 怎么选

场景优先选择原因
用户只问“北京天气怎么样”weatherAgent开放式问答 + 单次工具调用
用户说“我喜欢美食,帮我安排旅行”tripAgent需要结合偏好和上下文
产品需要固定 JSON 行程表tripPlanningWorkflow步骤稳定、输出可验证
要在前端展示每一步进度tripPlanningWorkflowstep 边界清楚,方便调试

简单判断:如果流程顺序必须稳定,用 Workflow;如果用户问题开放、需要自然语言协调,用 Agent。

在 Studio 中验证

启动 Studio:

bash
npm run final:dev

验证 Weather Agent

weatherAgent 输入:

text
北京今天天气怎么样?

检查:

  • 是否调用 weather 工具。
  • 回答是否包含当前温度、天气、湿度或风速。
  • 工具失败时是否给出清楚错误说明。

验证 Trip Agent

tripAgent 连续输入:

text
我喜欢轻松一点的旅行,不想赶景点。
text
想去杭州玩 3 天,帮我安排一下。

检查:

  • 是否调用 weather 工具。
  • 是否先总结天气,再给行程建议。
  • 第二轮是否能引用“轻松一点”的偏好。

验证 Trip Planning Workflow

运行 tripPlanningWorkflow,输入:

json
{
  "userMessage": "想去杭州玩3天,喜欢吃"
}

检查输出:

  • city 应为 杭州
  • days 应为 3
  • style 应为 美食
  • plan 应包含每天的上午、下午、晚上安排。

常见错误

错误影响修正方向
Agent instructions 没说何时调用工具模型可能只聊天不查天气明确“天气问题必须调用 weather 工具”
Tool 输出字段频繁变化Agent、Workflow、前端都难以复用outputSchema 固定字段
把旅行建议写进 weatherTool工具职责变重,复用性下降Tool 只查天气,建议放 Agent 或 Workflow
让 Agent 自由生成固定行程表输出不稳定,难评估用 Workflow 固定步骤和 schema
依赖 Memory 存权限或套餐容易串话或污染上下文权限、租户、套餐放 RequestContext

给 AI 的提示词

text
请基于现有 weatherTool 设计一个新的户外活动 Agent。
要求:
- 不新增依赖。
- 复用 weatherTool,不复制天气 API 请求逻辑。
- instructions 说明什么情况下调用工具。
- 如果需要固定输出结构,优先用 Workflow。
- 最后给出 Studio 中的验收问题。

小结

这个案例展示了三层设计:

  1. Tool 封装可验证动作。
  2. Agent 负责开放式用户协作和自然语言回答。
  3. Workflow 负责稳定流程和结构化输出。

理解这三层后,再回到 Study Agent,就更容易判断哪些能力应该写成工具,哪些逻辑应该放进 Agent instructions,哪些流程应该升级为 Workflow。