← Blog
26 de septiembre, 2026 · 19 min

¿Esperar o pagar? 402, 429 y Retry-After para agentes que pagan

Un agente que paga por llamada puede recibir dos tipos de rechazo. Un 402 significa "paga primero". Un 429 significa "espera". Revisamos el draft del IETF, el código de x402, cuatro SDK oficiales de LLM y la documentación de errores de tres proveedores, y enviamos requests sin pago a 1.951 vendedores x402. Pocos coinciden en qué rechazo es cuál, ni en cuánto hay que esperar.

Esto pesa más para un agente que paga que para una persona con una API key. Una persona que choca con un límite lee el error y se adapta. Un agente tiene que decidir solo, en cada rechazo, si paga, espera, cambia de proveedor o abandona. Si paga cuando debía esperar, gasta dinero para nada. Si espera cuando debía pagar, se queda detenido. Si reintenta un error de facturación, pierde tiempo y a veces un pago firmado. Si abandona ante un límite que se libera en quince segundos, pierde la tarea.

Nuestras fuentes, todas leídas el 26 de septiembre de 2026: draft-ietf-httpapi-ratelimit-headers-11; RFC 9110 y RFC 6585; el repositorio de referencia de x402 en el commit 4fcf836 (25 de septiembre); las versiones publicadas de los SDK de OpenAI y Anthropic para Python y TypeScript; y las páginas actuales de errores y rate limits de OpenAI, Anthropic y OpenRouter. Las mediciones salen del catálogo de discovery del Bazaar de x402, descargado a las 09:11 UTC, más un request sin pago a cada host listado. No hicimos ningún pago.

Dos códigos de estado, una decisión

HTTP define ambos códigos y dice poco de cualquiera de los dos. RFC 9110 le dedica al 402 una sola frase: "is reserved for future use". x402 es lo que el ecosistema construyó sobre esa frase. RFC 6585 define el 429 como "too many requests in a given amount of time". La respuesta MAY llevar un header Retry-After y "MUST NOT be stored by a cache". Retry-After es una fecha HTTP o un número entero de segundos.

Ninguno de los dos códigos le dice al cliente cuánta capacidad le queda. Años de headers ad hoc llenaron ese hueco: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset y muchas variantes. El grupo de trabajo HTTPAPI del IETF está estandarizando un reemplazo desde diciembre de 2020. La revisión -11 de RateLimit header fields for HTTP se publicó el 23 de mayo de 2026 y expira el 24 de noviembre. Sigue siendo un documento del grupo de trabajo y todavía no llegó al IESG.

El draft define dos campos estructurados. RateLimit-Policy describe la cuota y debería mantenerse estable entre respuestas. RateLimit informa lo que queda en este momento:

RateLimit-Policy: "burst";q=100;w=60,"daily";q=1000;w=86400
RateLimit:        "burst";r=37;t=18

// q = cuota, w = ventana en segundos, r = restante, t = segundos hasta que termina la ventana
// opcionales: qu = unidad de cuota, pk = partition key (una byte sequence)

Cuatro detalles importan para los agentes. Primero, los campos son pistas, no garantías. El cliente "MUST NOT assume that a positive available quota is a guarantee". Segundo, cuando vienen Retry-After y RateLimit juntos, manda Retry-After. Tercero, el draft registra tres problem types: quota-exceeded y abnormal-usage-detected con 429, y temporary-reduced-capacity con 503. Cuarto, el draft registra solo tres unidades de cuota: requests, content-bytes y concurrent-requests.

Ese último punto es el hueco para esta industria. Los proveedores de LLM limitan tokens por minuto, y los vendedores x402 limitan dinero. El draft no puede expresar ninguna de las dos cosas sin una nueva entrada en el registro o un parámetro con prefijo de vendor. Su apéndice sí nombra la "monetization" como una razón por la que los servidores usan cuotas, pero no define ninguna unidad para ella. El texto de la -11 además es inconsistente sobre la unidad por defecto: la sección 3.1.2 la llama requests, mientras que la tabla de IANA lista request. Un cliente que compara las unidades como strings exactos debería aceptar ambas hasta que se corrija.

Cómo dicen los proveedores "sin dinero"

Cuando el problema es de dinero y no de velocidad, tres upstreams habituales de los agentes responden de formas distintas. Esto sale de la documentación actual de errores y rate limits de cada proveedor:

