Skip to content

Pay Anthropic Credits from an AI Agent

Scenario: Your LangChain agent monitors its Anthropic API credit balance. When it drops below $10, the agent autonomously tops up by $50 — using a PQSafe spend envelope to authorize the payment through Airwallex ACH, no human intervention required.

Prerequisites

  • @pqsafe/agent-pay installed and configured
  • An Anthropic account with billing API access
  • Airwallex account with ACH enabled (AIRWALLEX_CLIENT_ID, AIRWALLEX_API_KEY in .env)
  • A PQSafe issuer key (PQSAFE_ISSUER_KEY in .env)
  • LangChain: npm install langchain @langchain/anthropic

Install

Terminal window
npm install @pqsafe/agent-pay langchain @langchain/anthropic
  1. Create a spend envelope scoped to Anthropic

    The envelope hard-caps spending at $200/day and restricts the recipient to Anthropic’s payment address.

    import {
    generateKeyPair,
    createSpendEnvelope,
    createSignedEnvelope,
    } from '@pqsafe/agent-pay'
    const { publicKey, secretKey } = await generateKeyPair()
    const envelope = createSpendEnvelope({
    agentId: 'anthropic-credit-topup-agent',
    maxAmount: 200, // Hard cap: $200 max per envelope
    currency: 'USD',
    allowedRails: ['airwallex'],
    allowedRecipients: ['anthropic.com'],
    validUntil: new Date(Date.now() + 86_400_000), // 24h validity
    requireApproval: false, // Fully autonomous below $200
    memo: 'Anthropic API credits — autonomous top-up',
    })
    const signedEnvelope = createSignedEnvelope(envelope, secretKey)
  2. Build the LangChain tool

    The tool checks the Anthropic balance and executes a top-up if credits are low.

    import { DynamicTool } from 'langchain/tools'
    import { executeAgentPayment, buildLedgerRecord, submitToLedger } from '@pqsafe/agent-pay'
    const TOP_UP_THRESHOLD = 10 // Top up when balance drops below $10
    const TOP_UP_AMOUNT = 50 // Add $50 each time
    async function getAnthropicBalance(): Promise<number> {
    const res = await fetch('https://api.anthropic.com/v1/account/usage', {
    headers: { 'x-api-key': process.env.ANTHROPIC_API_KEY! },
    })
    const data = await res.json()
    return data.credits_remaining_usd ?? 0
    }
    const anthropicTopUpTool = new DynamicTool({
    name: 'top_up_anthropic_credits',
    description: `Checks Anthropic API credit balance and tops up by $${TOP_UP_AMOUNT} if below $${TOP_UP_THRESHOLD}. Returns payment status.`,
    func: async (_input: string) => {
    const balance = await getAnthropicBalance()
    if (balance >= TOP_UP_THRESHOLD) {
    return `Balance is $${balance.toFixed(2)} — no top-up needed.`
    }
    // Execute payment via PQSafe
    const result = await executeAgentPayment(signedEnvelope, {
    recipient: 'anthropic.com/billing',
    amount: TOP_UP_AMOUNT,
    memo: `Credit top-up — balance was $${balance.toFixed(2)}`,
    })
    // Log to immutable ledger
    await submitToLedger(buildLedgerRecord(signedEnvelope, result))
    return `Top-up complete. Status: ${result.status}. TX: ${result.txId}. New balance expected: ~$${(balance + TOP_UP_AMOUNT).toFixed(2)}.`
    },
    })
  3. Wire the spending alert webhook

    Get notified when the envelope is 80% consumed (before it runs out).

    import express from 'express'
    import { setAgentPayConfig } from '@pqsafe/agent-pay'
    setAgentPayConfig({
    webhooks: {
    envelopeConsumed: {
    threshold: 0.8, // Fire at 80% of maxAmount
    url: 'https://your-server.com/webhooks/pqsafe',
    },
    },
    })
    // Webhook handler
    const app = express()
    app.use(express.json())
    app.post('/webhooks/pqsafe', (req, res) => {
    const { event, envelopeId, consumed, maxAmount } = req.body
    if (event === 'envelope.threshold_reached') {
    console.warn(
    `⚠️ Envelope ${envelopeId} is ${(consumed / maxAmount * 100).toFixed(0)}% consumed.`
    )
    // Trigger issuance of a new envelope here
    }
    res.sendStatus(200)
    })
  4. Build the LangChain agent

    import { ChatAnthropic } from '@langchain/anthropic'
    import { AgentExecutor, createOpenAIFunctionsAgent } from 'langchain/agents'
    import { ChatPromptTemplate } from '@langchain/core/prompts'
    const llm = new ChatAnthropic({
    model: 'claude-opus-4-5',
    apiKey: process.env.ANTHROPIC_API_KEY,
    })
    const prompt = ChatPromptTemplate.fromMessages([
    ['system', 'You are an autonomous ops agent. Monitor API credit balances and top them up as needed.'],
    ['human', '{input}'],
    ['placeholder', '{agent_scratchpad}'],
    ])
    const agent = await createOpenAIFunctionsAgent({
    llm,
    tools: [anthropicTopUpTool],
    prompt,
    })
    const executor = new AgentExecutor({ agent, tools: [anthropicTopUpTool] })
  5. Run the agent

    const result = await executor.invoke({
    input: 'Check Anthropic credit balance and top up if needed.',
    })
    console.log(result.output)

