How to Add ATXP to Mastra

Mastra is one of the fastest-growing TypeScript agent frameworks — clean API, good observability, solid workflow primitives. What it doesn’t have: a way to tell an agent it has a $5 budget and enforce it.

ATXP is that layer. Here’s how to connect them.

The Problem ATXP Solves for Mastra

Mastra agents call LLMs and tools. Both cost money. Without ATXP:

  • All agents share your primary API keys
  • No agent has a spending ceiling
  • You find out what an agent cost after the fact, if at all

With ATXP:

  • Each agent has its own account with an isolated key
  • Each account has a hard credit limit
  • Every call is logged with timestamp and cost

Prerequisites

  • Node.js 18+
  • @mastra/core installed
  • An ATXP account (atxp.ai)

Step 1: Create an Agent Account

const response = await fetch('https://api.atxp.ai/v1/agents', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.ATXP_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    name: 'mastra-research-agent',
    budget: 3.00,
    currency: 'usd',
  }),
});

const { id: agentId, api_key: agentKey } = await response.json();

Step 2: Configure Mastra’s LLM Client to Route Through ATXP

Mastra uses OpenAI-compatible LLM providers. Point the model at ATXP’s proxy endpoint:

import { Mastra } from '@mastra/core';
import { createOpenAI } from '@ai-sdk/openai';

// Route LLM calls through ATXP using the agent's isolated key
const atxpOpenAI = createOpenAI({
  apiKey: agentKey,  // Agent's key, not your primary OpenAI key
  baseURL: 'https://api.atxp.ai/v1/proxy/openai',
});

const mastra = new Mastra({
  agents: {
    researchAgent: {
      name: 'Research Agent',
      model: atxpOpenAI('gpt-4o'),
      instructions: 'You are a research agent. Gather and synthesize information on requested topics.',
    },
  },
});

For Anthropic models:

import { createAnthropic } from '@ai-sdk/anthropic';

const atxpAnthropic = createAnthropic({
  apiKey: agentKey,
  baseURL: 'https://api.atxp.ai/v1/proxy/anthropic',
});

// Use in your Mastra agent config
model: atxpAnthropic('claude-sonnet-4-6'),

Step 3: Run Your Agent Normally

const agent = mastra.getAgent('researchAgent');

const result = await agent.generate(
  'Summarize the current state of agent payment protocols.',
  { maxSteps: 5 }
);

console.log(result.text);

Nothing changes in your agent logic. The budget enforcement happens transparently at the ATXP layer.

Step 4: Check What the Agent Spent

async function getAgentSpend(agentId: string) {
  const response = await fetch(
    `https://api.atxp.ai/v1/agents/${agentId}/transactions`,
    {
      headers: { 'Authorization': `Bearer ${process.env.ATXP_API_KEY}` },
    }
  );

  const { data } = await response.json();

  const totalCost = data.reduce((sum: number, tx: any) => sum + tx.cost_usd, 0);

  console.log(`Agent spent: $${totalCost.toFixed(4)}`);
  data.forEach((tx: any) => {
    console.log(`  ${tx.timestamp} | ${tx.model} | $${tx.cost_usd.toFixed(4)}`);
  });
}

await getAgentSpend(agentId);

Step 5: Integrate With Mastra Workflows

For Mastra workflows that orchestrate multiple agents, give each agent its own ATXP account and track spend at the workflow level:

import { createWorkflow, createStep } from '@mastra/core/workflows';

const researchWorkflow = createWorkflow({
  id: 'research-workflow',
  inputSchema: z.object({ topic: z.string() }),
})
  .then(
    createStep({
      id: 'gather-sources',
      execute: async ({ context }) => {
        // Uses the research agent's ATXP account
        const agent = mastra.getAgent('researchAgent');
        return agent.generate(`Find 5 authoritative sources on: ${context.topic}`);
      },
    })
  )
  .then(
    createStep({
      id: 'synthesize',
      execute: async ({ context }) => {
        // Uses the synthesis agent's separate ATXP account
        const agent = mastra.getAgent('synthesisAgent');
        return agent.generate(`Synthesize these findings: ${context.previousOutput}`);
      },
    })
  );

Each agent’s spend is tracked independently. You can see exactly what the gather step cost vs. the synthesis step — and cap each separately.

Production Notes

Per-job accounts: For batch workflows, create a fresh ATXP agent account per job. When the job completes, archive the account. You get a clean cost record for every job run.

Graceful budget handling: When ATXP returns a 402, Mastra will surface it as an error. Wrap your agent calls in a try-catch and handle depletion explicitly — log it, alert, or trigger a human review.

Shared accounts for low-value agents: Not every agent needs its own account. A low-stakes summarization agent can share an account with other low-stakes agents. Reserve dedicated accounts for agents with significant blast radius — the ones that call external services, handle money, or take irreversible actions.

For more on the blast radius concept, see agent credential blast radius. For the broader architecture pattern, see how to build a multi-agent system with ATXP.

Get started with ATXP — the payment infrastructure layer for agents that need to act in production.