Events
BindAI uses events to expose important runtime activity without requiring application code to be tightly coupled to the component producing that activity. The event system is built around four core pieces:Event— the base event object.EventBus— a synchronous publisher/subscriber mechanism.ExecutionContext— the execution-scoped context that owns an event bus and execution ID.EventRecorderandEventTrigger— runtime utilities for recording and reacting to events.
Event Architecture
The basic flow is:EventBus.
Subscribers receive the event synchronously.
The event system does not require subscribers to know which component produced the event. They only need to subscribe to the relevant event name.
Event Objects
All BindAI events derive from theEvent base class.
The base event contains three pieces of metadata:
Payload
payload is a dictionary containing event-specific information.
It defaults to an empty dictionary.
Event-specific event classes may expose additional attributes alongside the payload.
Event ID
Every event receives a unique ID when it is created.uuid4().
Timestamp
Every event receives a UTC timestamp:Event name
Every event exposes a string name:EventBus subscriptions.
EventBus
EventBus is the central event publisher and subscriber mechanism.
- subscribing to an event name
- unsubscribing from an event name
- publishing events
- wildcard subscriptions
Subscribing to Events
Subscribe a callable to an event name:Publishing Events
Publish an event through the bus:publish() call.
Wildcard Subscriptions
The event bus supports the special event name:- recording events
- logging
- diagnostics
- general-purpose observability integrations
Unsubscribing
Remove a previously registered handler with:Handler Isolation
Event handlers are isolated from the publisher. The event bus invokes each handler inside atry/except block.
If a handler raises an exception:
- the exception is logged;
- the event bus continues processing the remaining handlers.
failing_handler does not prevent working_handler from being invoked.
This behavior is important for diagnostic and observability handlers because a faulty handler should not normally stop event delivery to other subscribers.
Framework Event Types
BindAI defines a collection of standard event names. The current event types include:
The event type definitions provide stable names that can be used by subscribers and integrations.
Agent Events
The core agent event types are:Model Events
Model interaction exposes two event types:Tool Events
Tool execution exposes:ExecutionContext
AnExecutionContext represents the context associated with one execution.
- execution state
- dependency container
- registry
- variables
- metadata
- execution data
Execution IDs
AnExecutionContext always has an execution_id.
execution_id. Event payloads are event-specific, and only events that include the field can be indexed by execution ID by EventRecorder.
EventRecorder
BindAI providesEventRecorder in the runtime package for lightweight in-memory event recording.
Recording Events
Once attached, events are recorded automatically:Reading All Recorded Events
Use:Reading Events for an Execution
If events contain anexecution_id in their payload, the recorder indexes them by execution.
Use:
execution_id are included in this execution-specific index.
Clearing Recorded Events
Remove all recorded events with:- the complete event list
- the execution-specific event index
Closing an EventRecorder
When the recorder is no longer needed:close() unsubscribes the recorder’s handler from the event bus.
The recorder therefore stops receiving newly published events.
Closing a recorder does not require destroying the event bus itself.
Recorder Lifecycle
A typical recorder lifecycle is:close() keeps it subscribed.
Thread Safety
EventRecorder protects its internal event collections with a lock.
Recording, reading, and clearing events therefore use synchronized access to the recorder’s internal state.
The recorder remains intentionally lightweight and stores events in memory.
It is not a persistent event database.
EventRecorder Example
A simple execution recording pattern is:EventTrigger
BindAI also provides an event-driven automation primitive:EventTrigger connects an event name to a callable target.
Create one with:
Attaching a Trigger
A trigger is not subscribed to the event bus until it is attached:attach() more than once does not create duplicate subscriptions.
Detaching a Trigger
Detach a trigger with:detach() when the trigger is already detached is safe.
Enabling and Disabling a Trigger
Triggers are enabled by default. Disable a trigger with:Disabled Triggers
Disabling a trigger does not unsubscribe it from the event bus. Instead, the trigger remains attached but ignores incoming events while disabled. This makes it possible to temporarily pause a trigger:detach() when the trigger should no longer be connected to the event bus.
EventTrigger Example
A complete example:model.responded events published through bus.
To temporarily disable it:
EventBus vs EventTrigger
EventBus and EventTrigger solve different parts of the event system.
EventBus
UseEventBus when application code needs to:
- publish events
- subscribe handlers
- unsubscribe handlers
- observe multiple event types
- register wildcard handlers
EventTrigger
UseEventTrigger when an event should activate an automation target and the trigger needs an explicit lifecycle:
EventBus.
Event Handling Patterns
Logging
A wildcard subscriber can provide simple event logging:Targeted monitoring
Subscribe only to the event of interest:Execution recording
Attach anEventRecorder:
Automation
Attach anEventTrigger:
Keeping Event Handlers Lightweight
Event handlers execute synchronously during event publication. Handlers should therefore avoid unnecessary blocking work. For example, an event handler that performs a long-running operation directly insidepublish() can increase the time spent publishing the event.
A lightweight handler can instead collect the information needed for later processing.
For example:
Event Handler Errors
BecauseEventBus isolates handler exceptions, a failing handler does not normally prevent other subscribed handlers from running.
The event bus logs the handler exception.
Application code should still treat handler failures as real operational errors and monitor the corresponding logs.
Event Names
Use the framework’s existing event names when subscribing to framework events. For example:Events and Execution
Events are useful because they separate the component performing an operation from the component observing it. For example, a model execution path can publish a model event while an independent subscriber records or monitors that event. The publishing component does not need to know which subscribers exist. This separation can be represented as:Events and Automation
EventTrigger provides the bridge between events and automation.
The basic pattern is:
Testing Event Handlers
BecauseEventBus is synchronous, event handling can be tested directly.
For example:
Testing Event Recording
EventRecorder can be used to inspect events emitted during a test:
Testing Event Triggers
Triggers can also be tested synchronously:Events vs Hooks
Events and hooks provide different integration mechanisms.Events
Events are published through anEventBus and can have multiple independent subscribers.
Use events when multiple components may need to observe the same activity.
Agent lifecycle hooks
Agent hooks are attached directly to an agent and participate in the agent lifecycle. They are appropriate when behavior belongs specifically to the lifecycle of that agent. Events are broader and decouple the producer from its consumers.Events and Callbacks
Agent callbacks are a separate mechanism from the coreEventBus.
Use the event system when the behavior should consume a published framework event.
Use an agent callback when the behavior is specifically associated with the agent’s callback lifecycle.
The two mechanisms should not be treated as interchangeable APIs.
Event Data and Payloads
Do not assume that all events have the same payload structure. The baseEvent guarantees:
Observability Architecture
The event system provides the foundation for runtime observation without requiring every consumer to be embedded inside execution code. A typical architecture is:Best Practices
Subscribe only to events you need
Prefer targeted subscriptions when possible:Keep handlers lightweight
Event delivery is synchronous. Avoid unnecessary blocking work inside handlers.Use EventRecorder for local inspection
EventRecorder is useful for debugging and tests when events need to be inspected after execution.
Close recorders when finished
Detach recorders that are no longer needed:Detach unused triggers
Remove triggers that should no longer listen:Disable triggers temporarily
Use:Do not assume execution IDs
Only use execution-specific recording for events that actually includeexecution_id in their payload.
Keep event consumers decoupled
The purpose of the event system is to allow consumers to observe activity without embedding that consumer logic into the component producing the event.Summary
BindAI’s event system consists of a small set of composable primitives:Eventprovides event metadata and payloads.EventBuspublishes events and manages subscriptions.- wildcard subscriptions allow observation of all events on a bus.
- handler exceptions are isolated and logged by the event bus.
ExecutionContextprovides an execution ID and an execution-scopedEventBus.- framework events cover application, agent, workflow, node, model, tool, memory, MCP, and human-task event names.
EventRecorderstores events in memory and can index events that contain an execution ID.EventTriggerconnects a specific event to an automation target.- triggers can be attached, detached, enabled, and disabled.
- event delivery is synchronous.
