Skip to content

Activity verbs

Every mutation appends an Activity row to the append-only log. That log is the audit trail, the webhook payload source, the agent poll history, and the trigger vocabulary for automations. The wire shape:

jsonc
{
  "id": "uuid",            // activity id (UUIDv7)
  "boardId": "uuid",
  "cardId": "uuid | null", // present for card-scoped verbs
  "actorId": "uuid",       // WHO caused it
  "verb": "card.created",
  "payload": { /* verb-specific */ },
  "createdAt": "ISO-8601"
}

Subscribe a webhook to specific verbs or to "*" for all; poll the same verbs over GET /api/boards/:id/activity?since=….

Board

VerbPayload
board.created{ name }
board.updated{ ...changed fields }
board.view_saved{ viewId, name } (shared views)
board.view_updated{ viewId, ...changed }
board.view_removed{ viewId }

List

VerbPayload
list.created{ listId, name }
list.updated{ listId, ...changed }
list.moved{ listId, position }
list.archived{ listId }

Card

VerbPayload
card.created{ title, listId }
card.updated{ ...changed fields }
card.moved{ fromListId, toListId, position }
card.archived{ cardId }
card.assigned{ actorId }
card.unassigned{ actorId }
card.delegated{ agentActorId, delegatedByActorId }
card.undelegated{ agentActorId }
card.labeled{ labelId }
card.unlabeled{ labelId }
card.linked{ linkId, externalSystem, externalId, externalUrl }
card.unlinked{ linkId, externalSystem, externalId, externalUrl }
card.mentioned{ cardId, mentionedActorIds }
card.priority_changed{ priority }
card.field_set{ fieldId, value }
card.field_cleared{ fieldId }
card.attachment_added{ cardId, attachmentId, filename, contentType, sizeBytes }
card.attachment_removed{ cardId, attachmentId, filename }
card.checklist_item_added{ cardId, itemId, text }
card.checklist_item_updated{ cardId, itemId, text }
card.checklist_item_completed{ cardId, itemId, text }
card.checklist_item_removed{ cardId, itemId, text }

Comment

VerbPayload
comment.added{ commentId, body }
comment.edited{ commentId, body }
comment.deleted{ cardId, commentId }
comment.mentioned{ cardId, commentId, mentionedActorIds }

Field

VerbPayload
field.created{ fieldId, ... }
field.updated{ fieldId, ...changed }
field.deleted{ fieldId }

Label

VerbPayload
label.created{ labelId, name, color }

Member

VerbPayload
member.added{ actorId, role }
member.role_changed{ actorId, role }
member.removed{ actorId }

Actor

VerbPayload
actor.capabilities_changed{ actorId, capabilities }

Integration

VerbPayload
integration.installed{ integrationId, type, actorId }
integration.updated{ integrationId, status }
integration.removed{ integrationId, type }

Agent session

Emitted as an agent drives a session. These route to matching board subscriptions and to an agent's actor-scoped subscription (matched on agentActorId), so a mention-invokable agent is reached on any board.

VerbWhen
agent_session.createda session opens (delegation / mention / api) — payload carries the full trigger context
agent_session.updateda state change / status update
agent_session.progressa progress note
agent_session.questionthe agent posted ask_human (session → awaiting_input)
agent_session.answereda human answered (session → working)
agent_session.loga raw inspectable log entry
agent_session.completedthe agent finished successfully
agent_session.failedthe agent failed (or the watchdog timed it out)

VCS (integration-emitted)

The github/gitlab integrations translate PR/MR lifecycle into these verbs, carrying the linked card, on the event path the rules engine watches. Write automations that trigger on them.

VerbWhen
vcs.branch_createda branch whose name carries a card key is pushed
vcs.pr_drafteddraft PR/MR opened (or converted to draft)
vcs.pr_openedready (non-draft) PR/MR opened / reopened
vcs.review_requesteda review is requested / submitted (non-approval)
vcs.pr_approveda review approves the PR/MR
vcs.pr_mergedPR/MR merged — carries filters.targetBranch
vcs.pr_closedPR/MR closed without merging

Additive by default

Treat unknown future verbs and extra payload keys as additive — don't fail on them. The grouped catalog the webhook UI renders is WEBHOOK_EVENT_GROUPS in packages/shared; new verbs enter the domain layer over time.

Released under the AGPL-3.0 license.