Skip to content

Mastra Adapter

Mastra is a TypeScript-first agentic framework with native tool calling, memory, and workflow support. The PQSafe Mastra adapter wraps spend envelope authorization into a Mastra-compatible tool definition.

Installation

Terminal window
npm install @pqsafe/agent-pay @mastra/core

Define the PQSafe payment tool

Mastra tools use a createTool() helper with Zod schema validation — the same pattern as the LangChain adapter.

import { createTool } from '@mastra/core/tools'
import { z } from 'zod'
import {
generateKeyPair,
createSpendEnvelope,
createSignedEnvelope,
executeAgentPayment,
buildLedgerRecord,
submitToLedger,
} from '@pqsafe/agent-pay'
// Initialize envelope at module load (once per agent instance)
const { secretKey } = await generateKeyPair()
const signedEnvelope = createSignedEnvelope(
createSpendEnvelope({
agentId: 'mastra-agent',
maxAmount: 500,
currency: 'USD',
allowedRails: ['airwallex', 'stripe'],
allowedRecipients: [
'anthropic.com',
'cloudflare.com',
'vercel.com',
],
validUntil: new Date(Date.now() + 3_600_000),
requireApproval: true,
approvalThreshold: 100,
memo: 'Mastra agent — infrastructure payments',
}),
secretKey
)
export const pqsafePayTool = createTool({
id: 'pqsafe-pay',
description: `Execute a post-quantum-authorized payment via PQSafe AgentPay.
Allowed recipients: anthropic.com, cloudflare.com, vercel.com
Max amount: $500 USD. Approval required above $100.`,
inputSchema: z.object({
recipient: z.string().describe('Recipient domain from the allowlist'),
amount: z.number().positive().max(500).describe('Amount in USD'),
memo: z.string().min(5).describe('Payment memo for ledger and bank reference'),
rail: z
.enum(['airwallex', 'stripe'])
.optional()
.default('airwallex')
.describe('Payment rail'),
}),
outputSchema: z.object({
status: z.enum(['settled', 'pending', 'failed']),
txId: z.string(),
rail: z.string(),
ledgerHash: z.string(),
}),
execute: async ({ context }) => {
const { recipient, amount, memo, rail } = context
const result = await executeAgentPayment(signedEnvelope, {
recipient,
amount,
memo,
rail,
})
const record = buildLedgerRecord(signedEnvelope, result)
const ledgerEntry = await submitToLedger(record)
return {
status: result.status,
txId: result.txId,
rail: result.rail,
ledgerHash: ledgerEntry.hash,
}
},
})

Wire to a Mastra agent

import { Agent } from '@mastra/core'
import { pqsafePayTool } from './tools/pqsafe-pay'
export const procurementAgent = new Agent({
name: 'Procurement Agent',
instructions: `You are an autonomous procurement agent with post-quantum-authorized payment capabilities.
You can make payments to approved vendors within your spend envelope limits.
Always confirm the business purpose before executing a payment.
All payments are logged to an immutable ledger — there is no undo.`,
model: {
provider: 'ANTHROPIC',
toolChoice: 'auto',
name: 'claude-sonnet-4-6',
},
tools: {
pqsafePay: pqsafePayTool,
},
})

Run the agent

import { Mastra } from '@mastra/core'
import { procurementAgent } from './agents/procurement'
const mastra = new Mastra({
agents: { procurement: procurementAgent },
})
const result = await mastra.getAgent('procurement').generate(
'Pay $45 to cloudflare.com for the April invoice. Reference: CF-2026-04.'
)
console.log(result.text)

Mastra workflows with PQSafe

Mastra’s workflow system lets you sequence payment steps with conditional logic:

import { createWorkflow, createStep } from '@mastra/core/workflows'
const payInvoiceWorkflow = createWorkflow({
name: 'pay-invoice',
triggerSchema: z.object({
invoiceId: z.string(),
amount: z.number(),
recipient: z.string(),
}),
})
const validateStep = createStep({
id: 'validate-invoice',
execute: async ({ context }) => {
// Validate the invoice details
const { invoiceId, amount, recipient } = context.triggerData
return { valid: amount > 0 && amount <= 500, invoiceId, amount, recipient }
},
})
const payStep = createStep({
id: 'execute-payment',
execute: async ({ context }) => {
const { amount, recipient, invoiceId } = context.steps['validate-invoice'].output
const result = await executeAgentPayment(signedEnvelope, {
recipient,
amount,
memo: `Invoice ${invoiceId}`,
})
return result
},
})
payInvoiceWorkflow.then(validateStep).then(payStep).commit()

Next steps