rate limit
  OpenAI      429  + Retry-After cuando viene
  Anthropic   429  rate_limit_error + retry-after
  OpenRouter  429  + Retry-After cuando viene
límite de gasto que pones tú
  OpenAI      429  organization_spend_limit_exceeded / project_spend_limit_exceeded
  Anthropic   400  invalid_request_error
  OpenRouter  402  limit_source: openrouter_key_limit
tope que fija el proveedor
  OpenAI      429  organization_usage_limit_exceeded
  Anthropic   429  enforced_spend_limit_reached, sin retry-after
saldo prepago agotado
  OpenAI      429  credit_balance_exhausted
  OpenRouter  402  limit_source: openrouter_credits
datos de facturación o pago
  Anthropic   402  billing_error
gasto ya en curso
  OpenRouter  402  in_flight_budget_exhausted + Retry-After
sobrecarga
  OpenAI      503  server_is_overloaded
  Anthropic   529  overloaded_error
  OpenRouter  503  sin proveedor disponible / provider_overloaded

OpenAI usa 429 para todas las condiciones de dinero y las separa solo mediante error.code. Advierte que "the broader error.type can still be insufficient_quota". Su consejo es claro: "Retrying billing, spend, or quota errors won't restore API access". Su guía de rate limits agrega que Retry-After "does not mean that quota, billing, or other errors that require user action can be resolved by retrying".

Anthropic usa tres códigos para el dinero. Un límite de gasto que pones tú devuelve 400 invalid_request_error. Un problema con los datos de facturación devuelve 402 billing_error. Llegar al tope mensual de tu usage tier devuelve 429 con el mismo tipo rate_limit_error que un throttling común. La página de rate limits dice que el uso entonces "pauses until 00:00 UTC on the first day of the next month". También dice que la respuesta "has no retry-after header" y que reintentar, "including the SDKs' automatic retries, fails until access resumes". El campo que lo distingue es error.details.error_code: enforced_spend_limit_reached.

OpenRouter usa 402 para el dinero, que es lo más cercano a la lectura que hace x402 del código. Uno de sus 402, sin embargo, significa "espera". OpenRouter cobra cuando termina un request. Por eso retiene por adelantado un costo estimado: los tokens de entrada más los tokens de completion que permite max_tokens. Rechaza los requests nuevos cuya estimación no cabe junto a las retenciones vigentes. Ese 402 trae reason: in_flight_budget_exhausted y un header Retry-After. La documentación aclara que "none of them" (los SDK de OpenAI, Anthropic, Vercel AI y OpenRouter) "retries a 402 on its own". Quien leyó nuestro post sobre reserve-proxy-settle va a reconocer el diseño, porque es una reserva.

Así que un agente que enruta entre estos tres puede ver "sin dinero" como 400, 402 o 429. También puede ver "espera" como 402 o 429. Si se suma x402, un 402 también puede ser una oferta: un precio que el agente debe pagar en el acto. El código de estado por sí solo no le dice al agente qué hacer. Tiene que leer el body, y cada proveedor pone la razón en un campo distinto.

Lo que hacen los SDK en realidad

La mayoría de los agentes no interpreta estas respuestas por su cuenta. Lo hace el SDK del proveedor. Leímos el código de reintentos en las últimas versiones de los cuatro clientes oficiales: openai-python 3.19.2, openai-node 7.23.0, anthropic-sdk-python 1.8.0 y anthropic-sdk-typescript 0.128.0, todas publicadas entre el 22 y el 24 de septiembre de 2026.

En lo que importa aquí, los cuatro se comportan igual:

Donde difieren es en Retry-After. Los dos clientes de Python y el cliente de Node de OpenAI usaban la misma regla generada, que respetaba el header solo hasta 60 segundos. Este año los dos clientes de Python la cambiaron en direcciones opuestas:

versión del SDK                    respeta Retry-After  por encima del techo
openai-python 3.19.2               hasta 120 s          sin reintento, devuelve el error
openai-node 7.23.0                 hasta 60 s           backoff por defecto, 0,5-8 s
anthropic-sdk-python 1.8.0         hasta 4.294.967 s    (el techo es un límite de plataforma)
anthropic-sdk-typescript 0.128.0   hasta 2^31-1 ms      backoff por defecto, 0,5-8 s

