Observe Execution

Hypergraph's event system lets you observe graph execution without modifying your workflow logic. Pass event processors to runner.run() or runner.map() to receive events as they happen.

Rich Progress Bars

The fastest way to observe execution — hierarchical progress bars powered by Rich.

pip install 'hypergraph[progress]'
from hypergraph import SyncRunner, RichProgressProcessor

runner = SyncRunner()
result = runner.run(graph, inputs, event_processors=[RichProgressProcessor()])

Output:

📦 my_graph ━━━━━━━━━━━━━━━━━━━━ 100% 3/3
  🌳 inner_rag ━━━━━━━━━━━━━━━━━ 100% 2/2

Works with map() too — failed items are tracked automatically:

results = runner.map(graph, {"url": urls}, map_over="url",
                     event_processors=[RichProgressProcessor()])
🗺️ scrape_graph Progress ━━━━━━━ 100% 50/50 (3 failed)
  📦 fetch ━━━━━━━━━━━━━━━━━━━━━ 100% 50/50
  📦 parse ━━━━━━━━━━━━━━━━━━━━━  94% 47/50

Non-TTY Fallback (CI and Piped Logs)

RichProgressProcessor auto-detects whether stdout is a TTY:

  • TTY: live Rich progress bars (default terminal experience)

  • Non-TTY (CI, redirected output): plain-text progress logs

In non-TTY mode, map runs log milestone progress at 10%, 25%, 50%, 75%, and 100%:

You can override auto-detection for testing/debugging:

OpenTelemetry Export

Use OpenTelemetry when you want Hypergraph runs to show up in external observability backends such as Jaeger, Honeycomb, Datadog, or Logfire. Hypergraph's native inspect UI, RunView, failure display, and checkpoint tools remain the primary debugging experience; OTel is the export layer.

Hypergraph emits:

  • Run spans for graph and map() scopes

  • Child node spans for node execution

  • Span events for supersteps, routing, cache hits, pauses, stops, forks, resumes, and retries

  • Explicit attributes such as workflow_id, run_id, item_index, graph_name, node_name, and batch summary counts

Typical hierarchy:

Mapped work uses a parent map span plus child graph spans per item:

Parent map spans export aggregate outcome attributes instead of vague blobs:

  • hypergraph.batch.total_items

  • hypergraph.batch.completed_items

  • hypergraph.batch.failed_items

  • hypergraph.batch.paused_items

  • hypergraph.batch.stopped_items

  • hypergraph.batch.outcome

Rich native debugging data stays inside Hypergraph on purpose:

  • Raw inputs and outputs

  • Checkpoint snapshots

  • Streamed chunks

  • Inspect-only UI payloads

Custom Event Processors

Collect All Events

Use EventProcessor to receive every event:

Handle Specific Event Types

Use TypedEventProcessor to handle only the events you care about:

Async Processors

For async runners, use AsyncEventProcessor:

The async runner calls on_event_async when available, falling back to on_event for sync processors. You can mix sync and async processors in the same list.

Multiple Processors

Pass multiple processors to observe different aspects simultaneously:

Real-World Example: Logging Execution History

Real-World Example: Route Tracing

Track which paths your routing nodes take:

Error Handling

Event processors use best-effort delivery. If a processor raises an exception, the error is logged but execution continues uninterrupted. This ensures observability code never breaks your workflow.

See Also

Last updated