> ## Documentation Index
> Fetch the complete documentation index at: https://docs.befailproof.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Agentes personalizados

> Instrumenta trazas de agentes personalizados para que Failproof AI pueda reconstruir ejecuciones y detectar fallos.

Instrumenta trazas de un agente personalizado con `failproofai-sdk` para que Failproof AI pueda reconstruir cada ejecución, auditar su comportamiento y encontrar fallos respaldados por evidencia. El SDK escribe eventos estructurados para que el daemon de Failproof los envíe a Cloud. Requiere Python 3.10 o superior.

El rastreo hace que los agentes personalizados sean observables y auditables. Para bloquear una acción insegura antes de que se ejecute también se necesita un hook de aplicación en tu runtime.

<Info>
  Para aplicar políticas en un entorno con agentes personalizados, [contacta con Failproof AI](mailto:support@befailproof.ai). Te ayudaremos a mapear los límites de modelo, herramienta y ciclo de vida de tu runtime a hooks de política.
</Info>

<div style={{ position: "relative", width: "100%", paddingBottom: "56.25%", height: 0, overflow: "hidden", borderRadius: "12px", margin: "1.5rem 0" }}>
  <iframe src="https://www.youtube.com/embed/VWxukZc5k7s?rel=0&playsinline=1" title="Agent tracing with the Failproof AI Python SDK" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture; fullscreen" allowFullScreen style={{ position: "absolute", top: 0, left: 0, width: "100%", height: "100%", border: 0 }} />
</div>

## Instalar `failproofai-sdk`

El SDK se distribuye actualmente como un wheel privado. Contacta con tu representante de Failproof AI para obtener la versión actual y acceso de descarga.

```bash theme={null}
VERSION=<sdk-version>
pip install "./failproofai_sdk-${VERSION}-py3-none-any.whl"
python -c "import failproofai; print(failproofai.__version__)"
```

Con `uv`, descarga primero el wheel y ejecuta `uv add ./failproofai_sdk-${VERSION}-py3-none-any.whl`. Fija el wheel en un repositorio privado de artefactos o en el archivo de bloqueo de dependencias.

El paquete se instala como `failproofai-sdk` y se importa en Python como `failproofai`.

## Conectar el daemon de Failproof

<Tabs>
  <Tab title="Panel de control">
    1. Ve a **Admin → Keys** y crea una clave con `events:add`.
    2. [Conecta el daemon de Failproof a Cloud](/es/start/setup#connect-a-machine-to-cloud) en la máquina del agente.
    3. Ejecuta una sesión instrumentada y luego busca su ID exacto en **Observe → Events**.
    4. Ve a **Observe → Sessions**, selecciona el mismo entorno y abre la traza reconstruida.

           <img src="https://mintcdn.com/exosphere/WgPwQzedeDNwJBTy/images/dashboard/session-detail.png?fit=max&auto=format&n=WgPwQzedeDNwJBTy&q=85&s=7b5f022dd5c485565a8cd92b2e936235" alt="Una sesión de agente Python personalizado reconstruida como grafo de ejecución y traza de eventos ordenada." width="3200" height="2000" data-path="images/dashboard/session-detail.png" />
  </Tab>

  <Tab title="CLI">
    ```bash theme={null}
    failproofai config \
      --connect https://app.befailproof.ai \
      --token <events-add-key>
    failproofai config --status
    ```
  </Tab>
</Tabs>

## Instrumentar una ejecución completa

Llama a `configure()` una sola vez durante el inicio del proceso. Todas las llamadas a eventos son solo por nombre de parámetro y requieren un `session_id` y un `agent_id` estables.

```python theme={null}
import traceback
import uuid

import failproofai

failproofai.configure(environment="production")

session_id = uuid.uuid4().hex
agent_id = "checkout-agent"

failproofai.event.agent_start(
    session_id=session_id,
    agent_id=agent_id,
    goal="Resolve a failed checkout",
)

try:
    tool_call_id = uuid.uuid4().hex
    failproofai.event.tool_use(
        session_id=session_id,
        agent_id=agent_id,
        tool_name="lookup_order",
        tool_call_id=tool_call_id,
        input={"order_id": "ord_8421"},
    )
    result = {"status": "payment_failed"}
    failproofai.event.tool_result(
        session_id=session_id,
        agent_id=agent_id,
        tool_name="lookup_order",
        tool_call_id=tool_call_id,
        output=result,
    )
except Exception as exc:
    failproofai.event.error(
        session_id=session_id,
        agent_id=agent_id,
        error_type=type(exc).__name__,
        message=str(exc),
        traceback=traceback.format_exc(),
    )
    failproofai.event.agent_end(
        session_id=session_id,
        agent_id=agent_id,
        outcome="failed",
    )
    raise
else:
    failproofai.event.agent_end(
        session_id=session_id,
        agent_id=agent_id,
        outcome="success",
        summary="Escalated the failed payment",
    )
```

Emite `agent_start` una vez por actor. Para sub-agentes, reutiliza el `session_id` del padre, asigna a cada actor un `agent_id` distinto y establece `parent_id` como el **ID del agente** padre, no el ID de sesión.

## Referencia de configuración

```python theme={null}
failproofai.configure(
    base_dir=None,
    flush_interval=0.5,
    environment="production",
)
```

| Parámetro          | Comportamiento                                                                                 |
| ------------------ | ---------------------------------------------------------------------------------------------- |
| `base_dir`         | Directorio raíz de spool explícito. Tiene precedencia sobre todas las variables de entorno.    |
| `flush_interval`   | Segundos entre escrituras en segundo plano desde memoria a JSONL. Valor predeterminado: `0.5`. |
| `environment`      | Etiqueta de despliegue en cada evento. Por defecto es `dev`.                                   |
| `FAILPROOFAI_HOME` | Cambia la raíz de Failproof AI que contiene el spool `custom-agents`.                          |

El SDK escribe en el `base_dir` explícito cuando está definido. De lo contrario, utiliza el spool `custom-agents` del daemon de Failproof bajo `FAILPROOFAI_HOME` o `~/.failproofai`.

El SDK encola llamadas en memoria y escribe lotes en un hilo en segundo plano. También realiza un flush final a través del mecanismo `atexit` de Python. Para workers de vida corta, permite un cierre normal del intérprete; la terminación forzada del proceso puede provocar la pérdida de eventos que aún estén en memoria.

## Catálogo de eventos

Todos los métodos devuelven `None`. Los campos con valor `None` se omiten en lugar de escribirse como `null` en JSON.

| Método            | Campos requeridos además de la identidad | Campos opcionales                                                          |
| ----------------- | ---------------------------------------- | -------------------------------------------------------------------------- |
| `agent_start`     | —                                        | `goal`, `parent_id`                                                        |
| `agent_end`       | —                                        | `outcome`, `summary`                                                       |
| `agent_pause`     | `pause_id`                               | `reason`, `user_id`                                                        |
| `agent_resume`    | `pause_id`                               | `reason`, `user_id`                                                        |
| `model_request`   | —                                        | `model`, `messages`, `system`, `tools`                                     |
| `model_response`  | —                                        | `model`, `stop_reason`, `input_tokens`, `output_tokens`, `content`, `role` |
| `tool_use`        | `tool_name`, `tool_call_id`              | `input`                                                                    |
| `tool_result`     | `tool_name`, `tool_call_id`              | `output`, `error`                                                          |
| `hook_triggered`  | `hook_name`, `hook_id`                   | `trigger_event`, `input`                                                   |
| `hook_completed`  | `hook_name`, `hook_id`                   | `outcome`, `output`, `error`                                               |
| `error`           | `error_type`, `message`                  | `traceback`                                                                |
| `human_wait`      | `input_id`                               | `prompt`, `options`, `reason`                                              |
| `human_input`     | `input_id`                               | `response`                                                                 |
| `human_pause`     | —                                        | `reason`, `user_id`                                                        |
| `human_interrupt` | —                                        | `reason`, `user_id`, `at_step`                                             |

Usa `outcome="failed"`, `"error"`, `"timeout"` o `"rejected"` cuando una finalización deba contabilizarse como un fallo. Otros valores, incluido `"failure"`, no son clasificados como fallos por el backend actual.

## Reglas de correlación y duración

* Reutiliza el mismo `tool_call_id`, `hook_id`, `pause_id` o `input_id` para el evento de finalización correspondiente.
* El SDK calcula `duration_ms` para `tool_result`, `hook_completed`, `agent_resume` y `human_input`. Pasarlo manualmente a esos métodos lanza `ValueError`.
* Los IDs de herramientas y hooks comparten un mapa de pendientes a nivel de proceso. Hazlos globalmente únicos en sesiones concurrentes y entre ambos espacios de nombres; los IDs de proveedor o UUIDs son la opción más segura.
* Un par dividido entre procesos sigue correlacionándose en el backend, pero el SDK no puede calcular su duración dentro del proceso.
* El mapa de pendientes admite un máximo de 10.000 entradas y elimina la más antigua cuando se llena.

## Campos personalizados y payloads

Todos los eventos aceptan campos adicionales por nombre de parámetro. Usa valores compatibles con JSON cuando las consultas downstream necesiten estructura. Los tipos no compatibles como UUIDs, datetimes, decimales, conjuntos, bytes y objetos de modelo se convierten a cadena de texto por el escritor.

Los nombres personalizados reservados son `timestamp`, `session_id`, `agent_id`, `type` y `environment`. Los errores tipográficos en campos opcionales se aceptan como nuevos campos personalizados, así que revisa el JSON emitido si un campo estándar no aparece en Cloud.

## Entregar y verificar

<Tabs>
  <Tab title="Panel de control">
    En **Observe → Events**, verifica que `agent_start` exista primero y `agent_end` al final. Luego abre **Observe → Sessions** y confirma que los eventos de modelo, herramienta, persona, hook y error aparecen en el orden previsto. Usa el ID de sesión como clave principal para la resolución de problemas.
  </Tab>

  <Tab title="CLI">
    ```bash theme={null}
    failproofai flush --wait --timeout 60
    failproofai config --status
    fp sessions --since 1h --env production --session-id <session-id>
    fp events --since 1h --session-id <session-id> --full
    ```
  </Tab>
</Tabs>

Si Cloud está vacío, inspecciona `$FAILPROOFAI_HOME/custom-agents/events`; de lo contrario, revisa `~/.failproofai/custom-agents/events`. Los archivos JSONL confirman la emisión del SDK; un spool en crecimiento apunta a un problema de configuración o entrega del daemon, mientras que un spool vacío apunta a la instrumentación o al ciclo de vida del proceso.

## Prevenir fallos en un runtime personalizado

Usa los hallazgos de auditoría y las trazas vinculadas para definir la acción insegura, la evidencia requerida y la respuesta esperada. Una integración de aplicación personalizada debe exponer la acción antes de su ejecución, pasar su entrada estructurada al motor de políticas y aplicar la decisión resultante: allow, instruct o deny.

Escribe a [support@befailproof.ai](mailto:support@befailproof.ai) para diseñar y validar esta integración en tu runtime.