Complete runnable example

import {
generateKeyPair,
createSpendEnvelope,
createSignedEnvelope,
executeAgentPayment,
buildLedgerRecord,
submitToLedger,
} from '@pqsafe/agent-pay'
import { DynamicTool } from 'langchain/tools'
import { ChatAnthropic } from '@langchain/anthropic'
import { AgentExecutor, createOpenAIFunctionsAgent } from 'langchain/agents'
import { ChatPromptTemplate } from '@langchain/core/prompts'
const { secretKey } = await generateKeyPair()
const signedEnvelope = createSignedEnvelope(
createSpendEnvelope({
agentId: 'anthropic-topup',
maxAmount: 200,
currency: 'USD',
allowedRails: ['airwallex'],
allowedRecipients: ['anthropic.com'],
validUntil: new Date(Date.now() + 86_400_000),
}),
secretKey
)
const topUpTool = new DynamicTool({
name: 'top_up_anthropic_credits',
description: 'Check Anthropic balance; top up $50 if below $10.',
func: async () => {
const result = await executeAgentPayment(signedEnvelope, {
recipient: 'anthropic.com/billing',
amount: 50,
memo: 'Autonomous credit top-up',
})
await submitToLedger(buildLedgerRecord(signedEnvelope, result))
return `Payment ${result.status}. TX: ${result.txId}`
},
})
const agent = await createOpenAIFunctionsAgent({
llm: new ChatAnthropic({ model: 'claude-opus-4-5' }),
tools: [topUpTool],
prompt: ChatPromptTemplate.fromMessages([
['system', 'You are an ops agent. Top up Anthropic credits when needed.'],
['human', '{input}'],
['placeholder', '{agent_scratchpad}'],
]),
})
const result = await new AgentExecutor({ agent, tools: [topUpTool] }).invoke({
input: 'Check and top up Anthropic credits if needed.',
})
console.log(result.output)

Expected output

> Entering new AgentExecutor chain...
> Invoking tool: top_up_anthropic_credits
Payment settled. TX: txn_airwallex_abc123
Balance after top-up: ~$57.34
> Finished chain.
Top-up complete. Added $50 to Anthropic account. New expected balance: ~$57.34.

Troubleshooting

ProblemSolution
ENVELOPE_EXPIREDEnvelope’s validUntil passed — create a new one
RECIPIENT_NOT_ALLOWEDCheck allowedRecipients includes 'anthropic.com'
RAIL_TIMEOUTAirwallex API is slow — retry with exponential backoff
INSUFFICIENT_BALANCEAirwallex account needs funds — top up via Airwallex dashboard
Balance API returns 401Check ANTHROPIC_API_KEY is set and valid

Next steps