Dynamic Tool Loading with Toolsets
Mastra lets you dynamically provide tools to an agent at runtime using toolsets. This approach is essential when integrating Arcade tools in web applications where each user needs their own authentication flow.
Per-User Tool Authentication in Web Applications
In web applications serving multiple users, implement user-specific authentication flows with these steps:
First, set up your Mastra configuration and agents 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 tools 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 { getArcadeMastraTools } from "@/lib/arcade-tools"; // Your tool adapter implementation
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");
// Fetch user-specific Arcade tools for GitHub
const arcadeTools = await getArcadeMastraTools({
toolkit: "github",
user_id: session.user.email,
});
// 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 tools
- A single agent instance works with multiple user-specific toolsets
Handling Tool Authorization
When a tool requires user authorization, the agent receives a response with:
{
authorization_required: true,
url: "https://auth.arcade.com/...",
message: "Forward this url to the user for authorization"
}
Your agent should recognize this pattern and present the URL to the user. 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 users to retry their request after authorization
Tips for Selecting Tools
- Focus on relevance: Choose tools that directly support your agent’s specific purpose
- Consider performance: Some tools may have higher latency than others
- Handle errors gracefully: Implement robust error handling for third-party service failures
- Create clear user flows: Design intuitive authorization experiences
Next Steps
After integrating Arcade tools into your Mastra agent, you can:
- Add memory capabilities to maintain context between interactions
- Implement structured workflows for complex multi-step operations
- Enhance your agent 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.