Building AI Agents with Mastra and 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:
- Building an OAuth consent flow for your users
- Securely storing access tokens and refresh tokens
- Handling token expiration mid-request
- Managing credentials separately for each user
- Dealing with rate limits that vary by endpoint
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:
- Node.js 20+
- A Hotglue account (grab an API key from the dashboard)
- An OpenAI API key, or another model provider Mastra supports
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:
- Head to api.slack.com/apps and create a new app
- Under OAuth & Permissions, add scopes:
chat:write,channels:read,users:read - Install the app to your workspace
- 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:
- Go to Settings → Developer settings → OAuth Apps in GitHub
- Click New OAuth App, fill in your details
- 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:
- The agent identifies it needs
slack_post_message - Hotglue injects the user's OAuth token
- The Slack API receives the request
- 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:
slack_post_message— send messages to channels or DMsslack_list_conversations— list available channelsslack_get_conversation_history— fetch message historyslack_add_reaction— react to messages
For GitHub:
github_create_issue— create issuesgithub_create_gist— create code snippetsgithub_list_repos— list repositories
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:
- Add more integrations — browse the available tools
- Chain actions into workflows — post a Slack message when a GitHub issue is created
- Add memory — let your agent remember past conversations
- Deploy — Mastra Cloud handles hosting if you don't want to manage infrastructure
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.