v1.4.0next
Reference

Events

Every event type on a work item's timeline, its key payload fields, and the notification webhook that sends them.

Kraft records what happens to a work item as a list of events, its timeline. Each event has a seq number, the work_item_id, a type, a JSON payload and a created_at time. Read them with:

kraft view events ID                     # the whole timeline
kraft view events ID --type gate_requested
kraft view events ID --after 120 -f      # later events, then follow
kraft view events ID --json              # the raw events

The tables list each type and the payload fields you are most likely to use. A payload can carry more fields than these. Event types and payloads are not a stable interface: a release can add, rename or reshape them.

Work item

TypeWhenKey fields
work_item_createdThe item is filed.title, repo, chain_template; source, bead_id, priority when auto-intake filed it
work_item_attachmentsThe item is filed with a spec or plan.attachments
work_item_resumedA paused item starts or restarts.steer
pause_requestedSomeone pauses the item.sessions
work_item_blocked_by_dependencyAn open bead dependency paused the item before its next node.node_id, blocked_by
paused_by_broken_baseAnother item broke the base branch, so this one paused.broken_by, follow_up_bead
work_item_needs_humanThe item stopped for a person. See below.node_id, reason
work_item_waitingThe item is parked on an external wait.node_id, retry_at
work_item_rate_limitedThe agent hit a rate limit; the item retries on its own.node_id, retry_at
work_item_retriedSomeone retried the item.node_id, steer, escalated (an escalation turn retried it)
work_item_completedThe item finished, on its own or by hand.none
work_item_manually_completedSomeone completed the item by hand.reason, node_id
work_item_cancelledSomeone cancelled the item.reason, node_id
work_item_abandonedThe item was cancelled or abandoned.none
work_item_archivedThe item left the Done column.by: you or auto
work_item_restoredAn archived item came back.none
work_item_title_editedThe title changed.title
work_item_description_editedThe description changed.description
plan_progressA worker started a plan task.node_id, task, total, title
steer_context_setA steer was stored for the next agent.steer
steer_undeliveredA steer was stored but no agent received it.steer

work_item_needs_human

This is the event behind stop_reason in kraft view show --json, and behind "why did it stop" on the board. Its fields:

FieldMeaning
node_idThe node the item stopped on.
reasonWhat stopped it, in words. A reason that starts needs_context: is a question from the agent.
session_idThe last session of that node, when it failed or asked a question. kraft view logs reads its log.
capped{cycles, attempts} when a fix loop spent its attempts.
budget{scope, spent_usd, cap_usd} when a spend cap stopped the item.
stucktrue when the item stopped in a way an escalation turn can answer.
bundleWhat Kraft gathered about a stuck item when it gave up.
suggested_action{action, reason}, the next step Kraft suggests.

Troubleshooting maps each reason to a fix.

Chain and nodes

TypeWhenKey fields
chain_loadedThe chain was built for the item.none
worktree_preparedThe worktree was created and set up.report
node_startedA node began.node_id
node_completedA node finished.node_id
node_skippedA node or its gate was skipped.node_id, gate, note
scope_skippedA step or task inside a node was skipped.path, note
node_recovery_startedKraft reran a node's failed tasks.node_id, failed_tasks
run_forkedA retry started a new run from part of the old one.path, scope, reopened
base_change_restartThe base branch moved, so part of the chain reran.node_id, restart_from, nodes
worktree_rebase_verifiedA rebase reported by a worker matched the worktree.reported_head, worktree_head
read_only_violatedA read-only node or step changed the worktree.node_id, scope, files
fix_cycle_startedA fix loop started another attempt.node_id, cycle, failed_tasks
fix_cycle_refundedA fix attempt did not count, because the repair never ran.node_id, cycle, outcome
findings_measuredA review or check produced findings.node_id, cycle, findings
judge_verdictA judge ruled on findings.node_id, cycle, verdict, reasoning
sweep_failedKraft could not commit work an agent task left uncommitted: the commit failed, or the worktree was not on the item's branch, held a git operation Kraft did not start, or held a repository Kraft did not create. The work stays in the worktree.node_id, task, error
bead_not_filedIntake could not file a bead.reason
beads_left_openThe item completed but its beads stayed open.beads, reason

Gates and review

TypeWhenKey fields
gate_requestedA gate is waiting for a decision.gate, node_id
gate_approvedA gate was approved.gate, by
gate_rejectedA gate was rejected.gate, note, node, by
gate_reopenedAn approved gate is open again.gate, reason
gate_auto_review_startedA gate's review agent started.gate, session_id
gate_auto_review_skippedA gate's review agent did not run.gate, reason
gate_auto_review_discardedA review agent's verdict was not used.gate, verdict, reason
chain_revision_shownA person was shown a chain revision.gate, digest
chain_revision_unchangedA chain revision proposed no change, so its gate passed.gate, rationale
chain_revisedAn approved chain revision replaced the chain.varies
artifact_refusedKraft found a gate's document but would not serve it.path, reason
review_submittedA review was sent.review_id, gate, outcome
thread_updatedA review thread was resolved or reopened.thread_id, state
rewind_requestedA review asked for work to be redone.review_id, target, note
rewind_cancelledThat request was withdrawn.review_id
reply_agent_wroteAn agent answered review threads.gate, files
reply_agent_skippedNo agent answered review threads.gate, reason
reply_agent_failedThe reply agent failed.gate, error

