Ir al contenido

Ciclo de vida del despacho de agentes

Un despacho es una ejecución de un agente, en una conversación y sobre un adaptador. Todo lo relativo a él ocurre en cc_server: el cliente envía un mensaje y después observa cómo llegan los eventos en flujo. Ningún cliente tiene una ruta de despacho.

Los agentes se despiertan por seis motivos, que la ejecución lleva consigo como su contexto de activación para que el agente sepa por qué está activo:

Motivo de la activación Desencadenante
userMessage Alguien envió un mensaje en un espacio o mencionó al agente
assignment Se asignó un ticket al agente
pipelineStep Un paso de un pipeline lo despachó
childCompleted Un ticket hijo terminó
followUp Un latido de seguimiento programado
recovery La ruta de recuperación volvió a despachar tras un fallo

El contexto de activación lleva los identificadores que acompañan al motivo (ticket, espacio, mensaje, ejecución de pipeline) y se inyectan en el entorno y el prompt del agente.

El prompt se construye por capas, y cada una es una sección etiquetada:

  • Identidad: el id propio del agente, su nombre y el id del espacio de trabajo, con una instrucción explícita de pasar esos UUID exactos a las herramientas con alcance de espacio de trabajo. El espacio de trabajo es intrínseco al agente, así que siempre está presente.
  • Catálogo de herramientas y protocolos de recursos, y después la estructura del espacio de trabajo.
  • Anulación del prompt de sistema, si el agente tiene una, y después la persona (parametrizada por rol) y el informe del equipo.
  • Skills: los nombres configurados en el agente.
  • Contrato de ejecución y procedimiento del modo actual.
  • Contexto de activación y contexto de mención: quién convocó al agente y el conjunto de participantes que lo rodea.
  • Bloque de modo: se genera a partir del perfil de capacidades del modo y de su lista de herramientas materializada, así que un prompt nunca puede nombrar una herramienta que la ejecución no tenga realmente.
  • Contexto de memoria: hechos recuperados para la tarea.
  • Contexto de conversación: el historial reciente del espacio, limitado a una ventana literal de 50.000 caracteres, independientemente del tamaño de contexto configurado para el agente. El historial más antiguo no se descarta: el agente lo recupera a petición con get_messages, y los mensajes antiguos semánticamente relevantes siguen apareciendo.

Los comandos se reparten entre dos sitios. /todo y /compact se interceptan en el compositor y nunca se persisten deliberadamente como mensajes ni se envían al agente; persistir /compact retrasaría un turno el corte de compactación y ensuciaría la transcripción. /plan se trata en ambos: el compositor cambia el modo del espacio, que es lo que hace que la superficie de herramientas, el preajuste de las barandillas y el prompt concuerden en este turno y en todos los siguientes. /goal, /loop y /skill:<name> se gestionan dentro de la propia ejecución y solo en el arnés integrado: /goal y /loop inician trabajo autónomo con un presupuesto de coste, y un nombre con el prefijo skill: se busca como una skill cuyo cuerpo SKILL.md se convierte en la directiva del turno. El espacio de nombres es lo que mantiene separados ambos vocabularios: resolver un nombre sin prefijo contra las skills hacía que una skill llamada plan o compact quedara permanentemente eclipsada por la integrada. Un nombre sin prefijo que no sea integrado todavía se resuelve, para los mensajes escritos antes de que existiera el espacio de nombres. Un nombre no reconocido simplemente pasa como texto sin formato.

Antes de que se ejecute nada, la conversación obtiene su propia raíz de trabajo, con un worktree aislado con copy-on-write por repositorio debajo de ella. De forma predeterminada, eso es cada repositorio vinculado al espacio de trabajo; un espacio de PR (o un espacio creado con una selección explícita) aprovisiona solo los incluidos en la lista de permitidos, y una conversación de revisión de PR fija su único repositorio a la ref head de la pull request mientras los demás se quedan en su rama predeterminada. El checkout de origen nunca se modifica y todo el directorio de la conversación se recupera cuando se elimina el espacio.

