This guide shows you how to integrate and use Arcade tools within a Mastra agent.
Prerequisites
- Obtain an Arcade API key
- Basic familiarity with TypeScript and Mastra concepts
Create a Mastra project
Start by creating a new Mastra project using the official CLI:
# Create a new Mastra project
npx create-mastra@latest my-arcade-agent
# Navigate to the project
cd my-arcade-agent
For more details on setting up a Mastra project, refer to the Mastra documentation.
Install required packages
Install the necessary packages for working with Arcade:
npm install @arcadeai/arcadejs @dmitryrechkin/json-schema-to-zod
@dmitryrechkin/json-schema-to-zod
package converts Arcade’s OpenAI-compatible JSON Schema tool definitions to Zod schemas used by Mastra, enabling type-safe tool definitions in your application.Configure API keys
Set up your environment with the required API keys:
// Set your API keys in your environment variables or .env file
process.env.ARCADE_API_KEY = "your_arcade_api_key";
process.env.ANTHROPIC_API_KEY = "your_anthropic_api_key"; // or another supported model provider
Create the Arcade tool adapter
Create a utility function to fetch Arcade tools and convert them into the format Mastra expects. This involves fetching tools, validating their schema, converting the input schema to Zod, and defining an execute
function that calls the Arcade API.
import { Agent } from "@mastra/core/agent";
import { anthropic } from "@ai-sdk/anthropic";
import { Arcade } from "@arcadeai/arcadejs";
import { createTool } from "@mastra/core/tools";
import { z } from "zod";
// Utility to convert JSON Schema to Zod schemas
import { JSONSchemaToZod } from "@dmitryrechkin/json-schema-to-zod";
// Initialize the Arcade client
const arcade = new Arcade();
/**
* Schema to validate Arcade tool definitions
*/
const arcadeToolMinimumSchema = z.object({
function: z.object({
name: z.string(),
parameters: z.record(z.any()),
description: z.string(),
}),
});
/**
* Fetches Arcade tools and converts them to Mastra tools
*/
async function getArcadeMastraTools({
toolkit,
user_id,
}: {
toolkit?: string;
user_id: string;
}) {
// Fetch tools from Arcade in OpenAI format
const tools = await arcade.tools.formatted.list({
...(toolkit && { toolkit }),
format: "openai",
});
// Convert each valid tool into a Mastra tool
return tools.items.reduce(
(acc: Record<string, ReturnType<typeof createTool>>, item) => {
const parsedItem = arcadeToolMinimumSchema.safeParse(item);
if (parsedItem.success) {
const { name, description, parameters } = parsedItem.data.function;
acc[name] = createTool({
id: name,
description,
// Convert JSON Schema to Zod schema
inputSchema: JSONSchemaToZod.convert(parameters),
// Execute function to call the Arcade tool
execute: async ({ context }) => {
try {
// Execute the tool via Arcade API
const result = await arcade.tools.execute({
tool_name: name,
input: context,
user_id,
});
return result;
} catch (error) {
// Handle authorization errors
if (
error instanceof Error &&
isAuthorizationRequiredError(error)
) {
// Get authorization URL if needed
const response = await getAuthorizationResponse(name, user_id);
return {
authorization_required: true,
url: response.url,
message: "Forward this url to the user for authorization",
};
}
throw error;
}
},
});
} else {
console.warn(
`Skipping tool due to invalid schema: ${JSON.stringify(item)}`,
parsedItem.error,
);
}
return acc;
},
{},
);
}
/**
* Check if an error indicates authorization is required
*/
function isAuthorizationRequiredError(error: Error) {
return (
error?.name === "PermissionDeniedError" ||
error?.message?.includes("permission denied") ||
error?.message?.includes("authorization required")
);
}
/**
* Get the authorization URL for a tool
*/
async function getAuthorizationResponse(toolName: string, user_id: string) {
return await arcade.tools.authorize({
tool_name: toolName,
user_id,
});
}
Create and configure your Mastra agent
Now create a Mastra agent that uses Arcade tools:
const USER_ID = "[email protected]";
// Fetch and prepare Arcade tools for a specific toolkit
const arcadeTools = await getArcadeMastraTools({
toolkit: "github", // Choose the toolkit you need
user_id: USER_ID, // Pass an application-side user id
});
// Create the Mastra agent with Arcade tools
export const githubAgent = new Agent({
name: "githubAgent",
instructions: `You are a GitHub Agent that can help with code-related tasks.
If a tool requires authorization, you will receive an authorization URL.
When that happens, clearly present this URL to the user and ask them to visit it to grant permissions.`,
model: anthropic("claude-3-7-sonnet-20250219"),
tools: arcadeTools,
});
Interact with your agent
You can interact with your agent in two main ways:
1. Using the Mastra Development Playground:
Start the Mastra development server:
npm run dev
This will launch a local development playground, typically accessible at http://localhost:4111
. Open this URL in your browser, select the githubAgent
from the list of available agents, and start chatting with it directly in the UI.
2. Programmatically:
Alternatively, you can interact with the agent directly in your code:
// Generate a response from the agent
const response = await githubAgent.generate(
"How many stars does the ArcadeAI/arcade-ai repository have?",
);
console.log(response.text);
// Or stream the response for a more interactive experience
const stream = await githubAgent.stream("Create a new issue in my repository");
for await (const chunk of stream.textStream) {
process.stdout.write(chunk);
}
{ authorization_required: true, url: '...', message: '...' }
). Your agent’s instructions should guide it to present this URL to the user. After the user visits this URL and grants permissions, the tool can be used successfully. See the Managing user authorization guide for more details on handling authentication flows.