Observers¶
The event observation system — how Pynchy emits events and how plugins subscribe to persist or process them. Use this page to build monitoring, analytics, or debugging tools for your Pynchy installation.
Observers are pluggable. The built-in observer stores operational events to SQLite, including a bounded evidence projection for live agent traces. The LiteLLM gateway exports metadata-only LLM traces to Phoenix; prompt and response content is disabled at the generated proxy configuration boundary.
Event Bus¶
Pynchy uses a small asyncio event dispatcher. Components emit events during normal operation, and observers subscribe to the event types they care about.
Design properties:
- Fire-and-forget — emission is non-blocking (creates async tasks)
- Type-based subscription — listeners subscribe to specific event types, not all events
- Error isolation — listener exceptions are logged but don't propagate to the emitter
Event Types¶
| Event | Fields | Emitted when |
|---|---|---|
MessageEvent | chat_jid, sender_name, content, timestamp, is_bot | A message is stored (inbound or outbound) |
AgentActivityEvent | chat_jid, active | An agent starts or stops processing |
AgentTraceEvent | chat_jid, trace_type, data | Agent emits a trace (thinking, tool use, intermediate text) |
ChatClearedEvent | chat_jid | Chat history is cleared |
Events are emitted from the message pipeline (session_handler, message_handler, output_handler).
Observer Contract¶
Plugins implement the pynchy_observer hook and return an object with:
| Attribute / Method | Type | Description |
|---|---|---|
name | str | Observer identifier (e.g., "sqlite", "otel") |
subscribe(event_bus) | (EventBus) → None | Attach listeners to the event bus |
close() | async () → None | Async teardown — unsubscribe and flush |
Multiple observers can coexist — each subscribes independently to the event bus during startup and is closed gracefully during shutdown.
Built-in: sqlite-observer¶
Persists operational events to a dedicated events table in the main SQLite database.
What it stores: message summaries, agent activity, and chat-clear events. Message content is truncated to 500 characters. For AgentTraceEvent, SQLite stores tool names, bounded tool inputs, bounded tool results, and bounded text. The observer removes control characters, replaces detected credentials and personal identifiers with irreversible redaction markers, limits collection depth and size, and omits payload bodies for thinking, system, and input trace types. The security Cop reads only the projected tool names, not tool inputs or results.
Use this SQLite projection for a bounded operational evidence packet. Use Phoenix for token, cost, timing, model, and provider-request metadata without prompt or response bodies.
Indexes: event type, chat JID, and timestamp — for querying event history by group or time range.
Want to customize this? Write your own observer plugin — see the Plugin Authoring Guide. Have an idea but don't want to build it? Open a feature request.