El copy-on-write es la única implementación allí donde se distribuye rift, respaldada por el binario nativo incluido. Un sistema de archivos que no puede hacer reflink (o un directorio de datos en un volumen distinto al del repositorio) hace que el aprovisionamiento falle en lugar de recurrir a una alternativa. git worktree es el backend en Windows, donde no hay ningún backend de copy-on-write que construir, y no es una degradación silenciosa en otras máquinas. Que falte rift en una plataforma donde se distribuye es una instalación rota: el servidor se niega a arrancar en lugar de recurrir a una alternativa en silencio, porque una alternativa silenciosa esconde la avería detrás de una ruta más lenta para siempre.

Se resuelven dos identidades por ejecución, antes de que se lance ningún proceso.

Autoría de Git. Los commits que hace un agente se firman como el agente (<Name> (agent) <agentId@agents.control-center.local> tanto en GIT_AUTHOR_* como en GIT_COMMITTER_*), nunca suplantando a una persona. La parte local es el UUID del agente, no el slug de su nombre. La persona solicitante recibe crédito mediante un trailer Co-Authored-By:, que se transporta en el entorno y se indica en el prompt de sistema. Una identidad explícita definida por el llamador siempre prevalece sobre ambas.

Identidad ante el host de código. La credencial de GitHub de la ejecución es siempre la del bróker (un token de instalación de la App con alcance de repositorio, o su alternativa PAT del entorno), nunca el token propio almacenado de la persona solicitante. actingUserId delimita la alternativa PAT para que una persona que no sea la propietaria del servidor no herede su alcance; no superpone un token personal al entorno del agente.

Las credenciales de los proveedores de modelos se resuelven en un orden fijo, y el orden importa:

  1. una anulación del entorno por adaptador,
  2. el entorno del llamador,
  3. el almacén de credenciales del servidor (renovando un token OAuth si está cerca de caducar),
  4. el entorno del proceso.

Como la anulación por adaptador va primero, gana en silencio a una cuenta de proveedor conectada en la aplicación. Si una ejecución está facturando a la cuenta equivocada, esa anulación es el primer sitio donde mirar. Las credenciales de los proveedores son globales a la máquina: se comparten entre todos los espacios de trabajo de la instalación.

El token de GitHub de la ejecución viene del bróker de credenciales: un token de solo lectura con alcance del repositorio del worktree. Un push pasa por la pasarela de ejecuciones de agentes, que pregunta a la regla Enviar a un remoto antes de reenviarlo, y no se inyecta ninguna clave de tickets. Consulta Entorno aislado y seguridad.

La ejecución se lanza con su worktree como directorio de trabajo y, en el caso de Claude Code, con una configuración de MCP generada para que el agente pueda llegar a la superficie de herramientas de Control Center. ACP y el bash del arnés reciben un entorno saneado; Claude Code a través de NoSandboxAdapter hereda el entorno de la máquina.

La ejecución devuelve un flujo de eventos tipados, que el procesador de flujo persiste como deltas de mensajes, pliega en segmentos de transcripción y convierte en eventos de mensajería:

Evento Qué transporta
thinking Salida de razonamiento, representada en línea
text Salida visible
toolCall Una invocación de herramienta, con su id y argumentos estructurados
toolResult El resultado correspondiente, marcado cuando dio error o es un flujo parcial
usage Recuentos de tokens y coste para una ventana de medición
error Un error, con el código estructurado del adaptador cuando este lo comunicó
sandboxViolation El sistema operativo denegó una llamada al sistema. Solo se emite donde un entorno aislado envuelve realmente el proceso; consulta la nota anterior
debug Diagnóstico en tiempo de ejecución (marcadores de lanzamiento, decisiones de las barandillas, avisos del contrato)
done La ejecución terminó

