Mandatos de tarea
Un mandato de tarea es un permiso para una tarea, no para un pago. El agente lo pide una vez, por ejemplo «comprar 3 licencias de la API de búsqueda, máximo 300 USD, en 2 horas», y un owner o un admin lo aprueba una vez. Mientras está activo, los pagos de esa tarea que solo esperarían por el umbral de aprobación o por una regla de aprobación pasan sin volver a preguntar. Nunca levanta un tope, una denegación, una retención de seguridad ni el webhook de decisión.
¿Qué problema resuelve?
- Las tarjetas no pueden esperar. Stripe le da a Burnbound 2 segundos para contestar a una autorización de tarjeta. Un pago con tarjeta que necesita aprobación se rechaza con
approval_required, porque nadie puede aprobarlo en ese tiempo. Con un mandato aprobado antes, ese pago pasa. - La fatiga de aprobaciones. Una tarea con diez pagos por encima del umbral son diez aprobaciones de lo mismo. Con un mandato, una persona decide una sola vez sobre la tarea entera: para qué es, cuánto, con qué métodos y hosts, y durante cuánto tiempo.
- Pagos que el usuario no pidió. Un mandato es estrecho: un agente, unos métodos, hosts, comercios y destinatarios opcionales, un presupuesto y un final. Eso limita lo que puede llevarse un pago al que empujan al agente: si queda fuera del alcance, o choca con una retención de seguridad que el mandato nunca levanta, espera a una persona como siempre. Si queda dentro, el mandato lo cubre, así que deja el alcance tan estrecho como la tarea.
¿Cómo lo pide el agente?
Con la herramienta MCP request_mandate. Solo puede pedirlo la clave del propio agente (bb_agent_…), y solo para él.
| Campo | Obligatorio | Qué es |
|---|---|---|
purpose |
sí | Qué es la tarea, con las palabras del usuario, de 1 a 200 caracteres. Lo ve quien aprueba. |
methods |
sí | Los métodos de pago que cubre, de 1 a 20. Consulta ¿Qué métodos puede cubrir?. |
hosts |
no | Los hosts de vendedor que cubre, con la sintaxis de allowHosts: un host exacto (admite puerto) o *.example.com. Sin él: cualquier host permitido. |
merchantCategories |
no | Tarjetas: categorías de comercio de Stripe, como computer_software_stores. |
merchantCountries |
no | Tarjetas: países del comercio, en ISO 3166-1 alfa-2, como ES. |
payees |
no | A quién se paga: direcciones o ids. Sin él: a cualquiera. |
maxUsd |
sí | Lo máximo que puede gastar la tarea en total, en USD, como "300". |
maxPayments |
no | El número máximo de pagos que cubre, de 1 a 1000. Sin él: no se cuentan. |
durationMinutes |
sí | Cuánto dura la tarea desde que se aprueba, de 1 minuto a 7 días (10080). |
context |
no | Datos para quien aprueba, como un ticket o un pedido. Se muestran como declarados por el agente, sin verificar. |
Cada lista opcional lleva de 1 a 20 valores. Un filtro que pongas se tiene que cumplir: un pago que no tiene ese dato no queda cubierto. Un pago x402 no tiene categoría de comercio, así que un mandato con merchantCategories nunca cubre uno.
{
"purpose": "Comprar 3 licencias de la API de búsqueda para el informe del T4",
"methods": ["x402.exact"],
"hosts": ["api.example.com"],
"maxUsd": "300",
"maxPayments": 3,
"durationMinutes": 120,
"context": { "ticket": "OPS-1423" }
}
La respuesta lleva los mismos campos que get_mandate_status (mandateId, status, normalmente pending, remainingUsd, expiresAt…), además de next (lo que debe hacer ahora el agente) y, cuando el servidor MCP conoce la dirección del panel, mandateUrl: la página del mandato en el panel. Los clientes que admiten la elicitación en modo URL ofrecen esa página al usuario desde el chat, igual que con un pago retenido, y approvalPrompt dice qué pasó (opened, declined, cancelled, failed o unsupported). El texto de ese aviso es fijo: el importe y la duración, nunca el purpose del agente.
La petición se rechaza, y no se pide nada, cuando:
| Error | Por qué |
|---|---|
mandate_exceeds_caps |
maxUsd supera el tope diario del agente por los días que dura la tarea, redondeados hacia arriba. El error lleva maxUsd, lo máximo que puede pedir. |
mandate_queue_full |
El agente ya tiene 5 mandatos esperando una decisión. |
mandate_rejected_request |
La API rechazó la petición por otro motivo, que va en reason. |
¿Cómo sabe en qué estado está?
get_mandate_status con el mandateId devuelve status, maxUsd, spentUsd, remainingUsd, maxPayments, usedPayments, durationMinutes, decidedAt y expiresAt. El agente solo ve sus propios mandatos: el de otro agente aparece como mandate_not_found. Nunca ve quién decidió ni su nota.
| Estado | Qué significa |
|---|---|
pending |
Espera a una persona. Caduca con el plazo de aprobación de la organización (15 minutos por defecto). |
active |
Aprobado. Cubre pagos hasta expiresAt, que es el momento de la aprobación más durationMinutes. |
rejected |
Una persona lo rechazó. Los pagos de la tarea esperan cada uno su aprobación, como antes. |
expired |
Nadie decidió a tiempo, o se acabó el tiempo de la tarea. |
exhausted |
Se ha gastado maxUsd o se han hecho maxPayments pagos. Vuelve a active si se devuelve un pago cubierto. |
revoked |
Una persona lo paró. El siguiente pago de la tarea vuelve a esperar una aprobación. |
El tiempo cuenta desde la aprobación, no desde la petición: un mandato de 2 horas aprobado a las 10:00 acaba a las 12:00. Si el agente esperaba en el aviso del chat y el mandato se rechaza o caduca, request_mandate falla con mandate_rejected o mandate_expired. El agente no debe volver a pedirlo para la misma tarea salvo que el usuario lo diga.
¿Quién lo aprueba, lo rechaza o lo revoca?
Solo un owner o un admin de la organización, con sesión en el panel. La clave del agente no puede, y nada de lo que conteste el cliente MCP en el chat decide nada. Los members y los viewers ven los mandatos, con los botones desactivados y el motivo.
- Dónde: en la vista de aprobaciones hay una pestaña mandatos de tarea junto a pagos retenidos, y la página de cada agente tiene una sección mandatos de tarea. La página del mandato enseña el propósito tal como lo escribió el agente, el alcance, el presupuesto, la duración y el contexto declarado.
- Aprobar o rechazar un mandato
pending, con una nota opcional de hasta 500 caracteres. Aprobar pide confirmación. Si la organización ya tiene 20 mandatos activos, aprobar falla contoo_many_active_mandates. - Revocar un mandato
activeoexhausted. Se para en el acto; lo ya pagado sigue pagado. - Slack y email: un mandato nuevo se avisa como un pago retenido, por los mismos canales y con los mismos límites por hora: email en todos los planes y Slack en Team o superior. El mensaje lleva nuestro importe y nuestra duración en el titular, después el propósito y el alcance del agente como texto plano tras etiquetas fijas, y el contexto declarado como no verificado. Los botones Aprobar y Rechazar solo abren la página del mandato en el panel, donde confirmas con tu sesión.
¿Qué pagos cubre?
Un mandato solo convierte en permitido un pago que la política retendría por uno de estos dos motivos:
threshold: su importe está en el umbral de aprobación del agente o por encima;rule: una regla propia en vigor pide aprobación, la del agente, la de su subequipo o la de la organización.
Y solo si se cumple todo esto:
- el pago es del agente del mandato;
- su método está en
methods; - cumple todos los filtros que haya (hosts, categorías de comercio, países del comercio, destinatarios);
- su importe en USD cabe en
maxUsd − spentUsd; - queda algún pago, si hay
maxPayments; - el mandato está
activey no ha pasadoexpiresAt.
Si varios mandatos cubren un pago, se usa el que acaba antes. Un pago que no cabe espera una aprobación como siempre: el mandato no se parte ni se estira.
¿Qué no cubre nunca?
Un mandato nunca amplía la política. Todo esto se aplica igual que sin él:
- Las denegaciones: el máximo por pago, el tope diario, el subtope de una persona, los presupuestos de subequipo y de organización, y las reglas
limitydeny. El tope diario sigue valiendo para cada día de la tarea. - Las retenciones de seguridad: un 402 que parece contener instrucciones (
instruction_like_description), el primer pago a una dirección de cobro nueva (new_pay_to) y el primer pago a un host del catálogo (catalog_new_host). - El webhook de decisión: un pago que retiene tu webhook de decisión sigue esperando, aunque también lo retenga una regla.
De ahí sale el techo de maxUsd. Un mandato no puede reservar más de lo que el agente puede gastar en los días que dura: su tope diario por los días, redondeados hacia arriba, así que 2 horas cuentan como 1 día. Con un tope diario de 100 USD, un mandato de 2 horas pide como mucho 100 USD y uno de 3 días, como mucho 300 USD. Por encima, mandate_exceeds_caps dice el máximo.
¿Cómo se consume?
- Cada pago cubierto suma su importe en USD a
spentUsdy 1 ausedPayments, en el mismo paso en que se reserva el pago, así que dos pagos a la vez no pueden llevarse los dos lo último que queda. - Cuando
spentUsdllega amaxUsd, ousedPaymentsllega amaxPayments, el mandato pasa aexhausted. - Un pago cubierto que falla o caduca devuelve su importe y su pago. Un mandato
exhaustedvuelve aactive. - Si entre la decisión y la reserva otro pago se lleva lo que quedaba, o una persona lo revoca,
authorizecontestaagent_busyy el reintento vuelve a decidir con el mandato tal como está. Una tarjeta, en ese caso, se rechaza. fetch_paidystripe_refunddevuelven elmandateIdque cubrió el pago.
¿Qué métodos puede cubrir?
Cualquier método de pago del agente, con la misma política:
| Método | Qué es |
|---|---|
x402.exact |
Pago a una API por x402 |
mpp.tempo.charge |
Pago por MPP en Tempo |
card.stripe_issuing |
Tarjeta de Stripe Issuing |
action.stripe.refund |
Reembolso de Stripe, por el gateway |
action.stripe.credit |
Abono a un cliente de Stripe |
action.shopify.refund |
Reembolso de Shopify, por el gateway |
Un mandato no activa un método. El método también tiene que estar permitido para el agente en sus Métodos de pago (consulta ¿De qué formas puede gastar un agente?). Los mandatos están en todos los planes.
¿Qué queda en la auditoría?
Cada cambio de un mandato es un evento de auditoría con el agente, mandateId, status, maxUsd, spentUsd, methods y expiresAt:
| Evento | Cuándo |
|---|---|
mandate.requested |
El agente lo pidió. |
mandate.approved |
Una persona lo aprobó. Con quién fue y su nota. |
mandate.rejected |
Una persona lo rechazó. Con quién fue y su nota. |
mandate.revoked |
Una persona lo revocó. Con quién fue y su nota. |
mandate.expired |
Acabó solo: reason es ttl (nadie decidió a tiempo) o duration (terminó la tarea). |
mandate.exhausted |
Un pago agotó su presupuesto o sus pagos. |
En cada pago cubierto, payment.authorized lleva el mandateId, y el pago guarda qué mandato lo cubrió. La decisión de la política se guarda tal cual, la retención, así que la auditoría enseña a la vez lo que dijo la política y qué mandato dejó pasar el pago. Si falla un mensaje de Slack o un email sobre un mandato, approval.notification_failed indica el mandateId y el canal.