by is human (the board or the kraft command), assistant (an agent through the MCP server), agent (a Kraft worker, such as a gate's review agent) or kraft (Kraft itself).

Agent sessions

TypeWhenKey fields
worker_session_createdA session was recorded, before launch.session_id, node_id, hook_point, attempt
worker_session_startedIts process started.session_id, node_id, hook_point, pid
worker_session_exitedIt ended.session_id, status, wall_ms, model, cost_usd, token counts
worker_session_pausedIt was stopped by a pause, skip or manual end.session_id
agent_session_resumedA session resumed the agent's earlier conversation.task, session_id
session_reattachedAfter a restart, Kraft found a session still running.session_id, pid
session_unknownAfter a restart, Kraft could not confirm a session.session_id, reason
background_jobs_abandonedA session left background jobs behind.reason
permission_decisionThe permission gate answered a tool call.session_id, node_id, tool, decision, reason, grant

Caps, budgets and limits

TypeWhenKey fields
time_cap_reachedA time cap ran out.scope, field, minutes, reason, node_id
scope_budget_reachedA scope's token or dollar cap refused a launch.the breach fields, task
budget_changedThe item's spend cap was set.budget_usd
budget_raisedThe cap was raised to continue a stopped item.budget_usd
spend_unpricedThe first session on the item whose harness reported no cost and whose model prices.json cannot price: the item and daily dollar caps count it as $0.session_id, harness, model, message
cap_counters_resetLoop counters were reset.by, counters
rate_limit_hitAn agent CLI refused a launch for a rate limit.node_id, rate_limit_type, resets_at_iso
launch_fallbackA launch moved to the next harness or model.node_id, task, from, to, reason
launch_fallback_exhaustedEvery fallback was limited.node_id, task, resets_at_iso

Escalation

TypeWhenKey fields
escalation_messageA message went into the escalation thread.session_id, message, auto, thread, turn
stuck_escalation_startedKraft started an escalation turn on a stuck item.node_id, task, reason, attempt
stuck_escalation_finishedThat turn ended.node_id, task, status
work_item_auto_escalate_skippedKraft did not escalate a stop.reason
work_item_auto_escalate_cappedAutomatic escalations hit their limit.cap, count
work_item_self_retry_requestedAn escalation turn asked to retry the item.node_id, path, restart, steer
work_item_self_retry_droppedThat retry did not happen.node_id, status

Forge, CI and waits

TypeWhenKey fields
mr_openedThe merge request was opened.number, url
mr_labels_setA worker labeled the merge request.labels
external_wait_startedA wait on CI or a review began.task, node_id, kind, timeout_s, deadline
external_wait_observedKraft checked the wait.task, observation, state, result, next_observation_at
external_wait_reboundedA policy change moved the wait's limits.task, timeout_s, deadline
external_wait_endedThe wait settled, timed out or errored.task, outcome, result, observations
ci_infra_exhaustedCI failed for its own reasons, and retries did not help.node_id, reason
ci_run_abandonedA cancelled CI run has no successor.node_id, reason
ci_not_configuredThe repo sets ci_checks: false, so a CI wait, before or after the merge, passed without checking.node_id, task, repo
automated_review_not_configuredThe repo names no automated reviewer, so the wait settles without one.node_id, task, repo
automated_review_erroredThe automated reviewer failed.node_id, reason

Sandbox

TypeWhenKey fields
sandbox_egress_refusedThe sandbox proxy refused a host.session_id, host, port, phase, reason
sandbox_oom_killedThe container was killed under its memory limit. confirmed is false when the runtime never flagged the kill and Kraft counted exit 137 under the limit instead.session_id, memory, confirmed
sandbox_branch_not_syncedThe sandbox's branch did not reach the worktree.session_id, branch, reason
sandbox_kit_resolvedA task was dispatched under a Kit, once per item and Kit. skipped lists the optional capabilities Kraft does not enforce, and ignored those it accepts without applying (agent-sessions@1, a credential's oauth).kit, manifest, skipped, ignored

A workspace item records one sandbox_branch_not_synced for each repository whose branch did not move, and its reason names that repository.

Settings changed

TypeWhenKey fields
chain_template_changedThe item moved to another chain before it started.from, to
attachments_changedIts spec or plan changed before it started.from, to
agent_overrides_changedIts model or effort override changed.overrides
node_overrides_changedA node's override changed.overrides
policy_override_changedIts policy override changed.policy
notification_failedThe notification webhook failed twice.event_type, status, host, error

Notifications

notify.yaml sends an HTTP POST to a webhook when an event you name happens. Set it on the Settings screen, or edit the file:

enabled: true
url: https://hooks.example.com/abc123   # a secret; Kraft never shows it back
base_url: https://kraft.example.com     # where links in the message point
events: [gate_requested, work_item_needs_human]
FieldDefaultMeaning
enabledfalseNothing is sent while this is off, or while url is empty.
urlnoneThe webhook.
base_urlthe address the server listens onThe start of the link in each message.
events[gate_requested, work_item_needs_human]Which event types send a message. Any type on this page works; Kraft does not check the names, so a typo sends nothing.

The body is JSON:

{
  "work_item_id": "<work-item-id>",
  "title": "Fix the flaky login test",
  "type": "gate_requested",
  "gate": "spec_approval",
  "url": "https://kraft.example.com/work-items/<work-item-id>"
}

gate is null for an event that is not about a gate.

  • Kraft sends at most one message per work item every 10 seconds. A second matching event in that window sends nothing.
  • A send that times out after 5 seconds, errors, or gets a status of 400 or more is tried once more after 2 seconds. If that fails too, Kraft records a notification_failed event on the item.
  • Events that happen while the server is down send nothing when it comes back.
  • The Settings screen's Send a test posts "type": "test" with a nullwork_item_id and gate.
Copyright © 2026