Deliberadamente no hay ningún techo de turnos en ningún sitio. Un recuento fijo de iteraciones mata trabajo largo legítimo (migraciones, limpieza tras un fan-out) y no captura nada que las protecciones de abajo no capturen antes. Una ejecución termina cuando:

  • el modelo se detiene por sí solo;
  • una persona la detiene o toma el control de la conversación (lo que pausa el arnés integrado en su siguiente límite de turno limpio; en su lugar, una ejecución de Claude Code, que no tiene un límite seguro, se detiene);
  • salta el vigilante de silencio. Si no hay salida durante el umbral, la sesión se termina con un fallo silentRun. El valor predeterminado son 15 minutos, que bajan a 10 en los modos predominantemente de lectura (revisión y plan); un agente puede anularlo entre 1 y 240 minutos. El vigilante se arma cuando un proceso hijo informa de su PID, así que cubre la CLI de Claude Code, no el arnés integrado, que no lanza nada;
  • actúa un tope de coste, pero solo para los comandos autónomos.

La protección contra bucles infinitos no es un terminador: tras tres llamadas idénticas a herramientas seguidas, el bucle orienta al agente para que cambie de enfoque.

En conjunto, un turno interactivo normal en el arnés integrado no tiene techo de turnos, ni tope de coste, ni vigilante de silencio. Termina cuando el modelo se detiene o cuando lo detienes tú. Es una contrapartida deliberada (las alternativas matan trabajo largo legítimo), pero sí significa que una ejecución interactiva sin supervisión no está limitada por nada salvo el propio criterio del modelo.

A mitad de ejecución, un mensaje enviado a un agente en marcha se pone en cola como orientación y se consume en el siguiente límite de turno, así que puedes reconducir una ejecución sin matarla. La orientación, la pausa, los subagentes y el contrato de finalización son características del arnés integrado; Claude Code no tiene ninguna de ellas.

Cada despacho escribe un AgentRunLog: hora de inicio y de fin, resumen, recuentos de tokens y coste estimado (incluido el coste acumulado de los subagentes), adaptador y modelo, id de proceso y ruta del log, la conversación y cualquier ticket o ejecución de pipeline a la que pertenezca, además de dos campos de clasificación que concentran la mayor parte de la verdad.

  • Estado es grueso: pending, running, completed, error.
  • Vitalidad es la lectura más fina: alive, productive, completed, blocked, empty, looping, failed, stalled, dead.
  • Familia de errores agrupa los fallos de forma útil: transientUpstream, sandboxInfrastructure, budgetExceeded, processLost, silentRun, unknown.

Cerrar la ejecución publica AgentRunCompleted, y de él cuelgan muchas cosas: la acumulación de costes del pipeline, la reanudación de un paso de pipeline que esperaba a la ejecución, la finalización del ticket de respaldo, la asignación de una orquestación a un estado terminal, la decisión de continuar o detenerse del supervisor de objetivos, el rol de verificador y la evaluación de presupuesto posterior a la ejecución. La lista de presencia llega aparte, observando los registros de ejecución recientes en lugar del evento. La notificación «Agente finalizado» no está en esa lista: el evento se dispara cuando termina el flujo del proceso, antes de que se escriba la respuesta, así que la notificación es el MessageReceived del turno, que se publica en cuanto se persiste el mensaje.

La aplicación del presupuesto es una reacción, no una puerta. Cuando una ejecución termina, el evaluador compara el gasto del agente en lo que va de mes con su techo efectivo (una política de presupuesto vinculada, si existe; si no, la cifra mensual propia del agente; cero significa ilimitado). Cruzar el umbral suave registra un incidente de advertencia; agotar el presupuesto registra un incidente grave y cambia el estado del ciclo de vida del agente a paused en el organigrama. El despacho sigue aceptando trabajo de ese agente. Un disparador de pipeline BudgetThresholdCrossed puede iniciar trabajo de seguimiento a partir del mismo evento.

Cada registro de ejecución puede llevar un linaje de reintentos: un id de ejecución padre, un contador de intentos y un resumen de continuación. El árbol de ejecuciones de la conversación muestra el número de intento cuando no es cero. Un reintento desde el chat es un despacho nuevo con un registro de ejecución nuevo.