Skip to content

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/events

Query the event store with filters and pagination.

bash
curl -H "Authorization: Bearer $TOKEN" \
  "https://api.nonsense.ws/api/v1/events?aggregate=all&limit=20"

Query Parameters

ParameterTypeDefaultDescription
aggregatestringallAggregate ID to filter by (or all)
user_uuidstringFilter events by user (admin only)
from_seqinteger0Start sequence number
limitinteger100Maximum events to return
offsetinteger0Pagination offset

Response:

json
{
  "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:

FieldTypeDescription
idstringUnique event identifier
typestringEvent type (see below)
versionintegerSchema version
aggregate_idstringAggregate root identifier
seqintegerMonotonic sequence within aggregate
timestampintegerUnix timestamp (milliseconds)
dataobjectEvent payload

Event Types

Sol defines 58 event types across 9 categories. Each type is versioned and validated at ingestion.

Task Events (4 types)

TypeAggregateDescription
task.createdtask_idNew task submitted
task.completedtask_idTask finished successfully
task.failedtask_idTask execution failed
task.dispatchedtask_idTask sent to a worker

Model Events (7 types)

TypeAggregateDescription
model.startedmodel_nameInference instance started
model.stoppedmodel_nameInference instance stopped
model.failedmodel_nameInference startup failed
model.readymodel_nameModel ready for requests
model.discoveredmodel_nameModel found during discovery
model.preparedmodel_nameModel files prepared
model.start_failedmodel_nameModel failed to start

Worker Events (8 types)

TypeAggregateDescription
worker.spawnedworker_idWorker process created
worker.crashedworker_idWorker process crashed
worker.readyworker_idWorker announced readiness
worker.task_startedtask_idWorker began a task
worker.task_completedtask_idWorker finished a task
worker.task_failedtask_idWorker task failed
worker.spawn_failedworker_idWorker spawn failed
worker.killedworker_idWorker killed by operator

Inference Events (4 types)

TypeAggregateDescription
inference.requestrequest_idInference request received
inference.completerequest_idInference completed
inference.errorrequest_idInference error
inference.interruptedrequest_idInference interrupted

Scheduler Events (3 types)

TypeAggregateDescription
scheduler.job_createdjob_idScheduled job created
scheduler.job_executedjob_idJob executed
scheduler.task_dispatchedjob_idJob dispatched a task

Workflow Events (5 types)

TypeAggregateDescription
workflow.startedworkflow_idWorkflow began
workflow.completedworkflow_idWorkflow finished
workflow.failedworkflow_idWorkflow failed
workflow.step_startedworkflow_idWorkflow step started

Agent Events (6 types)

TypeAggregateDescription
agent.turn_startedtask_idAgent turn began
agent.turn_completedtask_idAgent turn completed
agent.context_overflowtask_idContext exceeded limits
agent.diagnostictask_idAgent diagnostic event
agent.loop_warningtask_idPossible agent loop detected
agent.loop_detectedtask_idAgent loop confirmed

Audit Events (9 types)

TypeAggregateDescription
audit.tool_executedtask_idTool execution recorded
audit.tool_deniedtask_idTool execution denied
audit.permission_grantuser_uuidPermission granted
audit.permission_denyuser_uuidPermission denied
audit.llm_decisionrequest_idLLM decision logged
audit.intervention_pendingtask_idHuman intervention requested
audit.intervention_approvedtask_idIntervention approved
audit.intervention_rejectedtask_idIntervention rejected
audit.workflow_overrideworkflow_idWorkflow manually overridden

Memory Events (5 types)

TypeAggregateDescription
memory.storedagent_idMemory stored
memory.accessedagent_idMemory accessed
memory.decayedagent_idMemory importance decayed
memory.reflectedagent_idMemory reflection triggered
memory.forgottenagent_idMemory pruned

Team Events (5 types)

TypeAggregateDescription
team.createdteam_idTeam created
team.member_joinedteam_idMember joined team
team.member_leftteam_idMember left team
team.mail_sentteam_idTeam mail sent
team.destroyedteam_idTeam destroyed

SSE Streaming

Real-time event streaming via Server-Sent Events:

GET /api/v1/sync-events
bash
curl -N -H "Authorization: Bearer $TOKEN" \
  https://api.nonsense.ws/api/v1/sync-events

SSE 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

Released under the MIT License.