Understanding the DomainEvent Taxonomy in OpenHuman's Event Bus
The DomainEvent taxonomy in OpenHuman categorizes domain-specific events into ten type-safe variants—Agent, Memory, Thread, Tool, Channel, Cron, Skill, Web3, MCP, and System—enabling decoupled communication and efficient filtering across the application's lightweight event bus.
The tinyhumansai/openhuman repository implements a lightweight, type-safe event-bus system that serves as the central nervous system for the application runtime. At the heart of this architecture lies the DomainEvent taxonomy, a Rust enum defined in src/core/events.rs that provides a structured classification for routing domain-specific signals across agent harnesses, memory subsystems, and external integrations.
What is the DomainEvent Taxonomy?
The DomainEvent enum serves as the fundamental classification system for all events traversing the OpenHuman event bus. Defined in src/core/events.rs, this taxonomy organizes events by their originating domain, allowing subscribers to filter and react only to relevant signals without deserializing unrelated data.
The enum comprises ten distinct variants, each representing a specific subsystem:
| Domain | Event Variant | Purpose |
|---|---|---|
| Agent | Agent |
Events from the agent harness including tool execution, thought generation, and turn completion. |
| Memory | Memory |
Memory subsystem events such as chunk storage, retrieval results, and diff updates. |
| Thread | Thread |
Conversation thread lifecycle events including creation, deletion, and label changes. |
| Tool | Tool |
Tool execution events covering start signals, progress updates, and result publication. |
| Channel | Channel |
Communication layer events including inbound messages, status changes, and webhook callbacks. |
| Cron | Cron |
Scheduled task events for periodic clean-ups, automation triggers, and background job completions. |
| Skill | Skill |
Skills runtime events including workflow start/end and skill-registry updates. |
| Web3 | Web3 |
Blockchain interaction events such as wallet state changes and X-402 transaction outcomes. |
| MCP | Mcp |
Managed Compute Platform events including server registration and tool-call results. |
| System | System |
Broad system-level signals like shutdown notifications and health-check updates. |
Each variant carries a strongly-typed payload—typically a struct such as AgentEvent or MemoryEvent defined in the same module—ensuring type safety across the event bus.
Event Bus Communication Patterns
OpenHuman's event bus supports two primary communication patterns for interacting with the DomainEvent taxonomy, implemented in src/core/bus.rs.
Fire-and-Forget Publishing
Use publish_global to broadcast events to all subscribers and subscribe_global to receive the event stream. This pattern suits logging, monitoring, and side-effect triggers where no response is required.
Typed Request-Response
For synchronous interactions requiring a return value, use register_native_global to expose request handlers and request_native_global to invoke them. This pattern supports RPC-style communication with strongly-typed requests and responses.
Working with DomainEvents in Rust
The following examples demonstrate practical usage of the DomainEvent taxonomy in application code.
Publishing Memory Events
To broadcast a memory-related event, wrap the specific payload in the DomainEvent enum and invoke the global publisher:
use openhuman_core::core::events::{DomainEvent, MemoryEvent};
use openhuman_core::core::bus::publish_global;
// Create a specific memory payload
let mem_evt = MemoryEvent::ChunkStored { chunk_id: "c123".into() };
// Wrap in taxonomy enum and broadcast
publish_global(DomainEvent::Memory(mem_evt));
Subscribing to Tool Events
Subscribers can pattern-match on specific DomainEvent variants to filter the event stream efficiently:
use openhuman_core::core::events::{DomainEvent, ToolEvent};
use openhuman_core::core::bus::subscribe_global;
let mut sub = subscribe_global();
// Filter for Tool variant only
while let Some(event) = sub.next() {
if let DomainEvent::Tool(tool_evt) = event {
match tool_evt {
ToolEvent::Started { tool_name } => {
println!("Tool started: {}", tool_name);
}
ToolEvent::Progress { percent } => {
println!("Progress: {}%", percent);
}
_ => {}
}
}
}
Request-Response for Cron Jobs
For synchronous job execution, use the typed request API:
use openhuman_core::core::bus::{request_native_global, NativeResponse};
use openhuman_core::core::events::{DomainEvent, CronEvent};
let request = CronEvent::RunJob { job_id: "backup".into() };
let response: NativeResponse = request_native_global(
"cron.run_job",
request,
);
println!("Job result: {:?}", response);
Key Source Files
The following files implement the DomainEvent taxonomy and event bus infrastructure:
| File | Role |
|---|---|
src/core/events.rs |
Defines the DomainEvent enum and domain-specific payload structs like AgentEvent and MemoryEvent. |
src/core/bus.rs |
Implements the global publish/subscribe API including publish_global and subscribe_global. |
src/core/bus_testing.rs |
Provides test utilities and harnesses for verifying event-bus behavior. |
src/core/events_tests.rs |
Contains unit tests ensuring each domain variant emits and handles correctly. |
src/core/runtime/services.rs |
Orchestrates domain services that emit events into the bus. |
Summary
- The DomainEvent taxonomy provides ten type-safe variants (
Agent,Memory,Thread,Tool,Channel,Cron,Skill,Web3,Mcp,System) for categorizing events insrc/core/events.rs. - Each variant encapsulates a domain-specific payload, enabling efficient filtering without deserialization overhead.
- The event bus supports both asynchronous fire-and-forget patterns via
publish_global/subscribe_globaland synchronous request-response viarequest_native_global. - This architecture decouples subsystems while maintaining type safety across the OpenHuman runtime.
Frequently Asked Questions
What is the DomainEvent taxonomy used for in OpenHuman?
The DomainEvent taxonomy classifies all events flowing through the OpenHuman event bus into ten distinct domains, enabling type-safe routing and filtering. It allows subsystems like the agent harness, memory store, and Web3 integrations to communicate without direct coupling.
How do I filter specific event types in the OpenHuman event bus?
Subscribe to the global bus using subscribe_global from src/core/bus.rs, then pattern-match on the desired DomainEvent variant. This approach avoids the cost of deserializing unrelated events because filtering occurs at the enum level.
What is the difference between publish_global and request_native_global?
publish_global implements fire-and-forget broadcasting where events are emitted without expecting a response, while request_native_global implements a typed request-response pattern suitable for RPC-style communication requiring return values.
Where is the DomainEvent enum defined in the OpenHuman codebase?
The DomainEvent enum is defined in src/core/events.rs within the tinyhumansai/openhuman repository, alongside the domain-specific payload structs such as AgentEvent, MemoryEvent, and ToolEvent.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →