AAuth Budgets: un tope de gasto para agentes que no mueve dinero
Por primera vez, un draft rumbo al IETF nombra la inferencia LLM medida como el caso para el que fue escrito. AAuth Budgets le da a un agente un tope de gasto. El servidor de la persona decide el tamaño, el recurso lo hace cumplir y no se mueve dinero. Leímos el nuevo protocolo base, el draft Budgets aún no enviado y su pariente más cercano, sondeamos el único despliegue en producción que menciona y probamos su señal de costo en streaming contra 16 configuraciones de cliente HTTP. El diseño es cuidadoso. Encontramos cuatro huecos entre el diseño y la práctica.
La pregunta que responde es fácil de plantear. Un agente llama a un endpoint de inferencia con la cuenta de una persona o de una empresa. ¿Qué le impide gastar diez mil dólares cuando la tarea valía diez? Hoy las respuestas están fuera de cualquier protocolo: un dashboard del proveedor, un límite de tarjeta, una factura mensual. Nuestra propia auditoría de los spend controls de x402 encontró lo mismo del lado de las stablecoins. Los SDK del comprador limitan el gasto localmente, y nada en el wire dice cuánto puede gastar un agente.
Nuestras fuentes, todas leídas el 27 de septiembre de 2026: draft-hardt-oauth-aauth-protocol-11 (publicado el 25 de septiembre, 164 páginas); draft-hardt-httpbis-signature-key-09 (13 de septiembre); las copias del editor de AAuth Budgets y AAuth R3 en el repositorio dickhardt/AAuth en el commit a200889 (25 de septiembre); la especificación TPX v0.3; el repositorio regent-httpsig en la release 0.6.0; y los paquetes @aauth en npm. Enviamos requests GET y POST sin autenticar a dos despliegues públicos. Todas las pruebas de cliente corrieron contra un servidor local. No firmamos nada y no pagamos nada.
AAuth en una pasada
AAuth es la propuesta de Dick Hardt para la autorización de agentes. Hardt fue el editor de RFC 6749, el framework de OAuth 2.0. AAuth parte de una premisa: cada instancia de agente tiene su propia identidad criptográfica. Un agente recibe un identificador de la forma aauth:local@domain de su agent provider. Genera un par de claves, con Ed25519 como recomendación. El provider emite un agent token (typ: aa-agent+jwt) que ata la clave al identificador. Ese token no debería vivir más de 24 horas.
Cada request que hace el agente va firmada con una HTTP Message Signature de RFC 9421. El token viaja en un header Signature-Key, definido en un draft complementario que Hardt firma junto a Thibault Meunier, de Cloudflare. Ninguna credencial es un bearer token y nada requiere registro previo. En palabras del draft, "the first API call to a resource is the registration".
A partir de ahí, el protocolo sube una escalera. La revisión -11 define cinco modos de acceso a recursos:
Modo El recurso sabe Partes
agent identity qué agente agente, recurso
resource-managed qué persona (login propio) agente, recurso
person identity qué persona (vía PS) agente, recurso, PS
PS authorization persona + scope consentido agente, recurso, PS
federated persona + veredicto de policy agente, recurso, PS, AS
// PS = person server (representa a la persona u organización)
// AS = access server (el motor de políticas del recurso)
Un recurso dice lo que necesita con un solo header de respuesta, AAuth-Requirement. Puede ir en un 401, un 202 o un 402, con valores como agent-token, person-token, auth-token e interaction. Los person tokens y los auth tokens viven como máximo una hora. Los resource tokens, que el recurso le entrega al agente para que los lleve a su person server, no deberían vivir más de cinco minutos.
La revisión -11 es una reescritura grande. Agrega el person token y el modo person identity. Elimina el claim act. Reemplaza el objeto mission por un hash, mission_s256. Y en los tres modos que involucran un person server, "no token a resource reads carries an agent identifier". El recurso sabe quién es la persona, no qué agente está actuando.
El estado importa. El draft es una individual submission sin working group. Lleva doce revisiones con su nombre actual desde el 29 de abril de 2026, después de tres con un nombre anterior que empezó el 2 de abril. Su sección de implementaciones lista cuatro, todas marcadas como "exploratory": TypeScript de Hellō, un SDK de .NET, y una demo en Python más una extensión de Keycloak de Christian Posta. El repositorio de GitHub se creó en octubre de 2025 y tenía 123 stars y 37 issues y pull requests abiertos cuando lo revisamos.
draft-patwhite-aauth-00, mayo de 2025, y draft-rosenberg-oauth-aauth-01, abril de 2026) es un grant type de OAuth sin relación con el diseño de Hardt. Los resultados de búsqueda mezclan ambos. Todo lo que sigue se refiere a draft-hardt-oauth-aauth-protocol.
Un budget es una autorización, no un pago
AAuth Budgets es una extensión que todavía no se envió al IETF. Se agregó al repositorio el 11 de agosto de 2026, marcada como "Exploratory Draft", y su último cambio es del 20 de septiembre. Su abstract es una sola frase: un budget es "a ceiling on what an agent may consume at one resource, denominated in a unit the resource declares, carried as a claim in the auth token, and enforced by the resource".
La introducción plantea la motivación sin rodeos: "An agent harness calling a model inference endpoint on a person's account can spend without bound." Un scope como inference.completions se concede o no. No dice nada sobre si el agente puede gastar diez centavos o diez mil dólares. Y el draft agrega: "Metered inference is the initiating use case."
La decisión de diseño clave está en los non-goals. "Not payment or settlement. No funds move. 402 Payment Required and the resource's commercial arrangement with the person are untouched." Un budget acota lo que un agente puede consumir. Cómo se le paga al recurso es otra pregunta.
El objeto budget tiene tres miembros y aparece en los mismos lugares que un scope:
{
"scope": "inference.completions",
"budget": { "amount": 5000000, "unit": "USD", "decimals": 6 }
}
// 5000000 / 10^6 = $5.00. Un entero en una escala declarada, nunca un float.
Pasa por una cadena de reducción. El agente puede pedir un monto. El recurso fija la unidad y la escala, y puede bajar el monto. El person server puede bajarlo otra vez. En el acceso de cuatro partes, el access server puede bajarlo una vez más. Después de que habla el recurso, nadie puede cambiar la unidad ni los decimales. Pedir más de lo que el recurso permite no es un error. El recurso simplemente reduce el monto.
Una regla del camino de cuatro partes merece atención. Si el resource token trae un budget y la request del person server al access server lo omite, el access server "MUST NOT issue a budget claim". Una copia anterior leía la omisión como una concesión de la oferta completa. Eso hacía que un person server que nunca implementó Budgets pareciera uno que concedía el máximo. La corrección es acertada.
La asignación no es el techo
El draft separa dos números. El techo real de la persona es estado privado del person server: "no claim carries it, and it may not be shared with the agent". Lo que lleva un auth token es una asignación contra ese techo. El token vence en menos de una hora, o se agota su budget, lo que ocurra primero. En cualquiera de los dos casos, el agente tiene que volver a su person server por más.
Ese regreso es donde ocurre la supervisión. El draft lista seis respuestas posibles del person server: conceder la oferta del recurso, conceder menos, preguntarle al agente por qué necesita más, preguntarle a la persona, rechazar con un suggested_budget, o terminar el trabajo. También explica por qué al agente nunca se le informa su gasto acumulado. Un agente que ve su gasto a lo largo de varias asignaciones puede deducir el techo por resta.
El costo también está escrito. Un agente con varios tokens en el mismo recurso tiene varios budgets. Un person server que emite n tokens concurrentes de X cada uno "has authorized up to nX for as long as an hour". El recurso controla cada token por separado. Solo el person server puede controlar el total.
Dónde queda el pago
Si los budgets no mueven dinero, algo más tiene que hacerlo. La respuesta de AAuth es poner el pago al lado de la autorización, en la misma respuesta y en campos separados. La sección 11.6 de -11 dice que un 402 con AAuth-Requirement "says authorization and payment are both required; the payment requirement is conveyed separately, by x402 or the Payment scheme". Y agrega: "AAuth never conveys its own requirements via WWW-Authenticate."
Eso encaja limpiamente con x402 v2, cuyo challenge viaja en su propio header PAYMENT-REQUIRED, como confirma la spec de transporte. Un vendedor puede enviar un 402 con ambos headers. Un agente que habla los dos protocolos lee los dos. Uno que solo habla x402 paga, reintenta sin auth token y recibe otro challenge. Eso gasta un round trip y una firma, pero no rompe nada.
Dos detalles muestran hacia dónde miraban los autores. Primero, todos los ejemplos de 402 en -11 usan WWW-Authenticate: Payment, el scheme HTTP detrás de MPP, el protocolo de Stripe y Tempo. Ninguno muestra un header de x402. Segundo, el único flujo de 402 que -11 especifica paso a paso está en el token endpoint del access server. Ahí, el pago establece "a billing relationship" entre person server y access server, que "the PS caches per AS". Se parece más a abrir una cuenta que a pagar por llamada.
El draft Budgets mantiene separadas las dos condiciones a propósito. Un budget agotado se responde con 401 y requirement=auth-token, que significa "vuelve a tu person server". Un 402 significa que el recurso necesita dinero, no permiso. Y el 429 no se usa, porque un budget trata del costo de la próxima request, no de la frecuencia de requests.
TPX traza la línea en otro lugar. TPX es el perfil de OAuth 2.0 para grants de inferencia medida que Budgets cita como su contraparte en OAuth. Está desplegado en tokenpony.dev. Devuelve 402 con error.code: "budget_exhausted" cuando un grant se agota, y 402 con balance_exhausted cuando se vacía el saldo prepago de la persona. Dos drafts pensados para el mismo tipo de medidor no coinciden en el código de estado para "tu tope se agotó". Un cliente x402 que recibe un 402 de TPX va a buscar un challenge de pago que no existe. Describimos esa confusión en nuestro censo de 402 contra 429, y aquí aparece otra vez.
El medidor: reservar, confirmar, liberar
La sección de enforcement le va a resultar familiar a quien haya leído nuestro interior de reserve-proxy-settle. El budget es un tope duro: "A resource MUST NOT let metered consumption exceed the granted amount." El output se mide recién después de generarse, así que el recurso tiene que acotar cada request antes de servirla. El draft nombra el patrón: reservar el máximo, servir, confirmar el costo real, liberar la diferencia. También exige que "an operation with no finite cost bound MUST be given one, be truncated when the remainder is consumed, or be refused". En una llamada LLM, ese límite es max_tokens.
El agente ve el resultado en un header de respuesta, AAuth-Budget. Lleva remaining (obligatorio), cost de esta request, reserved con lo que sigue retenido, y required en un rechazo. Este último le dice al agente cuánto necesitaba la request rechazada:
HTTP/1.1 401 Unauthorized
AAuth-Requirement: requirement=auth-token;
resource-token="eyJ..."; reason=insufficient-budget
AAuth-Budget: remaining=150000, required=400000, unit="USD", decimals=6
// Al agente le quedan $0.15; esta llamada necesitaba hasta $0.40.
// Puede bajar max_tokens y reintentar con el mismo token, sin preguntarle a su PS.
El streaming es el caso difícil. Los headers se envían antes que el body, y el costo de una completion en streaming solo se conoce cuando termina el stream. La respuesta del draft es enviar reserved en el header y cost en un trailer HTTP, un header que se envía después del body:
HTTP/1.1 200 OK
Content-Type: text/event-stream
Trailer: AAuth-Budget
AAuth-Budget: remaining=1568800, reserved=431200, unit="USD", decimals=6
...stream...
AAuth-Budget: cost=221200
// saldo después = remaining + reserved - cost = 1,778,800 ($1.7788)
El draft da por hecho que los trailers a veces fallan. Un trailer solo puede agregar miembros, nunca repetirlos, así que no importa si el cliente mezcla los trailers con los headers o los descarta. Y "a recipient MUST NOT treat the trailer as necessary". Si no llega el trailer, el agente trata la request como si hubiera costado todo el reserved hasta que la siguiente respuesta lo corrija.
El draft también descarta la objeción principal contra los trailers. Dice que perderlos es "largely a browser property — fetch does not surface trailers — and the traffic this document governs is an agent calling a resource, which is server-to-server". Pusimos a prueba esa afirmación.
Hallazgo 1: la mayoría de los clientes de agentes nunca ve el trailer
Montamos un servidor local en Node.js 22.22.2 que sirve un stream SSE con la forma de OpenAI. Envía el header de arriba, el trailer AAuth-Budget: cost=221200 y un chunk final con usage. Habla HTTP/1.1 (chunked) y HTTP/2 sin cifrar. Luego leímos la respuesta con cada cliente y verificamos si el valor del trailer llegaba al código que llama.
Cliente ¿Trailer visible?
curl 7.81, HTTP/1.1 y HTTP/2 sí (se imprime con -i)
Go 1.27.1 net/http, HTTP/1.1 y h2c sí (resp.Trailer tras EOF)
Node node:http, node:http2 sí (res.trailers / evento 'trailers')
undici 8.11.2 request() sí (.trailers tras el body)
fetch global de Node 22 no
undici 8.11.2 fetch no
openai (npm) 7.23.0 no
requests 2.34.2 no
httpx 0.28.1, HTTP/1.1 y HTTP/2 no
httpx2 2.13.1 no
aiohttp 3.14.3 no
openai (PyPI) 3.19.2 no
// 16 configuraciones: 7 ven el trailer, 9 no.
// Todos los "no" recibieron igual el header y el chunk de usage.
La división es clara. Los transportes de bajo nivel exponen los trailers. Los clientes de alto nivel que usa el código de agentes en la práctica no lo hacen. Eso incluye el fetch nativo de Node en el servidor, todos los clientes Python habituales y los dos SDK oficiales de OpenAI. El SDK de npm está construido sobre fetch. La release actual en PyPI está construida sobre httpx2, que tampoco expone ningún atributo de trailer. Así que la objeción no es una rareza del navegador. Describe el stack de Python y JavaScript en el que se escribe la mayoría de los agentes.
Los dos SDK de OpenAI sí recibieron el usage en el chunk SSE final. Ese canal de capa de aplicación funciona en todos lados. El draft lo menciona y dice que un recurso que puede enviar ambos "SHOULD send both". En la práctica, el chunk es lo que va a leer el agente.
La única implementación en producción que nombra el draft llegó a la misma conclusión desde el lado del servidor. El camino de streaming de regent-httpsig tiene este comentario: "a streamed response's actual cost is known only when the stream ends, and this runtime sends no trailers". Usa el respaldo del draft, que el draft llama modo cost-omitted. Eso pone todo el peso sobre la fórmula de respaldo.
Hallazgo 2: la fórmula de respaldo cuenta dos veces la llamada siguiente
Cuando cost nunca llega, el draft le indica al agente que lo recupere de la siguiente respuesta:
cost = remaining anterior + reserved - remaining actual
El argumento es que remaining siempre descuenta las reservas. Es cierto. Pero eso también significa que el remaining de la siguiente respuesta ya descuenta el cargo o la retención de la siguiente request. La fórmula, tal como está escrita, le atribuye ese consumo a la request anterior.
Lo verificamos con el propio medidor de Regent (InMemoryMeter en regent-httpsig 0.6.0, ejecutado con Python 3.12). Le dimos a un token un budget de $2.00 e hicimos dos requests en serie. La request A fue en streaming, con una reserva de $0.4312 y un costo real de $0.2212.
// B es una llamada sin streaming que cuesta $0.05
header A : remaining=1568800, reserved=431200
header B : cost=50000, remaining=1728800
draft : 1568800 + 431200 - 1728800 = 271200 // real 221200, error 50000
// B también es en streaming, con reserva de $0.4312
header A : remaining=1568800, reserved=431200
header B : remaining=1347600, reserved=431200
draft : 1568800 + 431200 - 1347600 = 652400 // real 221200, error 431200
Un agente que hace streaming en todas las llamadas, que es el caso normal en inferencia, lee casi tres veces el costo real. El error siempre va en la dirección conservadora, así que el budget no puede sobregastarse. Pero la cifra por llamada que el agente registra, asigna a una subtarea o le muestra a su operador está mal. La corrección es un término más: restar el cost propio de la siguiente respuesta, o su reserved cuando se omite cost. Los dos valores están en ese header. Con la corrección, las dos corridas dan exactamente 221,200.
Hay una segunda consecuencia. La última llamada en streaming de un token no tiene una respuesta siguiente con ese token. El agente nunca puede recuperar su costo. Solo el person server puede hacerlo, más tarde, desde el usage endpoint.
Hallazgo 3: el precio está en el body, y el body no va firmado
El perfil de firma de AAuth, en la sección 11.3.3.1, exige que el agente cubra cuatro componentes: @method, @authority, @path y signature-key. Exige content-digest y content-type solo en requests con body hacia un person server, un access server o un endpoint de revocación. Un recurso puede pedir más cobertura con un campo de metadata, additional_signature_components.
En una llamada de inferencia medida, todo lo que fija el precio está en el body: model, max_tokens, los mensajes. El draft Budgets calcula la reserva justamente a partir de ese límite, "a maximum output length". Con el perfil por defecto, la firma prueba qué agente envió un POST a /v1/chat/completions. No prueba qué pidió ese agente.
TLS protege el body en tránsito, así que la exposición está en cualquier salto que termine TLS y reenvíe la request: una CDN, un proxy corporativo, una capa de logging en el propio stack del agente. Ese salto puede cambiar el body y conservar una firma válida. Una request capturada también se puede reproducir con otro body dentro de la ventana de firma de 60 segundos, salvo que el recurso use la caché de replay que el perfil deja como opcional. En los dos casos, el budget paga la request que llegó, no la que firmó el agente.
La solución ya existe y cuesta una línea. El ejemplo de metadata de recurso del propio draft base termina con "additional_signature_components": ["content-type", "content-digest"]. Pero el ejemplo de metadata de inference.example en el draft Budgets no lo incluye. Su request de ejemplo al authorization endpoint cubre solo los cuatro componentes por defecto. Lo mismo pasa con la metadata del despliegue en producción que veremos abajo. El draft ya exige content-digest en el usage endpoint y en las respuestas de uso firmadas. Debería exigir lo mismo para la request medida.
Hallazgo 4: el despliegue de referencia va detrás de la spec
El draft Budgets dice que Regent Protocol "is in production at get4agent.com". Su middleware, regent-httpsig, es Apache-2.0 y está en PyPI, con ocho releases entre el 17 de agosto y el 8 de septiembre. Descargamos la metadata de get4agent.com a las 09:04 UTC del 27 de septiembre:
GET /.well-known/aauth-resource.json
{
"resource": "https://get4agent.com",
"jwks_uri": "https://get4agent.com/.well-known/jwks.json",
"budget_units": [{ "unit": "USD", "decimals": 2, "max": 100000,
"description": "Marketplace calls, prepaid balance minor units." }],
"usage_endpoint": "https://get4agent.com/v1/budget/usage",
"revocation_endpoint": "https://get4agent.com/v1/budget/revoke"
}
GET /.well-known/jwks.json
{ "keys": [{ "kty": "OKP", "crv": "Ed25519", "alg": "EdDSA", ... }] }
Según -11, un verificador tiene que rechazar esta metadata. La sección 11.2 dice que un documento sin issuer "MUST be rejected with issuer_missing". Aquí el campo se llama resource, la forma de RFC 9728 que AAuth decidió explícitamente no usar. El alg de la clave es el polimórfico EdDSA, que la sección 11.3.1 dice que "MUST NOT be used" desde que la revisión -10 adoptó Ed25519 de RFC 9864. En comparación, el recurso de prueba del propio proyecto AAuth en whoami.aauth.dev publica issuer, access_mode y una clave Ed25519, como exige el draft.
La librería va detrás del draft de la misma forma. Su opción de algoritmos estrictos, require_fully_specified_algs, viene desactivada por defecto y se describe como "a transition affordance for the -10 ecosystem". La versión 0.5.1 agregó un challenge que lleva un registro final de consumo para un auth token vencido. El 13 de septiembre, el draft Budgets eliminó ese challenge porque "the base protocol does not permit" que un recurso acepte un token vencido. La release 0.6.0, del 8 de septiembre y todavía la más reciente, lo incluye.
Nada de esto sorprende en un draft exploratorio que cambia cada semana. El despliegue también hace algunas cosas bien. Su usage endpoint rechazó nuestro POST sin firmar con un mensaje que pide una firma jwks_uri "covering content-type + content-digest". Sus decimals de 2 son razonables para llamadas de marketplace con precio en centavos. Para inferencia, el draft argumenta a favor de 6: un decimal de structured field no puede representar $0.000015, el precio de un solo token a $15 por millón, y lo serializaría como 0.000.
El lado del agente va todavía más atrás. Los paquetes JavaScript de Hellō que revisamos (@aauth/agent 4.1.1, @aauth/fetch 4.0.0, @aauth/protocol 2.0.0 y @aauth/resource 3.0.0) leen la anotación R3 x-aauth-budget de un documento OpenAPI. Ninguno parsea el header AAuth-Budget ni maneja un 402.
Detalles menores que importan
El formato numérico está elegido con cuidado. Los montos son enteros porque un número JSON solo es exacto hasta 253 y un entero de structured field está limitado a 15 dígitos. El tope es entonces 999,999,999,999,999 unidades, unos $1,000 millones con seis decimales. El draft advierte que "if assets requiring 18 decimal places come into scope, both carriers break" y los montos tendrían que ser strings, como en x402. Un budget en USD con micro-dólares entra con holgura. Un monto contado en un token de 18 decimales no.
El person server tiene su propia vista. Un recurso medido puede publicar un usage_endpoint. El person server o el access server lo consulta con un POST firmado. La respuesta da contadores de calendario (día, semana, mes, año, total), siempre en UTC, un esquema tomado de Stripe Issuing. También puede dar totales por clave para las claves de firma que nombre el person server. Firmar la respuesta es recomendado, para que el recurso no pueda darle un número al person server y otro al que factura.
El gasto desconocido cuenta como gastado. Si una asignación vence y nadie reporta su consumo, el emisor "MUST account for the allocation as fully consumed" hasta que llegue una cifra. Es la misma regla conservadora que se le aplica al agente después de un stream cortado.
Las tools MCP pueden declarar que consumen budget. R3, el draft complementario para describir operaciones, agrega una anotación booleana de budget. En las tools MCP vive en el _meta de la tool como aauth.dev/budget. En OpenAPI es x-aauth-budget. Un agente que lee la lista de tools sabe qué llamadas van a necesitar un auth token con fondos antes de hacer la primera.
El saldo es público para cada salto. AAuth-Budget no va firmado y viaja en claro por encima de TLS. Los intermediarios "MUST NOT add, alter, or remove" el header, pero pueden leerlo. El draft limita la exposición al no enviar nunca una cifra acumulada. Cada respuesta revela el precio de una llamada y lo que queda de una asignación.
Qué significa para LLM4Agents
AAuth Budgets describe nuestro producto desde afuera. Vendemos inferencia medida a agentes autónomos. Reservamos el peor caso, hacemos streaming de la respuesta y liquidamos el costo real. Ya informamos costo y saldo restante en headers de respuesta en las llamadas sin streaming. El draft propone un nombre y un formato estándar para todo eso, y agrega algo que no tenemos: un tercero, el servidor de la persona, que decide cuánto puede gastar cada agente.
También separa tres cosas que nuestro modo walk-up combina. En el walk-up con x402, el pago es la autorización: el agente firma una transferencia EIP-3009 y la llamada pasa. AAuth divide el trabajo en identidad (un agent token firmado en lugar de una API key), permiso para gastar (una asignación en un auth token, dimensionada por el person server) y pago (un 402, vía x402 o MPP). Para un agente único que paga lo suyo, x402 solo es más simple y debe seguir así. Para una empresa que corre muchos agentes con una sola cuenta, esa división es lo que va a pedir el equipo de finanzas. El límite de gasto le pertenece al servidor de la empresa, no a la wallet de cada agente.
El draft también deja explícitamente fuera un tipo de despliegue: "AP-bundled inference", donde el proveedor del agente paga su inferencia. "This is the common deployment today." El caso para el que está construido el draft es un agente que gasta contra la propia cuenta de inferencia de la persona. Eso es un gateway como el nuestro, donde el titular de la cuenta no es el agente. Si los person servers se vuelven comunes, un gateway que solo ofrece API keys y saldos prepagos será uno que los compradores empresariales no pueden supervisar.
Los hallazgos definen cómo deberíamos implementarlo. El trailer no puede ser nuestro canal principal de costo, porque los SDK que usan nuestros usuarios no lo leen. Nuestras reservas ya salen de max_tokens, así que un body sin firmar le permitiría a un proxy cambiar el precio. Y la fórmula que los agentes van a copiar del draft está mal por un término. Si resolvemos esto bien, los agentes en nuestro gateway reciben cifras correctas desde la primera llamada.
El riesgo principal es el momento. El protocolo base cambia de forma cada pocas semanas. El draft Budgets todavía no es un documento del IETF, y el único despliegue en producción ya falla las validaciones de metadata de la revisión actual. Construir toda la escalera ahora significaría reconstruirla. Construir la parte que coincide con lo que ya hacemos es barato.
Cómo mantenerse en la frontera
Seis pasos, en orden.
1. Aceptar agent tokens de AAuth como alternativa a las API keys. Es el modo agent identity, el primer peldaño. No necesita person server ni access server. Verificar solo Ed25519 y ES256, rechazar EdDSA, aplicar la ventana de 60 segundos y mantener la caché de replay. Publicar /.well-known/aauth-resource.json con issuer, access_mode y additional_signature_components: ["content-type", "content-digest"], para que cada POST al gateway vaya firmado sobre su body. Así un agente podría registrarse haciendo su primera llamada firmada.
2. Implementar Budgets en /v1/chat/completions, solo del lado del recurso. Declarar budget_units en USD con seis decimales. Indexar las reservas por el jti del auth token sobre el ledger de reserve-settle que ya tenemos. Devolver 401 con reason=insufficient-budget y required cuando una reserva no entra. Nuestra fórmula de reserva ya produce ese número.
3. Informar el costo en tres lugares. Poner reserved en el header AAuth-Budget de cada respuesta en streaming. Poner cost en el chunk final de usage, que leen los dos SDK de OpenAI. Enviar además el trailer para los clientes Go y curl que pueden usarlo. Documentar la fórmula de recuperación corregida en nuestros ejemplos de cliente.
4. Mantener x402 como rail de pago y declarar qué significa cada rechazo. Usar 401 con requirement=auth-token cuando se agota una asignación. Dejar 402 con PAYMENT-REQUIRED para "paga por llamada o fondea el saldo". Cuando quien llama firmó con AAuth, agregar AAuth-Requirement al mismo 402. Publicar este mapeo, porque TPX y AAuth ya no coinciden.
5. Exponer un usage endpoint firmado. Servir contadores de calendario en UTC y totales por clave desde el ledger de transacciones que ya llevamos. Eso es lo que le permite al person server de una empresa supervisar el gasto de sus agentes sin raspar dashboards.
6. Llevar los datos upstream y seguir los drafts. Nuestros resultados sobre trailers y la corrección de un término en la fórmula corresponden al issue tracker de dickhardt/AAuth, junto con una propuesta para exigir content-digest en requests medidas. Después, seguir tres eventos: el primer envío al datatracker de draft-hardt-aauth-budgets-00, la próxima revisión del protocolo base, y si TPX saca su rechazo por budget del 402.
x402 respondió la pregunta "¿cómo paga un agente?". AAuth Budgets es el primer intento serio de responder "¿cuánto puede gastar este agente, y quién lo decide?". Las dos piezas se juntan en el 402. El gateway que implemente ambas, con los detalles bien resueltos, será el que las empresas elijan para correr sus agentes.
Inferencia medida con un medidor que tu agente puede leer
API compatible con OpenAI, facturación con reserva y liquidación, pagos por llamada en USDC vía x402 y fallback automático de modelos.
Registrar un agente