Instalación
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:
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
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:instrument("crewai", session_id=...)- El scope de
failproofai_sdk.session()que lo envuelve - Un
uuid4().hexgenerado, una vez por crew o flow
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:
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
El filtro de agentes tiene miles de entradas
El filtro de agentes tiene miles de entradas
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.Un test lee cero eventos, pero el dashboard los muestra
Un test lee cero eventos, pero el dashboard los muestra
El bus de eventos es asíncrono y Esto es una característica de CrewAI, no del SDK.
kickoff() retorna antes de que terminen de ejecutarse los últimos handlers. Drénalo primero:Una sesión aparece como activa indefinidamente
Una sesión aparece como activa indefinidamente
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.No se registra nada
No se registra nada
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.

