HomeMastraManaging user authorization

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
The toolsets parameter provides tools only for the current request without modifying the agent’s base configuration. This makes it ideal for multi-user applications where each user needs their own secure OAuth flow with Arcade.

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:

For more detailed information on Mastra’s capabilities, visit the Mastra documentation.