Skip to main content

Instalación

Compatible con: crewai 1.13 a 2.0. La versión 1.13 fue la que introdujo started_event_id y normalizó el uso de tokens, dos características de las que depende el adaptador para emparejar eventos e informar tokens.

Instrumentación

instrument() registra un listener en el bus de eventos a nivel de módulo de CrewAI y suscribe un handler por clase de evento. Nada en tu crew, agentes, tareas o herramientas cambia.

Qué se registra

Una tarea no emite nada de forma deliberada. Una tarea de CrewAI es un subconjunto de la ejecución del agente que la ejecuta; emitir ambas duplicaría cada fila y las mostraría como hermanas. El id y nombre de la tarea viajan en los propios eventos del agente. Las operaciones de memoria y conocimiento se registran como herramientas, nombradas según la superficie a la que acceden, de modo que aparecen junto a tus herramientas reales donde puedes comparar su latencia. En un crew jerárquico, el anidamiento es lo que hace legible el trace:
CrewAI asocia una ejecución delegada al evento de herramienta delegate_work_to_coworker, no al manager directamente, por lo que el adaptador sigue ese enlace. Sin él, todos los agentes quedarían como hermanos entre sí y se perdería la estructura de delegación.

Ejemplo

El traspaso es visible en el trace: el span del analyst se cierra, el span del writer se abre, y ambos están dentro de un único span crew.

Nombra tus spans

agent_id proviene de Agent(role=...), lo que lo convierte en una faceta legible en el dashboard.
agent_id es una columna de baja cardinalidad. Un rol que contenga un id de ejecución o timestamp la degrada para todas las consultas. Si un rol parece un id, el adaptador lo rechaza y coloca el valor real en un campo de payload en su lugar.

Controla la sesión

Se resuelve en este orden, ganando el primer resultado:
  1. instrument("crewai", session_id=...)
  2. El scope de failproofai_sdk.session() que lo envuelve
  3. Un uuid4().hex generado, una vez por crew o flow
Envuelve el kickoff para controlarlo por ejecución:

Opciones

session_id es la única opción que lee este adaptador. Los prompts y completions siempre se registran, truncados al presupuesto de payload.

Human in the loop

CrewAI tiene dos superficies de human-in-the-loop, y ambas se registran con los mismos cuatro eventos. @human_feedback en un método de flow pasa por el bus de eventos de CrewAI: el runtime emite un evento antes de bloquearse esperando a una persona y otro después de recibir la respuesta. Task(human_input=True) no lo hace. Llama a input() dentro del propio proveedor de entrada de CrewAI y no emite ningún evento, por lo que el adaptador envuelve directamente ese proveedor — sin ello, toda la espera humana era invisible y se facturaba como tiempo activo del agente. En cualquier caso obtienes:
El par agent_pause a agent_resume es el único que alimenta el tiempo en pausa. Sin él, una espera humana de diez minutos se factura como diez minutos de tiempo activo del agente.
CrewAI no establece ningún id de correlación en ninguno de los eventos de human-feedback, por lo que el adaptador los empareja usando el nombre del flow y del método, recurriendo en su defecto a la pausa abierta más recientemente. Esto es correcto porque un prompt de consola bloquea la ejecución. Si construyes un proveedor de feedback concurrente, establece request_id en ambos eventos.
Dado que la ruta Task(human_input=True) es un wrapper alrededor del proveedor de entrada de CrewAI en lugar de una suscripción a eventos, se restaura al llamar a uninstrument() y vuelve a lanzar cualquier excepción que lance input(), incluyendo KeyboardInterrupt, sin modificarla.

Problemas comunes

Un role contiene un UUID, timestamp o sufijo por ejecución. Usa un rol humano estable y coloca el id específico de la ejecución en la descripción de la tarea.
El bus de eventos es asíncrono y kickoff() retorna antes de que terminen de ejecutarse los últimos handlers. Drénalo primero:
Esto es una característica de CrewAI, no del SDK.
agent_end fuerza el cierre de pausas abiertas pero no de herramientas ni modelos, por lo que una ejecución que muere dentro de una llamada a herramienta deja ese span abierto. El cierre normal cierra lo que quede abierto y lo marca como incompleto. Solo un SIGKILL lo deja colgado, porque nada puede ejecutarse.
Verifica en este orden: instrument() se ejecutó antes que kickoff(); hay un with failproofai_sdk.session(): alrededor; crewai es 1.13 o más reciente; FAILPROOFAI_SDK_STRICT=1 está definido, para que un hook degradado lance una excepción en lugar de ser silenciado.

Siguientes pasos

Cómo funciona

Pares, ids, ciclo de vida de sesión y entrega.

Leer un trace

Sigue la causalidad a través de la sesión que acabas de capturar.

Otros frameworks

LangGraph, LlamaIndex, Pydantic AI y agentes personalizados.