Why agents need payment capabilities
The average e-commerce operation in Brazil involves six systems per sale: a payment gateway to charge via Pix, a fiscal service to issue the NF-e, a logistics platform to generate a shipping label, WhatsApp to notify the customer, an ERP to record the transaction, and a banking API to reconcile the funds. A human operator touches all six. For every order.
AI agents can orchestrate these systems faster, more reliably, and at a fraction of the cost. But they need the right tools. An LLM that "knows about Pix" cannot actually call a Pix provider's API, handle the webhook for payment confirmation, or parse SEFAZ's response codes. Knowledge without tools is trivia. Tools without orchestration is plumbing. You need both.
This tutorial walks you through building an agent that handles the complete commerce flow using the CodeSpar SDK. By the end, you'll have an agent that charges via Pix, issues an NF-e, and notifies the customer on WhatsApp. Then we'll combine all three into a single Complete Loop call.
Prerequisites
You need: Node.js 20+; a CodeSpar account, which comes with a test project and a test key (csk_test_…) at Dashboard → API Keys; and the providers these examples use, connected in the project: a charge provider for Pix, NFe.io for the NF-e (with the A1 certificate uploaded to your NFe.io company, the state tax registration, the tax regime and each item's ICMS, IPI, PIS and COFINS classification), Z-API for WhatsApp (an instance paired with your WhatsApp number, with its instance ID, instance token and Client-Token connected in the project), and a carrier for the shipping label. Under a test key, each call goes to its provider's test environment; NFe.io and Z-API have none, so the NF-e and the WhatsApp message are refused under a test key and run only in a live project, where they take real effect. The examples compile against @codespar/sdk 0.16.11; they were not run end to end for this article.
Start by installing the SDK:
Get your API key from the CodeSpar dashboard. Test mode is free, which is more than enough for this tutorial.
Create a .env file in your project root:
A test key keeps every tool call in test: each one goes to the provider's test environment, and a provider without one is refused instead of reaching production. No real charges. No real invoices. Switch to a live key when you're ready.
Step 1: Create a session with payment servers
Every interaction with CodeSpar starts with a session. A session is an immutable context container that tells the SDK which MCP servers to connect to, which credentials to use, and which user is making the request.
The preset: "brazilian" flag is important. It tells the SDK which servers to load for Brazilian commerce: zoop, nuvem-fiscal, melhor-envio, z-api and omie. The meta tools route each call to the provider connected in your project: a Pix charge to your Pix provider (Asaas, Mercado Pago, Celcoin and others in the catalog), the NF-e to NFe.io, WhatsApp to Z-API and labels to Melhor Envio. Omie has no meta tool.
You can also specify individual servers with the servers array.
Sessions solve three problems at once. First, credential isolation: each session binds to a specific user's OAuth tokens and API keys. Second, context scoping: the LLM only sees the tools available in the session, not the entire catalog. Third, usage attribution: every tool call in a session is logged against the organization that created it. Logging is not billing: tool calls are not billed, and billing follows the pricing table.
Step 2: Execute a Pix charge
With the session created, you can call codespar_charge to charge a customer via Pix (its counterpart, codespar_pay, sends money out). This is a meta tool: it doesn't call a provider's API directly. CodeSpar routes it to the Pix provider connected in your project (in Brazil, the catalog lists Asaas, Mercado Pago, EBANX, Celcoin, Iugu and Stone for Pix charges) and calls it with that connection's credentials.
The response includes a Pix copy-and-paste code and a QR code. You can send either to the customer.
Handling payment confirmation
Pix payments confirm in real time. When the customer scans the QR code and authorizes the payment, the BACEN (Central Bank) settles the funds instantly. CodeSpar listens for the provider's webhook and records the payment's status:
In test mode, how a payment gets confirmed depends on the provider's test environment. In production, you'll want to use webhooks for reliability.
Pix settles in under 10 seconds. Compare that to credit cards (D+30 in Brazil) or ACH in the US (2-3 business days). Instant settlement makes Pix structurally superior for agent-driven commerce.
Step 3: Issue the NF-e automatically
In Brazil, every sale requires a Nota Fiscal Eletronica (NF-e). This isn't optional. SEFAZ (the state tax authority) validates every invoice in real time. An incorrect CFOP, a wrong ICMS rate, or a malformed XML and the invoice is rejected. Businesses face fines for issuing invoices late or incorrectly.
The codespar_invoice meta tool sends the invoice to NFe.io, which generates and signs the XML and submits it to SEFAZ. Each item's tax classification and the fiscal setup come from you (below).
Tax classification: ICMS rates vary across 26 Brazilian states. A product shipped from SP to RJ has a different rate than SP to BA. Each item needs its ICMS, IPI, PIS and COFINS classification (CST/CSOSN) on the NFe.io side; without it, NFe.io refuses the NF-e.
XML signing: NF-e requires a valid A1 digital certificate. It is uploaded to your NFe.io company, and NFe.io signs the XML with it. Renewing the certificate before it expires is up to you.
Step 4: Notify the customer via WhatsApp
In Latin America, WhatsApp isn't a nice-to-have notification channel. It's the primary channel. Over 500 million people in the region use it daily. Customers expect order confirmations, payment receipts, and tracking updates on WhatsApp, not email.
The codespar_notify meta tool routes to the Z-API MCP server:
On this rail, codespar_notify sends the message as text through Z-API, to the number in to (country code and number, digits only). When Z-API accepts the send-text request, codespar_notify returns the message id Z-API sent back, the channel, the recipient and the status QUEUED. QUEUED means only that Z-API accepted the request: it does not say the message was delivered or read.
Why not email?
Open rates tell the story. WhatsApp messages in Brazil have a 90%+ open rate. Email marketing sits around 15-20%. For transactional messages (payment confirmation, shipping updates), WhatsApp delivery is nearly instant.
Step 5: The Complete Loop
Steps 2-4 each call a single tool. That's useful for testing, but in production you want the agent to chain the steps, within the credentials, permissions and approvals configured in your project. This is what the Complete Loop does: charge, invoice, ship, notify — in one call. ERP registration and bank reconciliation have no meta tool today, so this loop stops at the notification.
First, create a session with the full preset:
Then send a natural language instruction:
Four meta tools. One natural language instruction. This is what the Complete Loop looks like in code.
session.send() hands the instruction to the agent, which calls the meta tools in dependency order: the charge before the invoice, the invoice before the label, and so on. Each call comes back in run.tool_calls. When you want a fixed order instead, loop(session, { steps }) runs the steps you list, one after another, and onStepComplete reports each one.
What's happening under the hood
When you call session.send() or loop(session, ...), three layers process the request:
1. Meta tool routing
A Brazilian commerce preset loads several MCP servers, each with its own raw tools. Exposing all of them to an LLM wastes context window tokens and increases the chance of tool selection errors. Instead, the SDK compresses them into meta tools, among them codespar_charge, codespar_invoice, codespar_ship and codespar_notify.
Each meta tool acts as a router. When the agent calls codespar_charge with method: "pix", the meta tool resolves this to the charge tool of the provider your organization connected (Asaas create_payment, for example). If you passed method: "boleto", it would route to that provider's boleto instead. The agent doesn't need to know which underlying tool to call — the meta tool handles selection.
2. Managed authentication
Each provider takes different credentials. Zoop and NFe.io take an API key. Z-API takes an instance ID, an instance token and a Client-Token. Melhor Envio uses OAuth. CodeSpar keeps them in its vault, per user connection, and resolves them on each call. You never pass raw credentials in tool calls.
3. Framework adapters
The SDK works with any LLM framework. The tools(session) function returns tool definitions compatible with Claude, OpenAI, and the Vercel AI SDK:
Going to production
The sandbox gets you through development. Production requires three additional considerations.
Billing and quotas
CodeSpar prices by settled money movement, not by tool call. The payment that settles is the billable event; the invoice, label, notification, and ERP steps around it are included in that transaction price. Test mode is free, and Enterprise contracts negotiate volume pricing separately. Current rates are on the pricing page.
Error handling
Production commerce fails in predictable ways. Pix charges expire. SEFAZ goes down. WhatsApp rate-limits you. The SDK surfaces them in two places: a tool result that did not succeed, and a typed error when the API refuses the request or does not answer in time:
Monitoring
The dashboard provides real-time visibility into every session: tool calls, latencies, error rates, and billing. You can also feed Datadog, Grafana, or any OpenTelemetry-compatible system from session.sendStream(), which yields each tool call and its result as it happens.
What you've built
In this tutorial, you've built an agent that:
1. Charges via Pix through codespar_charge, with a QR code and a copy-and-paste code.
2. Issues an NF-e through codespar_invoice, once the fiscal setup in the prerequisites is in place.
3. Notifies the customer on WhatsApp through Z-API, as a text message.
4. Runs the Complete Loop: the charge, invoice, shipping and notification steps from a single natural language instruction.
These are the same meta tools a live key calls in production. The code does not change between your test session and a production session; the key does.
The code you wrote in test is the code you run in production. That's what infrastructure should feel like.
Try the Sandbox: Test tool calls interactively in the CodeSpar Sandbox.
Read the Complete Loop deep dive: Understand every step, every edge case, and every compliance requirement in our Complete Loop deep dive.
Browse the MCP catalog: See all 50+ servers and 400+ tools on GitHub.
Fabiano Cruz is co-founder of CodeSpar. The SDK is available at npm. All MCP servers referenced in this tutorial are open source on GitHub.
Atualizado em 07/10/2026: os exemplos agora compilam com o @codespar/sdk 0.16.11: a cobrança usa codespar_charge (o codespar_pay envia dinheiro), uma chave de teste substitui a variável CODESPAR_ENV, que nenhuma versão do SDK lê, o loop cobre os quatro passos que têm meta tool, os tempos que não foram medidos saíram e os links do sandbox e do catálogo apontam para as páginas atuais. A cobrança Pix vai para o provedor conectado ao projeto, não para a Zoop, e a contagem de ferramentas brutas saiu. Chamadas de ferramenta são registradas, não cobradas, e QUEUED quer dizer só que a Z-API aceitou o pedido.