ツールとしてのワークフロー
AIアプリケーションを構築する際、互いの出力に依存する複数のステップを調整する必要がよくあります。この例では、ワークフローから天気データを取得するAIワークフローの作成方法を示します。また、エージェントからワークフローの一時停止と再開を処理する方法も実演します。
ワークフロー定義
import { Mastra } from "@mastra/core";
import { Agent } from "@mastra/core/agent";
import { createStep, createWorkflow } from "@mastra/core/workflows";
import { createTool } from '@mastra/core/tools';
import { z } from "zod";
import { openai } from "@ai-sdk/openai";
const forecastSchema = z.object({
date: z.string(),
maxTemp: z.number(),
minTemp: z.number(),
precipitationChance: z.number(),
condition: z.string(),
location: z.string(),
});
function getWeatherCondition(code: number): string {
const conditions: Record<number, string> = {
0: 'Clear sky',
1: 'Mainly clear',
2: 'Partly cloudy',
3: 'Overcast',
45: 'Foggy',
48: 'Depositing rime fog',
51: 'Light drizzle',
53: 'Moderate drizzle',
55: 'Dense drizzle',
61: 'Slight rain',
63: 'Moderate rain',
65: 'Heavy rain',
71: 'Slight snow fall',
73: 'Moderate snow fall',
75: 'Heavy snow fall',
95: 'Thunderstorm',
};
return conditions[code] || 'Unknown';
}
const fetchWeatherWithSuspend = createStep({
id: 'fetch-weather',
description: 'Fetches weather forecast for a given city',
inputSchema: z.object({}),
resumeSchema: z.object({
city: z.string().describe('The city to get the weather for'),
}),
outputSchema: forecastSchema,
execute: async ({ resumeData, suspend }) => {
if (!resumeData) {
suspend({
message: 'Please enter the city to get the weather for',
});
return {};
}
const geocodingUrl = `https://geocoding-api.open-meteo.com/v1/search?name=${encodeURIComponent(resumeData.city)}&count=1`;
const geocodingResponse = await fetch(geocodingUrl);
const geocodingData = (await geocodingResponse.json()) as {
results: { latitude: number; longitude: number; name: string }[];
};
if (!geocodingData.results?.[0]) {
throw new Error(`Location '${resumeData.city}' not found`);
}
const { latitude, longitude, name } = geocodingData.results[0];
const weatherUrl = `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}¤t=precipitation,weathercode&timezone=auto,&hourly=precipitation_probability,temperature_2m`;
const response = await fetch(weatherUrl);
const data = (await response.json()) as {
current: {
time: string;
precipitation: number;
weathercode: number;
};
hourly: {
precipitation_probability: number[];
temperature_2m: number[];
};
};
const forecast = {
date: new Date().toISOString(),
maxTemp: Math.max(...data.hourly.temperature_2m),
minTemp: Math.min(...data.hourly.temperature_2m),
condition: getWeatherCondition(data.current.weathercode),
precipitationChance: data.hourly.precipitation_probability.reduce((acc, curr) => Math.max(acc, curr), 0),
location: resumeData.city,
};
return forecast;
},
});
const weatherWorkflowWithSuspend = createWorkflow({
id: 'weather-workflow-with-suspend',
inputSchema: z.object({}),
outputSchema: forecastSchema,
})
.then(fetchWeatherWithSuspend)
.commit();
ツール定義
export const startWeatherTool = createTool({
id: 'start-weather-tool',
description: 'Start the weather tool',
inputSchema: z.object({}),
outputSchema: z.object({
runId: z.string(),
}),
execute: async ({ context }) => {
const workflow = mastra.getWorkflow('weatherWorkflowWithSuspend');
const run = await workflow.createRunAsync();
await run.start({
inputData: {},
});
return {
runId: run.runId,
};
},
});
export const resumeWeatherTool = createTool({
id: 'resume-weather-tool',
description: 'Resume the weather tool',
inputSchema: z.object({
runId: z.string(),
city: z.string().describe('City name'),
}),
outputSchema: forecastSchema,
execute: async ({ context }) => {
const workflow = mastra.getWorkflow('weatherWorkflowWithSuspend');
const run = await workflow.createRunAsync({
runId: context.runId,
});
const result = await run.resume({
step: 'fetch-weather',
resumeData: {
city: context.city,
},
});
return result.result;
},
});
エージェントの定義
export const weatherAgentWithWorkflow = new Agent({
name: 'Weather Agent with Workflow',
instructions: `あなたは正確な天気情報を提供する親切な天気アシスタントです。
あなたの主な機能は、特定の場所の天気詳細をユーザーが取得するのを支援することです。応答する際は:
- 場所が提供されていない場合は、必ず場所を尋ねてください
- 場所名が英語でない場合は、翻訳してください
- 複数の部分を持つ場所(例:「New York, NY」)を指定する場合は、最も関連性の高い部分(例:「New York」)を使用してください
- 湿度、風の状況、降水量などの関連する詳細を含めてください
- 応答は簡潔でありながら情報豊富に保ってください
startWeatherToolを使用して天気ワークフローを開始してください。これによりワークフローが開始され、一時停止してrunIdが返されます。
resumeWeatherToolを使用して天気ワークフローを再開してください。これはstartWeatherToolから返されたrunIdとユーザーが入力した都市を受け取ります。ワークフローを再開し、結果を返します。
結果は、その都市の天気予報になります。`,
model: openai('gpt-4o'),
tools: { startWeatherTool, resumeWeatherTool },
});
エージェントの実行
const mastra = new Mastra({
agents: { weatherAgentWithWorkflow },
workflows: { weatherWorkflowWithSuspend },
});
const agent = mastra.getAgent('weatherAgentWithWorkflow');
const result = await agent.generate([
{
role: 'user',
content: 'London',
},
]);
console.log(result);
GitHubで例を見る