Every interesting thing a Runnable does — start, end, error, LLM token, tool call, checkpoint — flows through the sameDocumentation Index
Fetch the complete documentation index at: https://cognis.vasanth.xyz/llms.txt
Use this file to discover all available pages before exploring further.
Event enum. You attach consumers in two flavors:
Observer— a sync, broad-spectrum trait. Best for things like “log to stdout,” “push to a channel.”CallbackHandler— strongly-typed, per-event hook methods (on_llm_start,on_tool_end, …). Best for things like “translate to Langfuse spans.”
CallbackHandler is also usable as an Observer via HandlerObserver.
Observer
Fn(&Event) + Send + Sync is also an Observer thanks to a blanket impl, so quick uses don’t need a struct:
Attach to a run
Observers travel withRunnableConfig. They can be attached on construction or pushed into the observers field:
CallbackHandler
For richer integrations, implementCallbackHandler:
HandlerObserver(your_handler) to attach to RunnableConfig.
Built-in observer
cognis::observers::TracingObserver is a tiny stdout-printing observer good for local debugging:
Multiple consumers
Bundle handlers withCallbackManager (a HandlerBuilder builds one). The manager fans events out to every handler:
Event reference
| Variant | When |
|---|---|
OnStart / OnEnd | A Runnable started / finished. |
OnError | A Runnable returned Err. |
OnNodeStart / OnNodeEnd | A graph node started / finished. |
OnLlmToken | An LLM emitted a streaming token. |
OnToolStart / OnToolEnd | A tool call started / finished. |
OnCheckpoint | A graph engine persisted a snapshot. |
Custom { kind, payload, run_id } | A graph node emitted user-defined progress (ctx.write_custom). |
run_id correlates events from the same invocation; nested chains use parent_run_id automatically.
How it works
- Observers are sync, fan-out, and best-effort. A slow observer slows execution. Keep the work small or push to a channel.
- CallbackHandlers are async. They can do real I/O without blocking the engine.
- Order is propagation order, not strict global order. Two parallel branches emit events in their own threads; observers may see them interleaved.
run_idis set byRunnableConfig::default(). Reuse aRunnableConfig::with_parent_run_id(parent)to nest manually if needed.
See also
Trace with Langfuse
Wire the standard production exporter.
Cost tracking
Token counts and USD cost on every LLM call.
Streaming
Same events, returned as a stream instead.