Building AI Agents with Mastra and Hotglue

6 min read by Hotglue

Your AI agent can write poetry, debug code, and explain quantum physics. But ask it to send a Slack message? That's where things get complicated.

The gap between "AI that talks" and "AI that does" is surprisingly wide. Most of the difficulty isn't the AI part—it's everything around it. OAuth flows, token refresh, per-user credentials, rate limits. Each integration you add multiplies this complexity.

This guide walks through building an agent with Mastra that can actually interact with Slack, GitHub, and other services. Hotglue handles the integration infrastructure so you can focus on what your agent does, not how it authenticates.

The hidden cost of "just call the API"

It sounds simple: your agent needs to post a Slack message, so you add the Slack API. But here's what that actually involves:

And that's one integration. Add GitHub, Google Calendar, and Notion, and you've built a small identity platform before writing any agent logic.

This is the part that slows teams down. Not the AI—the plumbing.

What you'll need

Before we start:

Configuring your integrations

Each integration needs credentials from the third-party service. You set these up once in Hotglue, and your users authenticate through a hosted flow.

Slack

Create a Slack App for your workspace:

  1. Head to api.slack.com/apps and create a new app
  2. Under OAuth & Permissions, add scopes: chat:write, channels:read, users:read
  3. Install the app to your workspace
  4. Grab the Bot User OAuth Token (starts with xoxb-)

Need more capabilities? Add scopes like channels:history for reading messages or reactions:write for emoji reactions. The Slack docs have the full list.

GitHub

Create an OAuth App:

  1. Go to Settings → Developer settings → OAuth Apps in GitHub
  2. Click New OAuth App, fill in your details
  3. Copy the Client ID and generate a Client Secret

Scopes like repo grant repository access; gist lets you create snippets. See the GitHub docs for setup details.

Adding credentials to Hotglue

Once you have credentials, add them in the Hotglue dashboard. From there, users authenticate through the Master Auth flow—Hotglue handles the OAuth handshake and stores tokens securely.

Setting up the project

Scaffold a new Mastra project:

npm create mastra@latest my-agent
cd my-agent

Add the Hotglue SDK:

npm install @hotglue/sdk

Configure your environment:

OPENAI_API_KEY=sk-...
HOTGLUE_API_KEY=hg_live_...

Fetching tools from Hotglue

The SDK's getTools function fetches integration tools and returns them in Mastra's format. Each tool handles auth automatically—you just call it.

Create src/mastra/tools/hotglue-tools.ts:

import { getTools } from "@hotglue/sdk";

export async function getHotglueTools(userId: string) {
  return getTools({
    apiKey: process.env.HOTGLUE_API_KEY!,
    integrations: ["slack", "github"],
    userId,
  });
}

The userId matters here. It tells Hotglue which user's credentials to use—essential when your app has multiple users, each with their own connected accounts.

Building the agent

Now wire the tools into an agent. Create src/mastra/agents/assistant.ts:

import { Agent } from "@mastra/core/agent";
import { getHotglueTools } from "../tools/hotglue-tools";

export async function createAssistant(userId: string) {
  const tools = await getHotglueTools(userId);

  return new Agent({
    name: "Assistant",
    instructions: `You are a helpful assistant that can interact with Slack and GitHub.

When asked to send messages, create issues, or perform other actions:
- Use the available tools to complete the task
- Confirm what you did after completing an action
- Ask for clarification if the request is ambiguous`,
    model: "openai/gpt-4o",
    tools,
  });
}

That's the core of it. The agent now has access to real integrations, scoped to the current user.

Getting users authenticated

Before tools work, users need to connect their accounts. Hotglue provides a Master Auth flow for this:

import { Hotglue } from "@hotglue/sdk";

const client = new Hotglue({
  apiKey: process.env.HOTGLUE_API_KEY!,
});

async function getAuthUrl(userId: string) {
  const result = await client.authenticate({
    userId,
    redirectTo: "https://yourapp.com/callback",
  });

  if (result.isComplete) {
    return null; // Already connected
  }

  return result.connectionsUrl;
}

Send users to connectionsUrl. They'll see each required integration, authenticate, and get redirected back to your app. No OAuth code on your side.

Running the agent

With authentication done, the agent just works:

import { createAssistant } from "./agents/assistant";

const agent = await createAssistant("user_123");

const response = await agent.generate(
  "Send a message to #general saying hello from the AI agent"
);

console.log(response.text);

Behind the scenes:

  1. The agent identifies it needs slack_post_message
  2. Hotglue injects the user's OAuth token
  3. The Slack API receives the request
  4. The agent confirms what happened

You didn't write any OAuth code. You didn't store any tokens. It just worked.

What tools are available?

Each integration exposes multiple tools. For Slack:

For GitHub:

Full lists in the integration docs.

When things go wrong

The SDK provides typed errors so you can handle failures gracefully:

import { Hotglue, HotglueAuthError, HotglueApiError } from "@hotglue/sdk";

const client = new Hotglue({ apiKey: process.env.HOTGLUE_API_KEY! });

try {
  const result = await client.execute({
    integration: "slack",
    tool: "post_message",
    userId: "user_123",
    input: { channel: "C0123456789", text: "Hello!" },
  });
} catch (error) {
  if (error instanceof HotglueAuthError) {
    const result = await client.authenticate({ userId: "user_123" });
    console.log("Please authenticate:", result.connectionsUrl);
  } else if (error instanceof HotglueApiError) {
    console.error(`Error ${error.status}: ${error.message}`);
  }
}

For full type safety, use the generated helpers:

import { Hotglue } from "@hotglue/sdk";
import { postMessage } from "@hotglue/sdk/slack";

const client = new Hotglue({ apiKey: process.env.HOTGLUE_API_KEY! });

const result = await client.execute({
  ...postMessage({ channel: "C0123456789", text: "Hello!" }),
  userId: "user_123",
});

console.log(result.ok, result.ts);

Where to go from here

You've got an agent that can take real action. A few directions from here:

The integration docs have the full tool reference. The Mastra docs cover workflows, memory, and deployment.

Questions? Something not working? Reach out at use@hotglue.tech — we're happy to help.

Back to all posts