CrewAI Integration Guide
This guide shows how to give your CrewAI agents payment capabilities using PQSafe’s ML-DSA-65 spend envelopes. In a multi-agent setup, each agent gets its own envelope with scoped permissions — preventing any single agent from overspending or paying unauthorized recipients.
Prerequisites
- Node.js ≥ 18 (or Python ≥ 3.10 for the Python SDK)
@pqsafe/agent-payinstalled (installation)- CrewAI installed:
Terminal window pip install crewai pqsafe-agent-pay - PQSafe issuer key configured in environment
Multi-agent payment architecture
In a CrewAI crew, multiple agents collaborate on a task. PQSafe allows you to issue separate envelopes per agent role — giving tighter control than a single shared payment credential:
Crew├── ResearchAgent (no payment envelope — read-only)├── ProcurementAgent (envelope: $500/day, recipients: [vendor-a.com, vendor-b.com])├── FinanceApproverAgent (approval oracle — resolves PQSafe approval gates)└── AuditAgent (reads ledger — no payment capability)Python SDK example
-
Install dependencies
Terminal window pip install crewai pqsafe-agent-pay python-dotenv -
Define spend envelopes per agent role
import osfrom pqsafe import generate_key_pair, create_spend_envelope, create_signed_envelopefrom datetime import datetime, timedelta# Generate per-agent key pairs at startupprocurement_keys = generate_key_pair()# Procurement agent: can pay approved vendors up to $500/dayprocurement_envelope = create_spend_envelope(agent_id='crewai-procurement-agent',max_amount=500.00,currency='USD',allowed_rails=['airwallex', 'wise'],allowed_recipients=['vendor-a.com','vendor-b.com','stripe.com',],valid_until=datetime.utcnow() + timedelta(hours=24),require_approval=True,approval_threshold=200.00, # Require human approval above $200memo='CrewAI procurement run — automated vendor payments',)signed_procurement_envelope = create_signed_envelope(procurement_envelope,procurement_keys['secret_key']) -
Build the PQSafe payment tool
from crewai.tools import BaseToolfrom pydantic import BaseModel, Fieldfrom pqsafe import execute_agent_payment, build_ledger_record, submit_to_ledgerimport jsonclass PaymentInput(BaseModel):recipient: str = Field(description="Payment recipient domain (e.g. vendor-a.com)")amount: float = Field(description="Payment amount in USD")memo: str = Field(description="Payment memo — appears in ledger and bank statement")rail: str = Field(default="airwallex", description="Payment rail: airwallex | wise | stripe")class PQSafePaymentTool(BaseTool):name: str = "pqsafe_execute_payment"description: str = """Execute a post-quantum-authorized payment via PQSafe AgentPay.All payments are cryptographically bounded by the spend envelope.Allowed recipients: vendor-a.com, vendor-b.com, stripe.comMax amount: $500 USD per envelopeRequires human approval for payments above $200."""def _run(self, recipient: str, amount: float, memo: str, rail: str = "airwallex") -> str:try:result = execute_agent_payment(signed_procurement_envelope,recipient=recipient,amount=amount,memo=memo,rail=rail,)# Log to immutable ledgerrecord = build_ledger_record(signed_procurement_envelope, result)ledger_entry = submit_to_ledger(record)return json.dumps({"status": result.status,"tx_id": result.tx_id,"rail": result.rail,"ledger_hash": ledger_entry.hash,"amount_paid": amount,"recipient": recipient,})except Exception as e:return f"Payment failed: {str(e)}" -
Define the crew with payment-capable agent
from crewai import Agent, Task, Crew, Processpayment_tool = PQSafePaymentTool()# Procurement agent — the only agent with payment capabilityprocurement_agent = Agent(role='Procurement Specialist',goal='Execute vendor payments efficiently and within approved budget limits',backstory="""You are an autonomous procurement agent with access topost-quantum-authorized payment rails. You can pay approved vendors up to$500 per envelope, with human approval required above $200.""",tools=[payment_tool],verbose=True,allow_delegation=False,)# Finance approver — resolves PQSafe approval gatesfinance_agent = Agent(role='Finance Approver',goal='Review and approve vendor payments above threshold',backstory="""You review payment requests forwarded by the procurement agent.You approve payments that align with the quarterly budget.""",tools=[], # No payment tools — approval-onlyverbose=True,)# Define tasksprocurement_task = Task(description="""Pay the following outstanding invoices:1. Vendor A: $150 for cloud hosting (invoice #VA-2026-042)2. Vendor B: $300 for data pipeline services (invoice #VB-2026-017)For each payment:- Verify the recipient is in the allowlist- Execute payment via the most appropriate rail- Confirm the ledger hash""",agent=procurement_agent,expected_output='Payment confirmations with transaction IDs and ledger hashes for all invoices',)crew = Crew(agents=[procurement_agent, finance_agent],tasks=[procurement_task],process=Process.sequential,verbose=True,) -
Run the crew
result = crew.kickoff()print(result)
TypeScript CrewAI example
CrewAI has an experimental TypeScript port. The pattern is the same:
import { generateKeyPair, createSpendEnvelope, createSignedEnvelope, executeAgentPayment, buildLedgerRecord, submitToLedger,} from '@pqsafe/agent-pay'
// Setup envelope (done at crew initialization)const { secretKey } = await generateKeyPair()const signedEnvelope = createSignedEnvelope( createSpendEnvelope({ agentId: 'crewai-ts-agent', maxAmount: 500, currency: 'USD', allowedRails: ['airwallex'], allowedRecipients: ['vendor-a.com', 'vendor-b.com'], validUntil: new Date(Date.now() + 86_400_000), requireApproval: true, approvalThreshold: 200, }), secretKey)
// PQSafe payment function (pass to your CrewAI tool definition)async function pqsafePay(recipient: string, amount: number, memo: string) { const result = await executeAgentPayment(signedEnvelope, { recipient, amount, memo }) const ledgerEntry = await submitToLedger(buildLedgerRecord(signedEnvelope, result)) return { status: result.status, txId: result.txId, ledgerHash: ledgerEntry.hash }}Per-agent envelope scoping
A key security benefit of multi-agent PQSafe integration is per-agent envelope isolation:
| Agent role | maxAmount | allowedRecipients | requireApproval |
|---|---|---|---|
| ProcurementAgent | $500 | vendor-a.com, vendor-b.com | Yes (>$200) |
| DevOpsAgent | $100 | cloudflare.com, aws.amazon.com | No |
| MarketingAgent | $200 | mailchimp.com, meta.com/ads | Yes (>$50) |
| AuditAgent | $0 | (none — read-only) | n/a |
Each agent can only spend what it’s been authorized for. A compromised ProcurementAgent cannot pay meta.com/ads — that’s cryptographically enforced by the envelope’s allowedRecipients list.
Expected output
[Crew] Starting procurement run...[ProcurementAgent] Executing payment: $150 to vendor-a.com via airwallex...[PQSafe] Signature valid. Envelope bounds: OK. Dispatching...[PQSafe] Payment settled. TX: txn_airwallex_abc123[ProcurementAgent] Ledger hash: 0xf7a3c2...[ProcurementAgent] Executing payment: $300 to vendor-b.com...[PQSafe] approvalThreshold exceeded ($300 > $200). Awaiting human approval...[Telegram] Sent approval request to @your-handle[PQSafe] Approval received. Dispatching...[PQSafe] Payment settled. TX: txn_airwallex_def456
Payments complete.- Invoice VA-2026-042: settled | TX: txn_airwallex_abc123 | Ledger: 0xf7a3c2...- Invoice VB-2026-017: settled | TX: txn_airwallex_def456 | Ledger: 0x91e4b8...Next steps
- LangChain Integration Guide — single-agent pattern with tool calling
- Telegram Approval Gate recipe — wire human-in-the-loop for large payments
- Pay USDC Vendor recipe — on-chain payment for crypto-native vendors
- SpendEnvelope concept — envelope fields, invariants, lifecycle