El cambio de OpenAI en Python (#3555, mergeado el 30 de julio) explica su razonamiento. Las esperas de más de 60 segundos se estaban reemplazando por "a much shorter exponential delay". Por encima de dos minutos, el SDK ahora "surfaces the API error instead of blocking a synchronous worker". El cliente de Python de Anthropic fue en la dirección contraria el 12 de septiembre: "If the API asks us to wait a certain amount of time, just do what it says", con un tope de 4.294.967 segundos, unos 49,7 días. El cliente de Node de OpenAI sigue reemplazando en silencio cualquier valor de más de 60 segundos por una espera de 8 segundos como máximo. Ante el mismo Retry-After de 90 segundos, un SDK oficial espera 90 segundos y otro reintenta a los pocos segundos.

Aplica eso a la tabla de arriba. El credit_balance_exhausted de OpenAI es un 429, así que todos los clientes oficiales de OpenAI lo reintentan dos veces. La única forma de evitarlo es x-should-retry: false, y la página de códigos de error no dice si los 429 de facturación lo traen. El 429 de tope de gasto de Anthropic no trae retry-after, así que los clientes hacen backoff y reintentan dos veces, como su propia documentación advierte. Ninguno de los dos casos le cuesta caro a un agente con API key. Son unos segundos perdidos.

Para un agente que paga por llamada, el mismo reintento puede mover dinero. Los dos clientes de TypeScript aceptan un fetch personalizado, y la forma obvia de usar un gateway x402 desde ellos es pasarles wrapFetchWithPayment de @x402/fetch. Cuando el SDK reintenta después de un 429, el wrapper arranca de cero: un request sin pago, un 402 nuevo, una firma nueva con un nonce nuevo y un request pagado nuevo. Si eso le cuesta el doble al agente depende del vendedor, como muestra la sección siguiente.

x402 no tiene una palabra para "espera"

El transporte HTTP de x402 (specs/transports-v2/http.md) mapea los errores del protocolo a cuatro status: 402 cuando se requiere pago, 400 para un pago inválido, 402 otra vez cuando falla la verificación o el settlement, y 500 para un error del servidor. Nunca menciona 429, 503 ni Retry-After. El transporte MCP lleva el estado del pago en _meta y el transporte A2A lo lleva en la metadata de la tarea. Ninguno tiene una señal de throttling. La especificación central tiene un único código no terminal, settlement_pending, agregado el 17 de agosto en #3083. Cubre a un facilitator que difundió un settlement pero no pudo confirmarlo. No dice nada sobre un resource server ocupado.

El cliente de referencia sigue el mismo modelo. wrapFetchWithPayment devuelve sin cambios cualquier respuesta que no sea 402. Ante un 402 interpreta los requisitos, firma y reintenta una vez. No lee Retry-After ni reutiliza los requisitos entre llamadas. Por lo tanto, cada llamada pagada cuesta al menos dos requests HTTP: el request sin pago que recibe el precio, y el reintento pagado.

El servidor de referencia decide si un request limitado cuesta dinero. El middleware de TypeScript tiene tres payment flows. Con authorization, el flujo por defecto, verifica antes del handler, ejecuta el handler y hace el settlement después. Si el handler devuelve cualquier status de 400 o más, el adaptador de Express cancela el settlement con la razón handler_failed. Un 429 desde dentro del handler, entonces, no cuesta nada. Con upfront, el settlement ocurre antes de que corra el handler. Un 429 desde dentro del handler llega entonces después de que el USDC ya se movió. La auditoría del hueco de dos fases explica por qué los vendedores eligen upfront. El costo para el comprador aparece aquí. Un SDK que reintenta un 429 de un vendedor upfront vuelve a pagar en cada reintento.

La regla para los vendedores es simple. El lugar del limitador dentro del recorrido del request determina quién paga el throttling. Un limitador puesto antes del middleware de pago rechaza el request antes de verificar cualquier pago. Un limitador dentro del handler lo rechaza después de la verificación, lo cual es gratis con authorization y ya está pagado con upfront.

Lo que envían realmente 1.951 vendedores x402

Para ver qué hacen los vendedores en la práctica, descargamos el catálogo completo del Bazaar desde la API de discovery de CDP: 17.659 entradas en 2.028 hosts. Para cada host tomamos el recurso con más llamadas registradas, descartamos las rutas con plantillas y enviamos un request sin pago con el método que declara el catálogo. Eso dio 1.951 hosts. Después registramos todos los headers de rate limit de las respuestas.

censo del Bazaar de x402, 26 sep 2026, 09:13 UTC
hosts sondeados, un request sin pago c/u   1.951
respondieron 402                           1.903
  con header PAYMENT-REQUIRED              1.842
  con algún header de rate limit             163   (8,6%)
    RateLimit-Limit / -Remaining / -Reset     99
    RateLimit-Policy como "N;w=M"             99
    X-RateLimit-*                             54
    RateLimit: limit=, remaining=, reset=     10
    sintaxis actual ("name";q=;w= / r=;t=)     7
  con Retry-After en el propio 402             2

Menos de uno de cada once vendedores le dice algo al comprador sobre sus límites. Los que lo hacen usan en su mayoría una sintaxis que el IETF ya reemplazó. La forma más común, RateLimit-Policy: 120;w=60 con headers -Limit, -Remaining y -Reset separados, es el formato del draft-06 de diciembre de 2022. Es exactamente lo que envía express-rate-limit 8.7.0 cuando standardHeaders está en true. Siete hosts usan la sintaxis estructurada actual. Cinco de ellos llaman a su política "120-in-1min", "60-in-1min" y similares, que es el identificador por defecto de esa misma librería en su modo draft-8.

Los headers legacy no coinciden en lo que significan. X-RateLimit-Reset apareció en 39 hosts con tres significados incompatibles: 13 envían los segundos restantes, 23 un timestamp Unix en segundos y 3 un timestamp Unix en milisegundos. RateLimit-Reset fue una espera en segundos en 83 hosts y un timestamp ISO en uno. Si se suman los strings de duración de OpenAI (6m0s) y los timestamps RFC 3339 de Anthropic, un agente que lee headers de "reset" tiene que manejar cinco codificaciones de la misma idea.

Los dos vendedores que ponen Retry-After en el propio 402 muestran bien la ambigüedad. Uno envía Retry-After: 60 junto con remaining: 119 de 120. Es un precio con la instrucción de esperar un minuto, sobre una cuota casi llena. Un cliente que siga el consejo de OpenRouter de respetar Retry-After en los 402 se detendría sin motivo.

Los gateways de agentes son un subconjunto que vale la pena mirar. De los 21 hosts cuyo recurso sondeado era un endpoint /chat/completions o /v1/messages y respondió 402, 7 anuncian un límite. Los 7 usan headers legacy y ninguno usa la sintaxis actual.

Luego probamos si los límites anunciados se aplican al camino sin pago. Elegimos los 13 hosts que anunciaban una cuota de 20 requests o menos, uno por dominio, y le enviamos a cada uno su límite anunciado más dos requests sin pago, uno detrás de otro. Cuatro hosts pasaron de 402 a 429 exactamente en el request siguiente a su límite. Ocho siguieron respondiendo 402 más allá de él. Uno rechazó nuestro body vacío con un 400 antes de llegar al paywall. Tres de los cuatro 429 traían Retry-After (55, 55 y 49 segundos). El cuarto traía solo un reset en epoch Unix. Ninguno traía un header PAYMENT-REQUIRED.

En esos cuatro hosts, entonces, las consultas de precio sin pago cuentan contra la misma cuota que las llamadas pagadas. Si se combina con el patrón de dos requests del cliente de referencia, un límite anunciado de 10 por minuto permite como máximo 5 llamadas pagadas por minuto. El comprador no puede saberlo por los headers.

La idempotencia es la tercera pieza que falta

Reintentar un request pagado plantea una pregunta que los rate limits por sí solos no responden: ¿se ejecutó el primer intento? La respuesta general de HTTP iba a ser el header Idempotency-Key. Su draft del IETF llegó a la -07 el 15 de octubre de 2025 y expiró el 18 de abril de 2026 sin una versión nueva.

x402 tiene su propio mecanismo, la extensión payment-identifier, que cubrimos en nuestra auditoría de la capa de extensiones. El cliente envía un id de 16 a 128 caracteres. El mismo id con el mismo payload devuelve la respuesta cacheada, y el mismo id con un payload distinto devuelve 409. En el catálogo la declaran 1.946 entradas en 77 hosts, y 24 entradas en 23 hosts la hacen obligatoria.

La especificación no dice si una respuesta de error puede cachearse bajo un id, ni fija una vida útil para esa caché. Ese hueco importa para los rate limits. RFC 6585 dice que un 429 "MUST NOT be stored by a cache". Supón que un vendedor limita un request pagado y guarda el 429 bajo su payment-identifier. El cliente espera los 55 segundos que le indicaron, reintenta con el mismo id como pide la extensión y recibe el 429 guardado. Una espera corta se convirtió en una falla permanente para ese id.

Una función de decisión que un agente puede ejecutar

Mientras las especificaciones no converjan, el agente tiene que decidir por su cuenta. Abajo está el clasificador que pondríamos delante de cualquier agente que paga. code es la razón legible por máquina del proveedor: error.code en OpenAI, error.details.error_code en Anthropic, error.metadata.reason en OpenRouter. paid indica si esta respuesta contestó a un request que ya llevaba un pago.

type Decision =
  | { kind: 'pay'; requirements: string }
  | { kind: 'wait'; seconds: number }
  | { kind: 'backoff' }
  | { kind: 'failover' }
  | { kind: 'stop'; reason: string }

const MAX_WAIT_S = 120
const BILLING_CODES: ReadonlySet<string> = new Set([
  'credit_balance_exhausted', 'organization_spend_limit_exceeded',
  'project_spend_limit_exceeded', 'organization_usage_limit_exceeded',
  'enforced_spend_limit_reached',
])

function retryAfter(h: Headers): number | undefined {
  const v = h.get('retry-after')
  if (v === null) return undefined
  if (/^\d+$/.test(v.trim())) return Number(v)
  const at = Date.parse(v)
  return Number.isNaN(at) ? undefined : Math.max(0, (at - Date.now()) / 1000)
}

function classify(status: number, h: Headers, code: string | undefined, paid: boolean): Decision {
  const wait = retryAfter(h)
  const waitable = wait !== undefined && wait <= MAX_WAIT_S
  switch (status) {
    case 402: {
      const offer = h.get('payment-required')
      if (offer !== null && !paid) return { kind: 'pay', requirements: offer }
      if (waitable) return { kind: 'wait', seconds: wait }        // in-flight budget
      return { kind: 'stop', reason: paid ? 'payment_failed' : code ?? 'unfunded' }
    }
    case 429:
      if (code !== undefined && BILLING_CODES.has(code)) return { kind: 'stop', reason: code }
      if (wait === undefined) return { kind: 'backoff' }
      return waitable ? { kind: 'wait', seconds: wait } : { kind: 'failover' }
    case 503:
    case 529:
      return waitable ? { kind: 'wait', seconds: wait } : { kind: 'failover' }
    default:
      return status >= 500 ? { kind: 'failover' } : { kind: 'stop', reason: `http_${status}` }
  }
}

Tres reglas lo acompañan. Primero, desactiva los reintentos propios del SDK (maxRetries: 0) para que no se apilen dos loops de reintento. Segundo, después de cualquier intento pagado que falle, lee el header PAYMENT-RESPONSE antes de volver a firmar. Si ahí figura un settlement, el siguiente intento es una segunda compra. Tercero, reutiliza el mismo payment-identifier en los reintentos de una misma llamada lógica, y genera uno nuevo solo cuando el agente realmente quiere volver a comprar. El 400 de Anthropic por un límite de gasto propio cae por defecto en la rama stop, que es lo correcto. Si quieres distinguirlo de otros 400, la documentación da el prefijo del mensaje: You have reached your specified API usage limits.

Qué significa para LLM4Agents

Lo vemos desde los dos lados. Hacia arriba, somos clientes de proveedores que usan la tabla de arriba. La cadena de fallback ya convierte un 429 o un 5xx del upstream en otro modelo, y un eslabón fallido nunca se cobra. Por eso, la mayor parte del desacuerdo entre proveedores se detiene en nuestro gateway. Ese es el valor de un gateway: entran tres vocabularios de dinero y throttling, y debería salir uno.

Hacia abajo, somos vendedores, y nuestras respuestas tienen los mismos huecos que el Bazaar. El 26 de septiembre nuestro 402 de walk-up traía un header PAYMENT-REQUIRED con una sola opción exact en eip155:8453: 10000 unidades base de USDC (un centavo), maxTimeoutSeconds 300. No traía campos RateLimit ni Retry-After. Nuestro OpenAPI documenta un 429 para chat completions de 600 requests por API key por minuto. Menciona Retry-After, RateLimit e Idempotency cero veces.

Nuestro 402 además tiene dos significados. Es una oferta de walk-up o un insufficient_balance para un agente con Bearer. El segundo caso tiene la misma estructura que el in-flight budget de OpenRouter. La reserva retiene un monto de peor caso mientras corre una llamada, así que un agente que corre muchas llamadas en paralelo puede quedarse sin saldo temporalmente, y el problema se resuelve cuando se liquidan las retenciones. Hoy nada en la respuesta distingue ese caso de una wallet vacía.

El riesgo es concreto. Un desarrollador que apunta un SDK de TypeScript estándar de OpenAI o Anthropic a nuestro endpoint de walk-up a través de wrapFetchWithPayment va a reintentar nuestros 429 automáticamente. Cada reintento firma una autorización nueva. Si un intento limitado se liquida o no depende de dónde está nuestro limitador respecto al settlement, y nada en la respuesta le dice al agente en qué caso está. La oportunidad es igual de concreta. El gateway que responde con claridad "paga, espera o detente", en headers que los SDK estándar ya leen, tiene una ventaja fácil de explicar.

Cómo mantenerse en la frontera

1. Publicar en la sintaxis actual los límites que ya aplicamos. Enviar RateLimit-Policy: "per-key";q=600;w=60 y el RateLimit correspondiente en todas las respuestas, incluidos los 402 y los 429, y Retry-After en todos los 429. Omitir los headers legacy X-RateLimit-*, porque el censo muestra lo inconsistentes que son. El cambio es pequeño y nos pondría entre los siete hosts del censo que usan la sintaxis actual.

2. Usar la única señal que obedecen todos los SDK oficiales. Enviar x-should-retry: false en los rechazos que no se resuelven esperando: una wallet vacía o un error de facturación del proveedor que se propaga. Enviar x-should-retry: true con Retry-After en los que sí. Los cuatro clientes revisan este header antes que sus reglas de status. Los agentes que usan SDK estándar contra nuestro endpoint compatible con OpenAI dejarían de desperdiciar reintentos sin cambiar nada de su lado.

3. Dividir insufficient_balance en dos. Devolver reason: holds_outstanding con un Retry-After estimado a partir de la reserva abierta más antigua, y reason: wallet_empty sin pista de reintento. OpenRouter ya documentó este patrón, y los agentes están aprendiendo a manejarlo.

4. Evitar que el handshake de x402 reduzca el throughput a la mitad. Contar solo los requests pagados o autenticados contra la cuota por key. Medir los desafíos 402 sin pago en un bucket separado por IP. Los cuatro vendedores que limitaron su camino sin pago muestran qué pasa si no.

5. Soportar payment-identifier en walk-up, sin cachear errores. Atar cada id a un fingerprint de scheme, network, asset, amount, payTo y ruta. Repetir solo las respuestas exitosas. Nunca guardar un 4xx o un 5xx bajo un id.

6. Llevar los huecos a los estándares. Proponer una nota al transporte de x402 que defina 429 y 503 con Retry-After, y que obligue a los vendedores a rechazar los requests limitados antes del settlement. Preguntar al grupo HTTPAPI si una unidad de cuota tokens tiene lugar en el registro, ya que todos los proveedores de LLM limitan por tokens, y señalar la discrepancia request/requests de la -11. Mientras tanto, usar un parámetro con prefijo de vendor para declarar nuestros límites de tokens.

Con el tiempo, las especificaciones van a cubrir todo esto. Mientras tanto, cada rechazo que recibe un agente es una elección entre pagar, esperar y detenerse. Un vendedor que hace obvia esa elección recibe reintentos que puede manejar, en lugar de firmas repetidas y tareas detenidas.

Un gateway que le dice a tu agente cuándo pagar y cuándo esperar

API compatible con OpenAI, pago por llamada en USDC vía x402 o desde un saldo depositado, con fallback automático de modelos.

Registrar un agente