Skip to main content
See exactly what your AI agents did in production: every agent run, tool call, model request, hook, and human intervention. The Failproof AI Observability Python SDK records that trail from inside your agent code so you can debug, audit, and evaluate what happened. Use it whenever you want Failproof AI Observability to observe your agents. Under the hood, the SDK writes structured events to local JSONL files, and the collector daemon picks them up and ships them to the platform automatically. You do not manage those files yourself.
Tip: New to Failproof AI Observability? This page is the complete SDK event reference.

Installation

The SDK is distributed to customers as a private wheel rather than from a public package index. Your onboarding covers how to obtain it, install it, and pin it — talk to your Failproof AI contact if you need access. Once it is installed, confirm you have it:
Prefer to let a coding agent do the whole integration? The Python SDK Agent Skill knows the install path, plans the instrumentation points, writes them, and verifies the events land.

Quick Start

Instrumenting a real call

In practice you wrap your existing agent code. Bracket a model call with model_request before and model_response after, so the two events span the real request and Failproof AI Observability can pair them:
Wrap tool calls the same way with tool_use and tool_result, reusing one tool_call_id across the pair. Here is what those events look like once they reach the dashboard, colour-coded by type and filterable by environment, agent, and session: The live Events stream, colour-coded by event type and filterable by environment, agent, and session

configure()

Call once before any event.* call. Safe to omit; defaults work out of the box. All arguments are keyword-only; pass them by name as shown above. When base_dir is None (the default), the SDK reads $AGENTEYE_HOME if set, otherwise falls back to ~/.agenteye. This matches the collector’s own resolution, so a single AGENTEYE_HOME env var configures the shared event spool for both the SDK and the collector.

Environment

Label every event with a deployment environment (production, staging, qa, canary, etc.). Set it once; the SDK attaches it to every event automatically. Option 1: via configure():
Option 2: via environment variable:
Priority: configure(environment=...) wins over the environment variable. If neither is set, defaults to "dev". The environment value appears as a first-class filter in the dashboard and is stored on the server for fast queries.
Warning: Environment values must not contain a literal , comma. The dashboard filters use comma-separated multi-select on the wire (?environment=prod,staging), so an environment named prod,blue would be split into two values. Events with comma-containing environments are rejected at ingest time.

Data and privacy

The SDK records only the fields you explicitly pass. Prompts, messages, tool inputs and outputs, and model content are captured solely because you hand them to an event.* call. Nothing is read from your process or captured implicitly. Any field you leave unset is omitted from the event entirely; it is not written to disk. That makes redaction your choice and your responsibility. If a prompt or tool payload contains PII or secrets you would rather not store, strip or mask it before you pass it to the event method.

Event Reference

Most events come in start/end pairs that share a correlation ID: tool_use and tool_result share a tool_call_id, hook_triggered and hook_completed share a hook_id, and human_wait and human_input share an input_id. Emit the start event, do the work, then emit the end event with the same ID. Failproof AI Observability matches the pair and computes duration_ms for you, so you never pass duration_ms yourself. A session's git-style execution graph beside its event timeline, reconstructed from the paired events, with the tool/model/hook breakdown panel All event methods require these two fields: All methods also accept arbitrary **kwargs for custom metadata (see Custom Fields).

event.agent_start()

Emitted when an agent begins work.

event.agent_end()

Emitted when an agent finishes work.

event.tool_use()

Emitted when an agent invokes a tool. Pair with tool_result; the SDK auto-computes duration_ms.

event.tool_result()

Emitted when a tool returns. Correlates with tool_use via tool_call_id.

event.model_request()

Emitted just before sending a prompt to an LLM.
messages entries accept either a plain string content or Anthropic-style list-of-blocks content. Sampling params (temperature, max_tokens, etc.) can be passed as extra kwargs.

event.model_response()

Emitted when the LLM returns a response.
content accepts either a plain string (generic providers) or a list of Anthropic-style content blocks. Tool calls live inside content as {"type": "tool_use", ...} blocks, with no separate tool_calls field.

event.hook_triggered()

Emitted when a hook fires. Pair with hook_completed; the SDK auto-computes duration_ms.

event.hook_completed()

Emitted when a hook finishes. Correlates with hook_triggered via hook_id.

event.error()

Emitted when an unhandled error occurs.

Human-in-the-Loop Events

Human-in-the-loop events give you oversight over the moments where a person steps into the agent’s execution (waiting for approval, providing input, pausing, or stopping the agent). They let you measure how long humans take to respond (the SDK auto-computes duration_ms on the paired events), audit who paused or interrupted an agent, and build approval and oversight workflows that surface in the dashboard.

event.human_wait()

Emitted when the agent pauses execution to wait for a human to provide input. Pair with human_input; the SDK auto-computes duration_ms (how long the human took to respond).

event.human_input()

Emitted when a human provides input and the agent resumes. Correlates with human_wait via input_id. duration_ms is auto-computed and must not be passed by the caller.

event.human_pause()

Emitted when a human actively pauses the agent (e.g. via a dashboard control). The agent is suspended but not terminated.

event.human_interrupt()

Emitted when a human actively stops the agent mid-execution. Unlike human_pause, the agent’s work is terminated rather than suspended.

Custom Fields

Any extra keyword arguments are appended to the event after the standard fields:
timestamp, type, and environment are reserved and raise ValueError (Reserved field names cannot be used as custom fields: [...]) if passed as custom fields. session_id and agent_id are required parameters on every event method and cannot be supplied a second time; Python raises TypeError if you do. Set the environment with configure(environment=...) (or the AGENTEYE_ENVIRONMENT variable) instead. Keep payloads as structured JSON when you want to query their fields. Values JSON does not natively support—such as datetimes, UUIDs, decimals, sets, bytes, or model objects—are converted to strings so recording continues safely.

How Events Are Written

Events are buffered in-process and flushed to disk every flush_interval seconds (default 500 ms). Each flush writes one JSONL file:
The collector watches this directory and uploads files automatically. You do not need to manage these files directly. Each file is written atomically: the SDK writes to a temporary file and then renames it into place, so the collector never sees a half-written file. A final flush also runs when your process exits, so events buffered in the last interval are not lost. If the collector is offline, events simply accumulate as files on disk and ship once it comes back.

Next steps

  • Event stream: watch these events arrive live, colour-coded and filterable by environment, agent, and session.
  • Sessions: see how the paired events reconstruct each agent run as an execution graph and timeline.