Event Types
OpenParallax uses an event-driven architecture for real-time communication between the Engine and its clients (CLI, web UI, channel adapters). Every significant action in the message pipeline emits a PipelineEvent that clients receive through their transport (gRPC stream or WebSocket).
Source: internal/engine/eventsender.go
EventSender Interface
All transports implement the same interface:
type EventSender interface {
SendEvent(event *PipelineEvent) error
}Implementations: grpcEventSender (protobuf over gRPC for CLI), wsEventSender (JSON over WebSocket for web UI), and any custom channel adapter.
PipelineEvent Envelope
Every event is wrapped in a PipelineEvent with routing metadata:
| Field | Type | Description |
|---|---|---|
session_id | string | Session this event belongs to |
message_id | string | Message that triggered this event |
type | string | Event type identifier (see below) |
Exactly one payload field is set per event, determined by the type field.
Core Events
These 9 events cover the standard message pipeline.
llm_token
A single streamed token from the LLM response. Emitted continuously during text generation.
| Field | Type | Description |
|---|---|---|
text | string | The token text fragment |
JSON key: text
action_started
Signals that a tool call is beginning execution.
| Field | Type | Description |
|---|---|---|
tool_name | string | Name of the tool being executed |
summary | string | Human-readable description of the action |
shield_verdict
Carries the Shield security evaluation result for a proposed action.
| Field | Type | Description |
|---|---|---|
tool_name | string | Tool that was evaluated |
decision | string | Verdict: "ALLOW", "BLOCK", or "ESCALATE" |
tier | int | Shield tier that made the decision (0, 1, or 2) |
confidence | float64 | Confidence score (0.0 - 1.0) |
reasoning | string | Explanation of the verdict |
action_completed
Signals that a tool call finished execution.
| Field | Type | Description |
|---|---|---|
tool_name | string | Tool that completed |
success | bool | Whether the action succeeded |
summary | string | Human-readable result summary |
response_complete
Emitted once at the end of a message pipeline cycle. Carries the full assistant response and any extended thinking content.
| Field | Type | Description |
|---|---|---|
content | string | Full assistant response text |
thoughts | []Thought | Extended thinking content (optional) |
otr_blocked
Emitted when an action is blocked because the session is in OTR mode.
| Field | Type | Description |
|---|---|---|
reason | string | User-facing explanation of why the action was blocked |
error
Carries a pipeline error.
| Field | Type | Description |
|---|---|---|
code | string | Machine-readable error code |
message | string | Human-readable error description |
recoverable | bool | Whether the pipeline can continue after this error |
tier3_approval_required
Requests human-in-the-loop approval for an action that Shield escalated to Tier 3.
| Field | Type | Description |
|---|---|---|
action_id | string | Unique ID for the pending action |
tool_name | string | Tool awaiting approval |
reasoning | string | Explanation of why approval is needed |
timeout_secs | int | Seconds before auto-deny if no response |
JSON key: tier3_approval
log_entry
Global event — delivered to all connected clients regardless of session. Used by the web UI developer console. This event is processed before session filtering and has no session_id.
| Field | Type | Description |
|---|---|---|
level | string | Log level: debug, info, warn, error |
event | string | Structured event name |
message | string | Human-readable log message |
fields | object | Additional structured data |
Sub-Agent Events
These 5 events track the lifecycle of sub-agents spawned via the create_agent action.
sub_agent_spawned
A new sub-agent has been created and is starting work.
| Field | Type | Description |
|---|---|---|
name | string | Sub-agent name |
task | string | Task description assigned to the sub-agent |
tool_groups | []string | Tool groups available to the sub-agent (optional) |
sub_agent_progress
Periodic progress update from a running sub-agent.
| Field | Type | Description |
|---|---|---|
name | string | Sub-agent name |
llm_calls | int | Number of LLM calls made so far |
tool_calls | int | Number of tool calls made so far |
elapsed_ms | int64 | Milliseconds since the sub-agent started |
sub_agent_completed
A sub-agent finished its task successfully.
| Field | Type | Description |
|---|---|---|
name | string | Sub-agent name |
result | string | Task result or summary |
duration_ms | int64 | Total execution time in milliseconds |
sub_agent_failed
A sub-agent encountered an error and could not complete.
| Field | Type | Description |
|---|---|---|
name | string | Sub-agent name |
error | string | Error description |
sub_agent_cancelled
A sub-agent was terminated by the user or system.
| Field | Type | Description |
|---|---|---|
name | string | Sub-agent name |
Event Flow
Events are emitted in the following order during a typical message pipeline cycle:
User message arrives
-> llm_token (streamed, many)
-> action_started
-> shield_verdict
-> action_completed
-> ... (repeat for each tool call, up to 25 rounds)
-> llm_token (streamed, many)
-> response_completeFor sub-agent actions:
action_started (create_agent)
-> shield_verdict
-> action_completed
-> sub_agent_spawned
-> sub_agent_progress (periodic)
-> sub_agent_completed | sub_agent_failed | sub_agent_cancelledWebSocket Transport
Over WebSocket (ws://localhost:3100/ws), events are JSON-encoded PipelineEvent objects. Clients filter events by session_id to avoid cross-session contamination. The log_entry event type (used for live log broadcast) is global and processed before the session filter.
gRPC Transport
Over gRPC, events are protobuf-encoded via the PipelineService.StreamEvents RPC. See the gRPC API reference for protobuf definitions.