Skip to content

Event Taxonomy

OrgLoop uses three event types. This taxonomy is minimal by design — new types are always additive, never replacing existing ones.

TypeMeaningExample
resource.changedSomething changed in an external systemPR opened, ticket moved, CI failed, deploy completed
actor.stoppedAn actor’s session endedClaude Code exited, OpenClaw agent finished
message.receivedA human or system sent a messageSlack message, webhook payload, CLI notification

Routes match on these types using the events field:

routes:
- name: pr-review
when:
source: github
events: [resource.changed]
then:
actor: engineering

Every event shares the same envelope structure. The envelope is generic; payloads are connector-specific.

{
"id": "evt_a1b2c3d4e5",
"timestamp": "2026-02-08T20:47:00Z",
"source": "github",
"type": "resource.changed",
"provenance": {
"platform": "github",
"platform_event": "pull_request.review_submitted",
"author": "alice",
"author_type": "team_member"
},
"payload": {
"pull_request": {
"number": 42,
"title": "Refactor auth module",
"url": "https://github.com/my-org/my-repo/pull/42"
}
},
"trace_id": "trc_x9y8z7w6"
}
FieldTypeDescription
idstringUnique event identifier. Always prefixed with evt_.
timestampstringISO 8601 UTC timestamp.
sourcestringSource connector ID that emitted this event.
typestringOne of the three event types.
provenanceobjectOrigin metadata — platform, original event type, author, author classification.
payloadobjectConnector-specific data (freeform JSON).
trace_idstringTrace ID for end-to-end pipeline tracing. Prefixed with trc_. Added by the engine.

Provenance carries metadata about where the event originated in the external system:

FieldDescription
platformThe external platform (github, linear, claude-code, etc.)
platform_eventThe original event type on that platform (pull_request.review_submitted, issue.state_change)
authorWho caused the event (alice, app/renovate-bot)
author_typeClassification: team_member, external, bot, system, unknown

Routes can filter on provenance fields using dot-path matching:

routes:
- name: pr-review
when:
source: github
events: [resource.changed]
filter:
provenance.platform_event:
- pull_request.review_submitted
- pull_request_review_comment

actor.stopped is deliberately neutral. OrgLoop observes that a session ended. Whether the work was completed, the agent crashed, got stuck, or lied about finishing — that is for the receiving actor to judge. OrgLoop routes signals; actors have opinions.

This design enables supervision patterns:

Claude Code session ends
|
v
actor.stopped event (payload contains session details)
|
v
Route matches --> Supervisor actor wakes
|
v
Supervisor reads payload, decides:
- Work completed? Move on.
- Agent stuck? Re-dispatch with more context.
- Something broke? Escalate.

The supervisor makes the judgment call, not OrgLoop. The routing layer is opinion-free.

The event envelope is generic, but payloads are connector-specific. A GitHub resource.changed event carries PR data. A Linear resource.changed event carries ticket data. Connectors do not assume payload shapes from other connectors.

This keeps the system composable. You can swap connectors without changing route logic, because routes match on envelope fields (source, type, provenance), not payload internals.

Every event receives a trace_id (prefixed with trc_) when it enters the engine. The trace ID is carried through every phase of the pipeline — source ingestion, transform execution, route matching, actor delivery, and logging. Use it to trace a single event end-to-end:

Terminal window
orgloop logs --event evt_a1b2c3d4e5

See the Event Schema for the full JSON Schema definition, or the Five Primitives for how events flow through the system.