Events API
Sol uses a Mnesia-backed event sourcing system as its orchestration backbone. The Events API provides read access to the event stream and real-time SSE subscriptions.
List Events
GET /api/v1/eventsQuery the event store with filters and pagination.
curl -H "Authorization: Bearer $TOKEN" \
"https://api.nonsense.ws/api/v1/events?aggregate=all&limit=20"Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
aggregate | string | all | Aggregate ID to filter by (or all) |
user_uuid | string | — | Filter events by user (admin only) |
from_seq | integer | 0 | Start sequence number |
limit | integer | 100 | Maximum events to return |
offset | integer | 0 | Pagination offset |
Response:
{
"ok": true,
"data": [
{
"id": "evt-1744730000000",
"type": "task.completed",
"version": 1,
"aggregate_id": "task-123",
"seq": 42,
"timestamp": 1744730000000,
"data": {
"task_id": "task-123",
"worker_id": "luna-01",
"status": "ok",
"duration_ms": 3200
}
}
],
"total": 142,
"offset": 0,
"limit": 20
}Event Structure
Every event in the store follows a consistent schema:
| Field | Type | Description |
|---|---|---|
id | string | Unique event identifier |
type | string | Event type (see below) |
version | integer | Schema version |
aggregate_id | string | Aggregate root identifier |
seq | integer | Monotonic sequence within aggregate |
timestamp | integer | Unix timestamp (milliseconds) |
data | object | Event payload |
Event Types
Sol defines 58 event types across 9 categories. Each type is versioned and validated at ingestion.
Task Events (4 types)
| Type | Aggregate | Description |
|---|---|---|
task.created | task_id | New task submitted |
task.completed | task_id | Task finished successfully |
task.failed | task_id | Task execution failed |
task.dispatched | task_id | Task sent to a worker |
Model Events (7 types)
| Type | Aggregate | Description |
|---|---|---|
model.started | model_name | Inference instance started |
model.stopped | model_name | Inference instance stopped |
model.failed | model_name | Inference startup failed |
model.ready | model_name | Model ready for requests |
model.discovered | model_name | Model found during discovery |
model.prepared | model_name | Model files prepared |
model.start_failed | model_name | Model failed to start |
Worker Events (8 types)
| Type | Aggregate | Description |
|---|---|---|
worker.spawned | worker_id | Worker process created |
worker.crashed | worker_id | Worker process crashed |
worker.ready | worker_id | Worker announced readiness |
worker.task_started | task_id | Worker began a task |
worker.task_completed | task_id | Worker finished a task |
worker.task_failed | task_id | Worker task failed |
worker.spawn_failed | worker_id | Worker spawn failed |
worker.killed | worker_id | Worker killed by operator |
Inference Events (4 types)
| Type | Aggregate | Description |
|---|---|---|
inference.request | request_id | Inference request received |
inference.complete | request_id | Inference completed |
inference.error | request_id | Inference error |
inference.interrupted | request_id | Inference interrupted |
Scheduler Events (3 types)
| Type | Aggregate | Description |
|---|---|---|
scheduler.job_created | job_id | Scheduled job created |
scheduler.job_executed | job_id | Job executed |
scheduler.task_dispatched | job_id | Job dispatched a task |
Workflow Events (5 types)
| Type | Aggregate | Description |
|---|---|---|
workflow.started | workflow_id | Workflow began |
workflow.completed | workflow_id | Workflow finished |
workflow.failed | workflow_id | Workflow failed |
workflow.step_started | workflow_id | Workflow step started |
Agent Events (6 types)
| Type | Aggregate | Description |
|---|---|---|
agent.turn_started | task_id | Agent turn began |
agent.turn_completed | task_id | Agent turn completed |
agent.context_overflow | task_id | Context exceeded limits |
agent.diagnostic | task_id | Agent diagnostic event |
agent.loop_warning | task_id | Possible agent loop detected |
agent.loop_detected | task_id | Agent loop confirmed |
Audit Events (9 types)
| Type | Aggregate | Description |
|---|---|---|
audit.tool_executed | task_id | Tool execution recorded |
audit.tool_denied | task_id | Tool execution denied |
audit.permission_grant | user_uuid | Permission granted |
audit.permission_deny | user_uuid | Permission denied |
audit.llm_decision | request_id | LLM decision logged |
audit.intervention_pending | task_id | Human intervention requested |
audit.intervention_approved | task_id | Intervention approved |
audit.intervention_rejected | task_id | Intervention rejected |
audit.workflow_override | workflow_id | Workflow manually overridden |
Memory Events (5 types)
| Type | Aggregate | Description |
|---|---|---|
memory.stored | agent_id | Memory stored |
memory.accessed | agent_id | Memory accessed |
memory.decayed | agent_id | Memory importance decayed |
memory.reflected | agent_id | Memory reflection triggered |
memory.forgotten | agent_id | Memory pruned |
Team Events (5 types)
| Type | Aggregate | Description |
|---|---|---|
team.created | team_id | Team created |
team.member_joined | team_id | Member joined team |
team.member_left | team_id | Member left team |
team.mail_sent | team_id | Team mail sent |
team.destroyed | team_id | Team destroyed |
SSE Streaming
Real-time event streaming via Server-Sent Events:
GET /api/v1/sync-eventscurl -N -H "Authorization: Bearer $TOKEN" \
https://api.nonsense.ws/api/v1/sync-eventsSSE event format:
event: task.completed
data: {"id":"evt-1744730001","type":"task.completed","data":{"task_id":"t-456","status":"ok"}}
event: worker.ready
data: {"id":"evt-1744730002","type":"worker.ready","data":{"worker_id":"luna-02"}}Events are delivered in real-time as they are committed to the store. The connection stays open until the client disconnects or the server sends a keep-alive comment (: ping).
Event Hooks
Events support pre-commit and post-commit hooks. Hooks are registered programmatically:
- Pre-commit hooks can validate or enrich event data before persistence
- Post-commit hooks trigger side effects (notifications, projections, ZMQ broadcasts)
Event Store
The event store is backed by Mnesia with automatic sequence numbering per aggregate. Key properties:
- Events are append-only and immutable
- Each aggregate maintains a monotonic sequence counter
- Events are replayable for state reconstruction
- Projections can be registered for materialized views