@ar-agents/mercadopago 0.17.1 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +44 -0
- package/cookbook/16-acp-checkout-with-factura.ts +168 -0
- package/cookbook/17-usa-llc-companion.ts +117 -0
- package/cookbook/18-usa-llc-self-incorporates-ar.ts +208 -0
- package/cookbook/19-forensic-compliance-dashboard.ts +320 -0
- package/cookbook/20-multi-tenant-marketplace.ts +274 -0
- package/cookbook/21-cross-jurisdictional-ap2.ts +298 -0
- package/cookbook/22-mp-webhook-afip-reconciliation.ts +374 -0
- package/cookbook/23-astro-arg-reference-customer.ts +187 -0
- package/cookbook/24-sociedad-ia-disaster-recovery.ts +350 -0
- package/cookbook/25-sociedad-ia-quarterly-compliance.ts +545 -0
- package/cookbook/26-certify-by-fetch.ts +536 -0
- package/cookbook/27-live-conformance-monitoring.ts +260 -0
- package/cookbook/28-operator-onboarding-checklist.ts +315 -0
- package/cookbook/29-publish-your-keys.ts +193 -0
- package/cookbook/30-submit-to-registry.ts +257 -0
- package/cookbook/README.md +2 -0
- package/dist/index.cjs +27 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -5
- package/dist/index.d.ts +21 -5
- package/dist/index.js +27 -14
- package/dist/index.js.map +1 -1
- package/package.json +5 -3
- package/tools.manifest.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,49 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.18.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`8c58aa0`](https://github.com/ar-agents/ar-agents/commit/8c58aa061a7579a2854ee4239ceb698c92148f28) Thanks [@naza00000](https://github.com/naza00000)! - `MercadoPagoError` now extends `ArAgentsError` from `@ar-agents/core`.
|
|
8
|
+
|
|
9
|
+
Brings family-coherence to the flagship integration. Every MP error
|
|
10
|
+
(`MercadoPagoAuthError`, `MercadoPagoRateLimitError`,
|
|
11
|
+
`MercadoPagoOverloadedError`, `MercadoPagoTimeoutError`,
|
|
12
|
+
`MercadoPagoPaymentRejectedError`, …) now exposes the uniform
|
|
13
|
+
`{ code, retryable, context }` contract so `@ar-agents/core`'s
|
|
14
|
+
`withRetry` middleware (and any external middleware) can switch on
|
|
15
|
+
the same fields used by every other `@ar-agents/*` package.
|
|
16
|
+
|
|
17
|
+
Codes assigned:
|
|
18
|
+
|
|
19
|
+
| Subclass | code | retryable |
|
|
20
|
+
| ------------------------------------------------------------------ | ----------------- | --------------------------------- |
|
|
21
|
+
| `MercadoPagoError` (generic) | `mp_api_error` | `true` for 5xx / 429 / `status:0` |
|
|
22
|
+
| `MercadoPagoAuthError` | `mp_auth_failed` | `false` |
|
|
23
|
+
| `MercadoPagoRateLimitError` | `mp_rate_limited` | `true` |
|
|
24
|
+
| `MercadoPagoOverloadedError` | `mp_overloaded` | `true` |
|
|
25
|
+
| `MercadoPagoTimeoutError` | `mp_timeout` | `true` |
|
|
26
|
+
| all 400 subclasses (back_url / self-payment / country / authorize) | `mp_api_error` | `false` |
|
|
27
|
+
|
|
28
|
+
Backward compatible: all existing public properties (`status`,
|
|
29
|
+
`endpoint`, `mpResponse`, `retryAfterSeconds`, `preapprovalId`, …) are
|
|
30
|
+
preserved on the instance AND mirrored into `context` for new code
|
|
31
|
+
that reads the `ArAgentsError` contract. `instanceof MercadoPagoError`
|
|
32
|
+
keeps working; `isArAgentsError(e)` now additionally returns `true`.
|
|
33
|
+
|
|
34
|
+
All 328 existing mercadopago tests pass with no changes.
|
|
35
|
+
|
|
36
|
+
## 0.17.2
|
|
37
|
+
|
|
38
|
+
### Patch Changes
|
|
39
|
+
|
|
40
|
+
- [`9b8e83c`](https://github.com/ar-agents/ar-agents/commit/9b8e83ce6f291a24e00101830a49afceb0102920) - Add 2 cookbook recipes that demonstrate the cross-package thesis:
|
|
41
|
+
|
|
42
|
+
- **16-acp-checkout-with-factura.ts** — the headline ACP-with-factura pattern. A ChatGPT Instant Checkout / Claude / Gemini agent POSTs an ACP `checkout_session`, the bridge mints a Mercado Pago preference, the buyer pays, and the bridge auto-emits an AFIP/ARCA Factura A/B/C/E via the `facturacionHook` — selecting the comprobante type based on the buyer's IVA condition. No other OSS implementation in LATAM ships this end-to-end.
|
|
43
|
+
- **17-usa-llc-companion.ts** — pattern for a USA-LLC agent (ClawBank, doola Agentic, MIDAO) operating in Argentina via an AR-resident facade. The USA agent declares `@ar-agents/mcp` in its MCP host config; all 89+6+2+10+5+6+5 tools become available without the USA agent ever holding AR credentials. Walks through the operator-of-record split + sample agent prompt that drives charge → factura → WhatsApp confirmation.
|
|
44
|
+
|
|
45
|
+
Cookbook is now 17 recipes (was 15).
|
|
46
|
+
|
|
3
47
|
## 0.17.1
|
|
4
48
|
|
|
5
49
|
### Patch Changes
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recipe 16 — ACP checkout with auto-issued AR factura electrónica.
|
|
3
|
+
*
|
|
4
|
+
* The headline pattern that no other implementation in LATAM ships out of the
|
|
5
|
+
* box: a **Stripe-style hosted checkout where the buyer is an LLM agent**
|
|
6
|
+
* (ChatGPT Instant Checkout / Claude tool calls / Gemini extensions), and your
|
|
7
|
+
* server auto-emits AFIP/ARCA factura electrónica when the payment confirms.
|
|
8
|
+
*
|
|
9
|
+
* # The flow
|
|
10
|
+
*
|
|
11
|
+
* 1. Agent POSTs `/checkout/sessions` with cart + buyer info (ACP spec).
|
|
12
|
+
* 2. Bridge validates the cart, computes totals, generates a session id.
|
|
13
|
+
* 3. Bridge creates a Mercado Pago `preference` and stores the mapping
|
|
14
|
+
* `acp_session → mp_preference` in your KV.
|
|
15
|
+
* 4. Bridge returns the ACP session with the `init_point_url` for the buyer.
|
|
16
|
+
* 5. Buyer pays. MP fires `payment.created` webhook.
|
|
17
|
+
* 6. Bridge's MP webhook handler dispatches to your `facturacionHook`,
|
|
18
|
+
* which calls `@ar-agents/facturacion` to emit Factura A/B/C/E based on
|
|
19
|
+
* the buyer's IVA condition (looked up via @ar-agents/identity).
|
|
20
|
+
* 7. ACP `complete_session` returns the factura PDF URL inside the receipt.
|
|
21
|
+
*
|
|
22
|
+
* # Why this is unique
|
|
23
|
+
*
|
|
24
|
+
* - Stripe's ACP doesn't ship AR factura (Stripe doesn't operate in AR).
|
|
25
|
+
* - Satsuma.ai's "make-my-site-agent-compatible" SaaS handles the agent
|
|
26
|
+
* surface but defers tax to the merchant.
|
|
27
|
+
* - MercadoPago's official MCP exposes payments but no ACP layer.
|
|
28
|
+
* - This recipe is the only OSS path from "agent buys" to "factura emitted"
|
|
29
|
+
* without the merchant writing tax-emission code themselves.
|
|
30
|
+
*/
|
|
31
|
+
|
|
32
|
+
import { createDispatcher } from "@ar-agents/agentic-commerce-bridge";
|
|
33
|
+
import {
|
|
34
|
+
createMercadoPagoPaymentProvider,
|
|
35
|
+
mercadoPagoPaymentHandler,
|
|
36
|
+
} from "@ar-agents/agentic-commerce-bridge/mp";
|
|
37
|
+
import {
|
|
38
|
+
createFacturacionHook,
|
|
39
|
+
selectFacturaType,
|
|
40
|
+
} from "@ar-agents/agentic-commerce-bridge/facturacion";
|
|
41
|
+
import { InMemoryStateAdapter } from "@ar-agents/agentic-commerce-bridge";
|
|
42
|
+
|
|
43
|
+
import { MercadoPagoClient } from "@ar-agents/mercadopago";
|
|
44
|
+
import { WsfeClient } from "@ar-agents/facturacion";
|
|
45
|
+
|
|
46
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
47
|
+
// Wire the bridge — payment provider + factura emission hook
|
|
48
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
49
|
+
|
|
50
|
+
const mp = new MercadoPagoClient({
|
|
51
|
+
accessToken: process.env.MP_ACCESS_TOKEN!,
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const wsfe = new WsfeClient({
|
|
55
|
+
certPem: process.env.AFIP_CERT_PEM!,
|
|
56
|
+
keyPem: process.env.AFIP_KEY_PEM!,
|
|
57
|
+
cuit: Number(process.env.AFIP_CUIT!),
|
|
58
|
+
env: "prod",
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// Payment provider: knows how to mint MP preferences from ACP cart payloads.
|
|
62
|
+
const mpProvider = createMercadoPagoPaymentProvider({
|
|
63
|
+
client: mp,
|
|
64
|
+
notificationUrl: "https://yourdomain.com/api/mp/webhook",
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// Facturacion hook: fires after `payment.approved` from MP webhook.
|
|
68
|
+
const facturacionHook = createFacturacionHook({
|
|
69
|
+
wsfe,
|
|
70
|
+
defaultPtoVta: 1, // your AFIP point-of-sale
|
|
71
|
+
// Agent decides what to bill against — typically a CUIT lookup result
|
|
72
|
+
// for B2B sales, or "consumidor final" for B2C (Factura B).
|
|
73
|
+
selectType: ({ buyer }) =>
|
|
74
|
+
selectFacturaType({
|
|
75
|
+
sellerCondition: "responsable_inscripto", // your IVA condition
|
|
76
|
+
buyerCondition: buyer.taxStatus ?? "consumidor_final",
|
|
77
|
+
}),
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// Dispatcher: routes the ACP HTTP surface (checkout-session CRUD).
|
|
81
|
+
const dispatcher = createDispatcher({
|
|
82
|
+
state: new InMemoryStateAdapter(), // VercelKVStateAdapter in prod
|
|
83
|
+
payment: mpProvider,
|
|
84
|
+
hooks: { onPaymentApproved: facturacionHook },
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
88
|
+
// Next.js Route Handler — the ACP HTTP surface
|
|
89
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
90
|
+
|
|
91
|
+
export async function POST(req: Request, ctx: { params: { route: string[] } }) {
|
|
92
|
+
// Spec endpoints:
|
|
93
|
+
// POST /checkout_sessions → handleCreateSession
|
|
94
|
+
// POST /checkout_sessions/{id} → handleUpdateSession
|
|
95
|
+
// POST /checkout_sessions/{id}/complete → handleCompleteSession
|
|
96
|
+
// POST /checkout_sessions/{id}/cancel → handleCancelSession
|
|
97
|
+
return dispatcher.handle(req);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export async function GET(req: Request) {
|
|
101
|
+
// Spec endpoints:
|
|
102
|
+
// GET /checkout_sessions/{id} → handleGetSession
|
|
103
|
+
// GET /.well-known/acp.json → discovery payload
|
|
104
|
+
return dispatcher.handle(req);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
108
|
+
// Companion MP webhook route — fires the facturacion hook
|
|
109
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
110
|
+
|
|
111
|
+
export async function MP_WEBHOOK(req: Request) {
|
|
112
|
+
// The bridge's MP integration verifies HMAC signatures and dispatches
|
|
113
|
+
// to your `onPaymentApproved` hook. The hook receives the ACP session
|
|
114
|
+
// (looked up via the external_reference round-trip) + the MP payment.
|
|
115
|
+
return mercadoPagoPaymentHandler({
|
|
116
|
+
state: dispatcher.state,
|
|
117
|
+
hooks: dispatcher.hooks,
|
|
118
|
+
webhookSecret: process.env.MP_WEBHOOK_SECRET!,
|
|
119
|
+
})(req);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
123
|
+
// What an agent sees
|
|
124
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
125
|
+
|
|
126
|
+
/*
|
|
127
|
+
A ChatGPT Instant Checkout flow (excerpt):
|
|
128
|
+
|
|
129
|
+
1. Agent calls `POST /checkout_sessions` with:
|
|
130
|
+
{
|
|
131
|
+
"buyer": { "email": "buyer@example.com" },
|
|
132
|
+
"items": [{ "id": "sku-123", "quantity": 1, "amount": 100000 }],
|
|
133
|
+
"totals": { "amount": 100000, "currency": "ars", ... },
|
|
134
|
+
"fulfillment_address": { ... }
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
2. Bridge returns:
|
|
138
|
+
{
|
|
139
|
+
"id": "cs_abc123",
|
|
140
|
+
"status": "ready_for_payment",
|
|
141
|
+
"payment_method": {
|
|
142
|
+
"type": "redirect",
|
|
143
|
+
"redirect_url": "https://www.mercadopago.com.ar/checkout/v1/redirect?pref_id=…"
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
3. Buyer pays. MP fires webhook → facturacionHook fires → AFIP returns CAE.
|
|
148
|
+
|
|
149
|
+
4. Agent calls `POST /checkout_sessions/cs_abc123/complete`:
|
|
150
|
+
{
|
|
151
|
+
"id": "cs_abc123",
|
|
152
|
+
"status": "complete",
|
|
153
|
+
"receipt": {
|
|
154
|
+
"payment_id": "mp-payment-id",
|
|
155
|
+
"factura": {
|
|
156
|
+
"type": "B",
|
|
157
|
+
"cae": "75123456789012",
|
|
158
|
+
"cae_due": "2026-05-18",
|
|
159
|
+
"pdf_url": "https://yourdomain.com/facturas/cs_abc123.pdf",
|
|
160
|
+
"amount": 100000,
|
|
161
|
+
"issued_at": "2026-05-08T19:00:00Z"
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
The agent surfaces the factura URL to the buyer in its receipt rendering.
|
|
167
|
+
The merchant did zero tax-emission code — the bridge handled it.
|
|
168
|
+
*/
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recipe 17 — USA-LLC agent operating in Argentina via @ar-agents/* MCP.
|
|
3
|
+
*
|
|
4
|
+
* Pattern: a USA-incorporated agent (ClawBank-formed Wyoming/Ohio LLC, doola
|
|
5
|
+
* Agentic LLC, Marshall Islands MIDAO entity, etc.) needs to do business in
|
|
6
|
+
* Argentina — invoice AR customers, validate AR taxpayer IDs, accept Mercado
|
|
7
|
+
* Pago, ship via Andreani, monitor regulatory changes. The USA agent doesn't
|
|
8
|
+
* itself have AR tax residency or banking infrastructure; it composes with a
|
|
9
|
+
* thin AR-resident "facade" entity (escribano, contador, or platform partner)
|
|
10
|
+
* for the bits that legally require AR presence.
|
|
11
|
+
*
|
|
12
|
+
* # The split
|
|
13
|
+
*
|
|
14
|
+
* USA-LLC agent AR facade (escribano / contador / platform)
|
|
15
|
+
* ----------------- -------------------------------------------
|
|
16
|
+
* - decides what to do - holds the AFIP/ARCA cert
|
|
17
|
+
* - signs payment intent - emits factura under their CUIT
|
|
18
|
+
* - holds USD escrow - converts USD → ARS for settlement
|
|
19
|
+
* - delegates AR ops - acts as the AR-resident contracting party
|
|
20
|
+
*
|
|
21
|
+
* The USA agent never touches AFIP directly. Instead it calls an AR-resident
|
|
22
|
+
* MCP server that exposes @ar-agents/* tools, and that MCP server's keys belong
|
|
23
|
+
* to the AR facade. This is the legally-clean way to operate cross-border:
|
|
24
|
+
* the AR entity is the principal, the USA agent is the platform.
|
|
25
|
+
*
|
|
26
|
+
* # The MCP host config (USA-LLC side)
|
|
27
|
+
*
|
|
28
|
+
* The USA agent (Claude Desktop / Cursor / a custom MCP host) declares:
|
|
29
|
+
*
|
|
30
|
+
* {
|
|
31
|
+
* "mcpServers": {
|
|
32
|
+
* "ar-ops": {
|
|
33
|
+
* "command": "npx",
|
|
34
|
+
* "args": ["-y", "@ar-agents/mcp"],
|
|
35
|
+
* "env": {
|
|
36
|
+
* // ALL of these belong to the AR facade — never the USA agent.
|
|
37
|
+
* "MP_ACCESS_TOKEN": "APP_USR-…", // facade's MP merchant token
|
|
38
|
+
* "AFIP_CERT_PEM": "-----BEGIN CERTIFICATE-----…",
|
|
39
|
+
* "AFIP_KEY_PEM": "-----BEGIN PRIVATE KEY-----…",
|
|
40
|
+
* "AFIP_CUIT": "30-12345678-9", // facade's CUIT
|
|
41
|
+
* "WHATSAPP_ACCESS_TOKEN": "EAA…" // optional
|
|
42
|
+
* }
|
|
43
|
+
* }
|
|
44
|
+
* }
|
|
45
|
+
* }
|
|
46
|
+
*
|
|
47
|
+
* # What the USA agent can now do
|
|
48
|
+
*
|
|
49
|
+
* - validate_cuit(payerCuit) — algorithm, free, no AR exposure
|
|
50
|
+
* - lookup_cuit_afip(payerCuit) — AR fiscal data, scoped to facade's cert
|
|
51
|
+
* - create_payment(amount, payerEmail, ...) — charges run on facade's MP merchant
|
|
52
|
+
* - emit_factura_b(amount, payerCuit, items) — emitted under facade's CUIT
|
|
53
|
+
* - cotizar_envio_andreani(toCpa, weight) — quote against facade's carrier account
|
|
54
|
+
* - send_whatsapp_text(to, body) — sent from facade's WhatsApp number
|
|
55
|
+
*
|
|
56
|
+
* The USA agent's logic stays in JS; the AR-resident operations stay on the
|
|
57
|
+
* AR side. Both sides see the agreement via signed MCP tool-call records.
|
|
58
|
+
*
|
|
59
|
+
* # Sample agent loop (USA-LLC side, using Vercel AI SDK 6 + MCP client)
|
|
60
|
+
*/
|
|
61
|
+
|
|
62
|
+
import { Experimental_Agent as Agent, stepCountIs } from "ai";
|
|
63
|
+
// In a USA agent's project, you'd use the MCP client from `ai` v6 (or `@modelcontextprotocol/sdk`)
|
|
64
|
+
// to connect to the locally-spawned ar-agents MCP server. The agent then sees
|
|
65
|
+
// every @ar-agents/* tool in its tool list.
|
|
66
|
+
//
|
|
67
|
+
// import { experimental_createMCPClient as createMCPClient } from "ai";
|
|
68
|
+
|
|
69
|
+
async function exampleAgentLoop() {
|
|
70
|
+
// ─── Boot the MCP client connection (USA agent → AR facade's MCP server) ─
|
|
71
|
+
// const arOps = await createMCPClient({
|
|
72
|
+
// transport: { type: "stdio", command: "npx", args: ["-y", "@ar-agents/mcp"] },
|
|
73
|
+
// });
|
|
74
|
+
// const tools = await arOps.tools();
|
|
75
|
+
//
|
|
76
|
+
// The 89 + 6 + 2 + 10 + 5 + 6 + 5 = 123 tools across all 7 packages are
|
|
77
|
+
// now available as if they were native to the USA agent.
|
|
78
|
+
|
|
79
|
+
const agent = new Agent({
|
|
80
|
+
model: "anthropic/claude-sonnet-4-6",
|
|
81
|
+
instructions:
|
|
82
|
+
"You are an AI agent incorporated as a Wyoming LLC. To do business in " +
|
|
83
|
+
"Argentina you delegate AR-resident operations to an AR facade via the " +
|
|
84
|
+
"ar-ops MCP server. ALL invoicing, payment collection, taxpayer lookups, " +
|
|
85
|
+
"and shipping in AR go through ar-ops tools. Never store AR credentials " +
|
|
86
|
+
"yourself.",
|
|
87
|
+
// tools, // injected from MCP client
|
|
88
|
+
tools: {} as Record<string, unknown>,
|
|
89
|
+
stopWhen: stepCountIs(10),
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// What the agent does behind this prompt:
|
|
93
|
+
// 1. validate_cuit("20-12345678-9") via ar-ops
|
|
94
|
+
// 2. lookup_cuit_afip → "Cliente SRL, Responsable Inscripto"
|
|
95
|
+
// 3. cotizar_envio_andreani(B1842, 0.5kg) → AR$ 4.500
|
|
96
|
+
// 4. create_payment(amount=104500, payerEmail) → init_point_url
|
|
97
|
+
// 5. (after payment confirms) emit_factura_a(104500, payerCuit, ["servicio digital"])
|
|
98
|
+
// 6. send_whatsapp_text(payerPhone, "Listo. Factura A: <pdf-url>")
|
|
99
|
+
const { text } = await agent.generate({
|
|
100
|
+
prompt:
|
|
101
|
+
"Cobrale a un cliente AR (CUIT 20-12345678-9, email contacto@ejemplo.com.ar, " +
|
|
102
|
+
"WhatsApp +5491155555555) USD 100 (≈ AR$ 100.000) por un servicio de consultoría " +
|
|
103
|
+
"+ envío Andreani al CP B1842. Si validás que es Responsable Inscripto, emití " +
|
|
104
|
+
"factura A. Si no, factura B. Mandale el link por WhatsApp cuando esté.",
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
console.log(text);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (process.argv[1]?.endsWith("17-usa-llc-companion.ts")) {
|
|
111
|
+
exampleAgentLoop().catch((err: unknown) => {
|
|
112
|
+
console.error(err);
|
|
113
|
+
process.exit(1);
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export { exampleAgentLoop };
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recipe 18 — USA-LLC agent self-incorporates an AR sociedad-IA.
|
|
3
|
+
*
|
|
4
|
+
* The end-to-end pattern that the headline of `/sociedades-ia` makes a
|
|
5
|
+
* concrete claim about: a USA-incorporated agent (ClawBank-formed
|
|
6
|
+
* Wyoming/Ohio LLC, doola Agentic LLC, Marshall Islands MIDAO) needs an
|
|
7
|
+
* AR-resident operating layer for some of its activity. Until now this
|
|
8
|
+
* was a manual escribano + contador job per spawn. Recipe 18 collapses
|
|
9
|
+
* the manual layer to one programmatic call:
|
|
10
|
+
*
|
|
11
|
+
* POST https://ar-agents.ar/api/auto-incorporate
|
|
12
|
+
*
|
|
13
|
+
* via the `@ar-agents/incorporate` client. The output is everything the
|
|
14
|
+
* USA-LLC agent's deploy pipeline needs to spin up the AR side:
|
|
15
|
+
*
|
|
16
|
+
* - package.json + lib/agent.ts + .env.example + README.md
|
|
17
|
+
* - Vercel one-click deploy URL pointing at apps/sociedad-ia-starter
|
|
18
|
+
* - Env-var manifest the agent must source from its secret store
|
|
19
|
+
* - Legal + operational checklist (ARCA cert, MP token, Meta verify,
|
|
20
|
+
* IGJ inscription via TAD)
|
|
21
|
+
* - Signed audit-log reference — the entire incorporation request is
|
|
22
|
+
* a forensic event under RFC-001 § 9.2, queryable later
|
|
23
|
+
*
|
|
24
|
+
* # Why this recipe matters
|
|
25
|
+
*
|
|
26
|
+
* RFC-001 § 7 sketches "cross-jurisdictional agent commerce". The USA
|
|
27
|
+
* side has its own corporate-form vehicles for AI-only entities (Wyoming
|
|
28
|
+
* DAO LLC, Marshall Islands MIDAO). What it doesn't have natively is a
|
|
29
|
+
* way to operate inside the AR jurisdiction — emit factura electrónica,
|
|
30
|
+
* receive Mercado Pago, monitor Boletín Oficial, pay monotributo. Recipe
|
|
31
|
+
* 18 is how that side fills.
|
|
32
|
+
*
|
|
33
|
+
* # The one-line pitch
|
|
34
|
+
*
|
|
35
|
+
* `pnpm add @ar-agents/incorporate` → `await incorporate({...})` →
|
|
36
|
+
* AR sociedad-IA spec ready in 100ms (then the human-pending bits:
|
|
37
|
+
* ARCA cert wait, IGJ inscription wait, Meta verification wait — all
|
|
38
|
+
* upstream timers we don't control).
|
|
39
|
+
*
|
|
40
|
+
* # Edge Runtime
|
|
41
|
+
*
|
|
42
|
+
* The client is fetch-only, zero dependencies. Runs on Vercel Edge,
|
|
43
|
+
* Cloudflare Workers, Deno, browsers. No `node:*` imports.
|
|
44
|
+
*/
|
|
45
|
+
|
|
46
|
+
import { incorporate, fetchAudit, type IncorporateInput } from "@ar-agents/incorporate";
|
|
47
|
+
|
|
48
|
+
// ─── 1. The USA-LLC agent gathers the AR sociedad's parameters ─────────────
|
|
49
|
+
//
|
|
50
|
+
// Often these come from the human deal-maker once (corporate name + objeto)
|
|
51
|
+
// and the rest is mechanical. The `sessionId` is what ties this incorporation
|
|
52
|
+
// request to subsequent operational events under one forensic timeline.
|
|
53
|
+
|
|
54
|
+
const sessionId = crypto.randomUUID();
|
|
55
|
+
|
|
56
|
+
const input: IncorporateInput = {
|
|
57
|
+
// Public corporate name. IGJ rejects reserved words (Nacional / Estatal /
|
|
58
|
+
// Gobierno / Estado / Oficial). The pre-flight at the server side will
|
|
59
|
+
// catch them; surface the validation findings to the human if any.
|
|
60
|
+
denominacion: "ClawBank-AR Operations SAS",
|
|
61
|
+
|
|
62
|
+
// SOCIEDAD-IA is the eventual target — but until the AR regime is
|
|
63
|
+
// sancionado (estimated H1 2027), use SAS so the operator runs under the
|
|
64
|
+
// RFC-001 § 3.1 three-layer liability framework with a human representante.
|
|
65
|
+
tipo: "SAS",
|
|
66
|
+
|
|
67
|
+
// Capital social in ARS. SAS minimum is 100k. Set higher if the operator
|
|
68
|
+
// expects to handle larger incoming flows (banks may scrutinize disparities
|
|
69
|
+
// between capital and transaction volume).
|
|
70
|
+
capitalSocial: 200_000,
|
|
71
|
+
|
|
72
|
+
// Objeto social. IGJ rejects generic phrasing; be specific. 20-2000 chars.
|
|
73
|
+
objeto:
|
|
74
|
+
"Operación de servicios digitales y desarrollo de software propio para clientes argentinos, en representación de la entidad madre USA-incorporada bajo el marco RFC-001 § 7 (cross-jurisdictional agent commerce).",
|
|
75
|
+
|
|
76
|
+
// Human representante for the AR-side legal facade per RFC-001 § 3.1. In
|
|
77
|
+
// production the orchestrator pulls this from its operator-of-record store
|
|
78
|
+
// (e.g., the escribano contracted as the AR-presence layer).
|
|
79
|
+
representante: {
|
|
80
|
+
nombre: "Pérez, Juan",
|
|
81
|
+
cuit: "20-12345678-9",
|
|
82
|
+
},
|
|
83
|
+
emailContacto: "ops+ar@usa-llc.example",
|
|
84
|
+
|
|
85
|
+
// Pieza selection. The auto-incorporate endpoint always merges in the
|
|
86
|
+
// required set (identity, gde-tad, mercadopago, banking, facturacion).
|
|
87
|
+
// Add what this particular operator needs:
|
|
88
|
+
piezas: [
|
|
89
|
+
"identity",
|
|
90
|
+
"gde-tad",
|
|
91
|
+
"mercadopago",
|
|
92
|
+
"banking",
|
|
93
|
+
"facturacion",
|
|
94
|
+
"boletin-oficial",
|
|
95
|
+
"igj",
|
|
96
|
+
"whatsapp",
|
|
97
|
+
"ap2", // for AP2 mandate verification on incoming agent commerce
|
|
98
|
+
"agentic-commerce-bridge", // to expose ACP-compliant checkout to ChatGPT/Claude buyers
|
|
99
|
+
],
|
|
100
|
+
|
|
101
|
+
// The session id chains every event under one forensic timeline.
|
|
102
|
+
sessionId,
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
// ─── 2. Call the endpoint ──────────────────────────────────────────────────
|
|
106
|
+
|
|
107
|
+
async function main() {
|
|
108
|
+
const result = await incorporate(input);
|
|
109
|
+
|
|
110
|
+
if (!result.ok) {
|
|
111
|
+
// Validation failure (HTTP 422). The server caught a structural issue
|
|
112
|
+
// (reserved word, capital below minimum, malformed CUIT, etc). The agent
|
|
113
|
+
// should surface findings to the human and retry with a fix.
|
|
114
|
+
console.error("Incorporation rejected at pre-flight:");
|
|
115
|
+
for (const f of result.validation.findings) {
|
|
116
|
+
console.error(` [${f.severity}] ${f.field}: ${f.message}`);
|
|
117
|
+
}
|
|
118
|
+
process.exit(1);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// ─── 3. Materialize the four generated files into the deploy repo ─────
|
|
122
|
+
//
|
|
123
|
+
// The output is plain strings — the USA-LLC's deploy pipeline writes them
|
|
124
|
+
// to a fresh GitHub repo, then triggers the Vercel deploy. Below we just
|
|
125
|
+
// print to stdout for the recipe's purposes.
|
|
126
|
+
|
|
127
|
+
console.log("Sociedad:", result.sociedad);
|
|
128
|
+
console.log();
|
|
129
|
+
console.log("Generated files:");
|
|
130
|
+
for (const path of Object.keys(result.config) as Array<
|
|
131
|
+
keyof typeof result.config
|
|
132
|
+
>) {
|
|
133
|
+
console.log(`\n--- ${path} (${result.config[path].length} chars) ---`);
|
|
134
|
+
console.log(result.config[path].slice(0, 200) + "…");
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// ─── 4. Surface the deploy URL to the human (or auto-deploy) ──────────
|
|
138
|
+
//
|
|
139
|
+
// The Vercel one-click clone URL is pre-filled with the right env-var
|
|
140
|
+
// slots. In production: pipe to the orchestrator's deploy runner. For
|
|
141
|
+
// a manual flow: print the URL and let the human click.
|
|
142
|
+
|
|
143
|
+
console.log("\nDeploy:", result.deploy.oneClickUrl);
|
|
144
|
+
|
|
145
|
+
// ─── 5. Hand off the operational checklist to the human ───────────────
|
|
146
|
+
//
|
|
147
|
+
// These are the human-pending steps: ARCA cert wait, MP creds, Meta
|
|
148
|
+
// business verify, IGJ inscription via TAD. The agent can't shortcut
|
|
149
|
+
// them — they're upstream gov/private-co timers — but it can emit them
|
|
150
|
+
// all at once so nothing falls through the cracks.
|
|
151
|
+
|
|
152
|
+
console.log("\nChecklist (human-pending):");
|
|
153
|
+
for (const [i, step] of result.checklist.entries()) {
|
|
154
|
+
console.log(` ${i + 1}. ${step}`);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// ─── 6. Log + verify the forensic event ───────────────────────────────
|
|
158
|
+
//
|
|
159
|
+
// The incorporation request is itself a tool call recorded in the audit
|
|
160
|
+
// log. Anyone (regulator, journalist, downstream agent) can later hit
|
|
161
|
+
// /api/play/audit/{sessionId}?verify=1
|
|
162
|
+
// and confirm the entry is HMAC-clean. This is what makes RFC-001 § 9.2's
|
|
163
|
+
// claim that the log is "legally probative" mechanically true.
|
|
164
|
+
|
|
165
|
+
console.log("\nAudit:");
|
|
166
|
+
console.log(" sessionId:", result.audit.sessionId);
|
|
167
|
+
console.log(" backend:", result.audit.backend);
|
|
168
|
+
console.log(" hmac:", result.audit.entry.hmac?.slice(0, 30) + "…");
|
|
169
|
+
console.log(" dashboard:", result.audit.dashboardUrl);
|
|
170
|
+
|
|
171
|
+
// Optional: re-verify the entry the agent just wrote. Useful if the orchestrator
|
|
172
|
+
// wants to assert tamper-free state before proceeding to step 7+.
|
|
173
|
+
const audit = (await fetchAudit(sessionId, { verify: true })) as {
|
|
174
|
+
verification?: { tampered: number; verified: number; total: number };
|
|
175
|
+
};
|
|
176
|
+
if (audit.verification && audit.verification.tampered > 0) {
|
|
177
|
+
throw new Error(
|
|
178
|
+
`Audit log shows ${audit.verification.tampered} tampered entries — abort`,
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
console.log("\nVerified clean:", audit.verification);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
main().catch((err) => {
|
|
185
|
+
console.error("Recipe 18 failed:", err);
|
|
186
|
+
process.exit(1);
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
// ─── 7. What happens after ─────────────────────────────────────────────────
|
|
190
|
+
//
|
|
191
|
+
// Once the AR side is provisioned, the USA-LLC agent and the AR sociedad-IA
|
|
192
|
+
// can transact under a single trust contract:
|
|
193
|
+
//
|
|
194
|
+
// - The USA agent calls the AR sociedad's /api/agent endpoint with mandate
|
|
195
|
+
// proof (AP2 § 4 — see @ar-agents/ap2 cookbook recipe 02 — multi-hop).
|
|
196
|
+
// - The AR sociedad executes within its jurisdiction (factura emission,
|
|
197
|
+
// MP cobro, BCRA credit checks, etc).
|
|
198
|
+
// - Every tool call lands in the same audit log (chain via the same
|
|
199
|
+
// sessionId).
|
|
200
|
+
// - At end-of-month, the USA-LLC's accountant + the AR sociedad's contador
|
|
201
|
+
// settle the inter-entity ledger off the audit log's signed events.
|
|
202
|
+
//
|
|
203
|
+
// This is the reference implementation of cross-jurisdictional agent
|
|
204
|
+
// commerce. The whole stack — from the npm package this recipe imports to
|
|
205
|
+
// the audit log it leaves behind — is MIT-licensed and SLSA-provenanced.
|
|
206
|
+
//
|
|
207
|
+
// `agent self-incorporates → operates → settles` in three contractual hops,
|
|
208
|
+
// no escribono in the loop after step 1.
|