diff --git a/frameworks/mastra/using-a-tool/.cursorrules/agent.mdc b/frameworks/mastra/using-a-tool/.cursorrules/agent.mdc new file mode 100644 index 00000000..5df70422 --- /dev/null +++ b/frameworks/mastra/using-a-tool/.cursorrules/agent.mdc @@ -0,0 +1,36 @@ +--- +description: Guidelines for writing Agentuity AI Agents in TypeScript +globs: "**/src/agents/**/index.ts" +alwaysApply: true +--- + +# AI Agent File + +- Prefer using the `agentuity agent create` command to create a new Agent +- Prefer loading types from the node modules package `@agentuity/sdk` in the node_modules folder +- The file should export a default function +- Prefer naming the default function Agent or the name of the Agent based on the context of the Agent description +- All code should be in Typescript format +- Use the provided logger from the `AgentContext` interface such as `ctx.logger.info("my message: %s", "hello")` + +## Example Agent File + +```typescript +import type { AgentRequest, AgentResponse, AgentContext } from "@agentuity/sdk"; + +export default async function Agent(req: AgentRequest, resp: AgentResponse, ctx: AgentContext) { + return resp.json({"hello":"world"}); +} +``` + +### AgentRequest + +The AgentRequest interface provides a set of helper methods and public variables which can be used for working with data has been passed to the Agent. + +### AgentResponse + +The AgentResponse interface provides a set of helper methods for responding with different data formats from the Agent. + +### AgentContext + +The AgentContext has information specific to the incoming Agent request and a set of helper methods for accessing AI services like KeyValue storage and Vector storage. diff --git a/frameworks/mastra/using-a-tool/.cursorrules/agentuity.mdc b/frameworks/mastra/using-a-tool/.cursorrules/agentuity.mdc new file mode 100644 index 00000000..0e32105c --- /dev/null +++ b/frameworks/mastra/using-a-tool/.cursorrules/agentuity.mdc @@ -0,0 +1,9 @@ +--- +description: Guidelines for the Agentuity AI Configuration file +globs: "agentuity.yaml" +alwaysApply: true +--- + +# Agentuity Configuration File + +This file is used by agentuity to configure the AI Agent project. You should NOT suggest edits to this file. diff --git a/frameworks/mastra/using-a-tool/.gitignore b/frameworks/mastra/using-a-tool/.gitignore new file mode 100644 index 00000000..4f827ed8 --- /dev/null +++ b/frameworks/mastra/using-a-tool/.gitignore @@ -0,0 +1,9 @@ +node_modules/ +.env +.env.local +.env.development +.env.production +.agentuity/ +dist/ +*.log +.DS_Store diff --git a/frameworks/mastra/using-a-tool/README.md b/frameworks/mastra/using-a-tool/README.md new file mode 100644 index 00000000..d1481664 --- /dev/null +++ b/frameworks/mastra/using-a-tool/README.md @@ -0,0 +1,74 @@ +# Mastra Using a Tool - Agentuity Example + +This example demonstrates how to wrap a Mastra agent that uses tools within the Agentuity framework. It preserves the original Mastra framework functionality while providing Agentuity SDK interfaces. + +## Overview + +This agent uses the Mastra framework to create a London weather assistant that has access to historical weather data for the current year. The agent can answer questions about weather patterns, temperature records, rainfall, and other meteorological data. + +## Original Mastra Example + +This example is based on the [Mastra "Using a Tool" documentation](https://mastra.ai/en/examples/agents/using-a-tool), which demonstrates how to add tools to Mastra agents. + +## Features + +- **Historical Weather Data**: Access to year-to-date weather information for London +- **Tool Integration**: Uses Mastra's `createTool` function to define the weather data tool +- **Agentuity Wrapper**: Wrapped with Agentuity SDK for seamless integration +- **Error Handling**: Proper error logging using Agentuity's context logger + +## Project Structure + +``` +src/ +├── agents/ +│ └── london-weather-agent/ +│ └── index.ts # Main agent implementation +└── tools/ + └── london-weather-tool.ts # Weather data tool definition +``` + +## Tool Functionality + +The `londonWeatherTool` provides: +- Daily temperature maximums and minimums +- Precipitation/rainfall data +- Wind speed measurements +- Snowfall amounts +- Data from January 1st of current year to present + +## Usage Examples + +- "How many times has it rained this year?" +- "What was the highest temperature recorded this year?" +- "Show me the weather trends for the past month" +- "What's the average rainfall so far this year?" + +## Setup + +1. Install dependencies: + ```bash + npm install + ``` + +2. Start development server: + ```bash + agentuity dev + ``` + +3. Test the agent in the Agentuity Console + +## Dependencies + +- **@mastra/core**: Core Mastra framework for agent and tool creation +- **@ai-sdk/openai**: OpenAI integration for the language model +- **@agentuity/sdk**: Agentuity SDK for request/response handling +- **zod**: Schema validation for tool inputs/outputs + +## Implementation Notes + +This example follows the Agentuity wrapper pattern: +- Preserves all original Mastra framework imports and functionality +- Uses Agentuity SDK types for request/response handling +- Implements proper error handling with context logging +- Provides a welcome function with example prompts diff --git a/frameworks/mastra/using-a-tool/agentuity.yaml b/frameworks/mastra/using-a-tool/agentuity.yaml new file mode 100644 index 00000000..fa09857c --- /dev/null +++ b/frameworks/mastra/using-a-tool/agentuity.yaml @@ -0,0 +1,17 @@ +name: mastra-using-a-tool +description: Mastra agent with London weather tool wrapped in Agentuity SDK +version: 0.0.1 +runtime: nodejs + +agents: + london-weather-agent: + name: London Weather Agent + description: Provides historical weather data for London using Mastra tools + path: src/agents/london-weather-agent + +development: + port: 3000 + +deployment: + memory: 512 + timeout: 30 diff --git a/frameworks/mastra/using-a-tool/index.ts b/frameworks/mastra/using-a-tool/index.ts new file mode 100644 index 00000000..47bcb99d --- /dev/null +++ b/frameworks/mastra/using-a-tool/index.ts @@ -0,0 +1,3 @@ +import { serve } from "@agentuity/sdk"; + +serve(); diff --git a/frameworks/mastra/using-a-tool/package.json b/frameworks/mastra/using-a-tool/package.json new file mode 100644 index 00000000..6344465d --- /dev/null +++ b/frameworks/mastra/using-a-tool/package.json @@ -0,0 +1,28 @@ +{ + "name": "mastra-using-a-tool", + "description": "Mastra agent with London weather tool wrapped in Agentuity SDK", + "version": "0.0.1", + "main": "index.js", + "type": "module", + "scripts": { + "build": "agentuity build", + "prestart": "agentuity bundle", + "start": "node --env-file .env .agentuity/index.js", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": ["agentuity", "agent", "ai", "ai agent", "mastra", "weather"], + "author": "", + "license": "ISC", + "devDependencies": { + "@types/node": "^22.13.9", + "mastra": "^0.2.9-alpha.4", + "typescript": "^5.8.2" + }, + "dependencies": { + "@agentuity/sdk": "^0.0.73", + "@ai-sdk/openai": "^1.2.1", + "@mastra/core": "^0.5.0-alpha.4", + "ai": "^4.1.53", + "zod": "^3.24.2" + } +} diff --git a/frameworks/mastra/using-a-tool/src/agents/london-weather-agent/index.ts b/frameworks/mastra/using-a-tool/src/agents/london-weather-agent/index.ts new file mode 100644 index 00000000..6635975f --- /dev/null +++ b/frameworks/mastra/using-a-tool/src/agents/london-weather-agent/index.ts @@ -0,0 +1,53 @@ +import type { AgentRequest, AgentResponse, AgentContext } from "@agentuity/sdk"; +import { openai } from "@ai-sdk/openai"; +import { Agent } from "@mastra/core"; +import { londonWeatherTool } from "../../tools/london-weather-tool"; + +export function welcome() { + return { + message: "I'm a London weather assistant with access to historical weather data for the current year. I can help you analyze weather patterns, trends, and specific data points.", + prompts: [ + "How many times has it rained this year?", + "What was the highest temperature recorded this year?", + "Show me the weather trends for the past month", + "What's the average rainfall so far this year?", + ], + }; +} + +export default async function Agent( + req: AgentRequest, + resp: AgentResponse, + ctx: AgentContext, +) { + try { + const prompt = req.text() ?? "What is the weather data for London this year?"; + + const londonWeatherAgent = new Agent({ + name: "london-weather-agent", + description: "Provides historical information about London weather", + instructions: `You are a helpful assistant with access to historical weather data for London. + +The data is provided for the current calendar year from January 1st up to today. When responding: +- Use the londonWeatherTool to fetch current year's weather data for London +- The data includes daily temperature maximums and minimums, rainfall, wind speed, and snowfall +- Answer the user's question using that data +- Keep responses concise, factual, and informative +- If the question cannot be answered with available data, say so clearly`, + model: openai("gpt-4o"), + tools: { londonWeatherTool }, + }); + + const result = await londonWeatherAgent.generate(prompt); + return resp.text(result.text); + } catch (error) { + ctx.logger.error( + "Error generating response: %s", + error instanceof Error ? error.message : String(error), + ); + + return resp.text( + "I'm sorry, I encountered an error while processing your request.", + ); + } +} diff --git a/frameworks/mastra/using-a-tool/src/tools/london-weather-tool.ts b/frameworks/mastra/using-a-tool/src/tools/london-weather-tool.ts new file mode 100644 index 00000000..795ee274 --- /dev/null +++ b/frameworks/mastra/using-a-tool/src/tools/london-weather-tool.ts @@ -0,0 +1,34 @@ +import { createTool } from "@mastra/core"; +import { z } from "zod"; + +export const londonWeatherTool = createTool({ + id: "london-weather-tool", + description: "Returns year-to-date historical weather data for London", + outputSchema: z.object({ + date: z.array(z.string()), + temp_max: z.array(z.number()), + temp_min: z.array(z.number()), + rainfall: z.array(z.number()), + windspeed: z.array(z.number()), + snowfall: z.array(z.number()), + }), + execute: async () => { + const startDate = new Date().getFullYear() + "-01-01"; + const endDate = new Date().toISOString().split("T")[0]; + + const response = await fetch( + `https://archive-api.open-meteo.com/v1/archive?latitude=51.5072&longitude=-0.1276&start_date=${startDate}&end_date=${endDate}&daily=temperature_2m_max,temperature_2m_min,precipitation_sum,wind_speed_10m_max,snowfall_sum`, + ); + + const { daily } = await response.json(); + + return { + date: daily.time, + temp_max: daily.temperature_2m_max, + temp_min: daily.temperature_2m_min, + rainfall: daily.precipitation_sum, + windspeed: daily.wind_speed_10m_max, + snowfall: daily.snowfall_sum, + }; + }, +}); diff --git a/frameworks/mastra/using-a-tool/tsconfig.json b/frameworks/mastra/using-a-tool/tsconfig.json new file mode 100644 index 00000000..265b4ded --- /dev/null +++ b/frameworks/mastra/using-a-tool/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "target": "ES2022", + "lib": ["ES2022"], + "module": "ESNext", + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "noEmit": true, + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "skipLibCheck": true, + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "isolatedModules": true, + "verbatimModuleSyntax": true + }, + "include": ["src/**/*", "index.ts"], + "exclude": ["node_modules", "dist"] +}