Dynamic Tool Loading with Toolsets
Mastra lets you dynamically provide tools to an at runtime using toolsets. This approach is essential when integrating Arcade in web applications where each needs their own authentication flow.
Per-User Tool Authentication in Web Applications
In web applications serving multiple users, implement -specific authentication flows with these steps:
First, set up your Mastra configuration and in separate files:
// @/mastra/index.ts
import { Mastra } from "@mastra/core";
import { githubAgent } from "./agents/githubAgent";
// Initialize Mastra
export const mastra = new Mastra({
agents: {
githubAgent,
},
});
// @/mastra/agents/githubAgent.ts
import { Agent } from "@mastra/core/agent";
import { anthropic } from "@ai-sdk/anthropic";
// Create the agent without tools - we'll add them at runtime
export const githubAgent = new Agent({
name: "githubAgent",
instructions: `You are a GitHub Agent that helps with repository management.
You can help with tasks like:
- Listing repositories
- Creating and managing issues
- Viewing pull requests
- Managing repository settings
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"),
// No tools defined here - will be provided dynamically at runtime
});
Then, create an API endpoint that provides dynamically:
// app/api/chat/route.ts
import { NextRequest, NextResponse } from "next/server";
import { mastra } from "@/mastra";
import { Arcade } from "@arcadeai/arcadejs";
import { getUserSession } from "@/lib/auth"; // Your authentication handling
import { toZodToolSet } from "@arcadeai/arcadejs/lib";
import { executeOrAuthorizeZodTool } from "@arcadeai/arcadejs/lib";
export async function POST(req: NextRequest) {
// Extract request data
const { messages, threadId } = await req.json();
// Authenticate the user
const session = await getUserSession(req);
if (!session) {
return NextResponse.json({ message: "Unauthorized" }, { status: 401 });
}
try {
// Get the agent from Mastra
const githubAgent = mastra.getAgent("githubAgent");
const arcade = new Arcade();
const githubToolkit = await arcade.tools.list({ toolkit: "github", limit: 30 });
// Fetch user-specific Arcade tools for GitHub
const arcadeTools = toZodToolSet({
tools: githubToolkit.items,
client: arcade,
userId: session.user.email,
executeFactory: executeOrAuthorizeZodTool,
});
// Stream the response with dynamically provided tools
const response = await githubAgent.stream(messages, {
threadId, // Optional: For maintaining conversation context
resourceId: session.user.id, // Optional: For associating memory with user
toolChoice: "auto",
toolsets: {
arcade: arcadeTools, // Provide tools in a named toolset
},
});
// Return streaming response
return response.toDataStreamResponse();
} catch (error) {
console.error("Error processing GitHub request:", error);
return NextResponse.json(
{ message: "Failed to process request" },
{ status: 500 },
);
}
}
This approach provides several benefits:
- Each user gets their own separate authentication flow with Arcade
- A single instance works with multiple -specific toolsets
Handling Tool Authorization
When a tool requires user authorization, the receives a response with:
{
authorization_required: true,
url: "https://auth.arcade.com/...",
message: "Forward this url to the user for authorization"
}
Your should recognize this pattern and present the URL to the . To create a better user experience:
- Display the authorization URL as a clickable link in your UI
- Explain which service needs authorization and why
- Provide a way for to retry their request after authorization
Tips for Selecting Tools
- Focus on relevance: Choose tools that directly support your ’s specific purpose
- Consider performance: Some may have higher latency than others
- Handle errors gracefully: Implement robust error handling for third-party service failures
- Create clear flows: Design intuitive authorization experiences
Next Steps
After integrating Arcade tools into your Mastra , you can:
- Add memory capabilities to maintain between interactions
- Implement structured workflows for complex multi-step operations
- Enhance your with RAG capabilities for domain-specific knowledge
- Set up logging and tracing to monitor performance
For more detailed information on Mastra’s capabilities, visit the Mastra documentation .