The work item object
A work item reaches a client in three shapes, and the route entries name the one each answers with. This page lists the fields of each shape, then explains the ones that need it.
The three shapes
| Shape | Answered by | What it holds |
|---|---|---|
| The stored row | A gate's approve or reject, skip, complete, cancel, and a resume or retry that stops at once. | Every column of the item's row, as saved. |
| The list row | One per item in GET /api/work-items. | A short subset of the columns, and a few computed fields. |
| The detail object | GET /api/work-items/{id}. | The stored row, and the computed fields below. |
The stored row
The stored row has one key per column of the item's row. A column that holds JSON comes as text, except the three override columns, which are decoded. It has none of the computed fields, such as display_status, stop or budget_cap.
| Column | Type | Meaning |
|---|---|---|
id | string | The item's id. |
title | string | One line of plain text. |
description | string or null | The brief the agents are given. |
repo | string | The absolute path of the connected repo. |
status | string | active, needs_human, waiting, rate_limited, paused, completed or abandoned. Work item statuses says what each means. |
chain_template | string or null | The chain named when the item was filed, or null when none was named. |
chain_definition | string | "{}" on an item filed now. The chain is in materialized_chain. |
materialized_chain | string or null | The chain the item runs, frozen when it was filed, as JSON text. null on a row filed before chains were frozen. |
run_chain | string or null | The frozen chain of the run fork the item is executing, as JSON text. null until the first retry, when the filed chain is the run. |
current_node_id | string or null | The node the item stands on. null before it first runs. |
current_step | integer | The step group of that node it last began. 0 unless a wait or a retry resumed the node past its first group. |
stop_kind | string or null | Why the item is stopped, while it is needs_human, waiting or rate_limited. null otherwise. See stop.kind. |
retry_at | string or null | While rate_limited, when the limit resets and the item may relaunch. null otherwise. |
pending_steer_context | string or null | The note left while the item was paused, which the next agent launch takes. |
escalation_session_id | string or null | The agent CLI's own session id for the item's escalation thread. null until the first escalation turn. |
base_ref | string or null | The commit the item's diff is measured against. null until the item first runs. |
branch | string or null | The git branch the item's worktree, merge request and merge all name. null on a row filed before the column existed, which uses kraft/<id>. |
ci_pipeline_ref | string or null | The pipeline the last CI read pinned, as <head_sha>:<pipeline_id>. Empty until the first poll. |
bead_id | string or null | The item's own bead. |
bead_cwd | string or null | The directory of the bd workspace the bead lives in. null on an older row, which uses the instance-wide one. |
implements_beads | string or null | The bead ids the item implements, as a JSON list. null when none. |
attachments | string or null | The spec and plan attached at intake, as a JSON list of {kind, path, ...}. null when none. |
submodules | string or null | The mount paths of a workspace item's members, as a JSON list. null for any other item. |
root_merge_policy | string or null | A workspace item's root pointer policy, ignore or bump. null for any other item. |
auto_gate | integer | 1 when agent review of the item's auto_escalate gates is armed, 0 when not. |
budget_set | integer | 1 when the item has its own cap choice, held in budget_usd, and 0 when the policy default applies. |
budget_usd | number or null | The item's own dollar cap. With budget_set 1, null means no cap. |
agent_overrides | object or null | The item's model and effort override, decoded. null when it has none. |
node_overrides | object | The per-node overrides, {node_id: {field: value}}, decoded. {} when it has none. |
policy_override | object or null | The item's own policy override, decoded. null when it has none. |
archived_at, archived_by | string or null | When the item was archived, and whether by you or auto. null when it is not archived. |
created_at, updated_at | string | When the row was made and last changed, as UTC timestamps. |
The list row
The list row is built for the board, from one grouped query, so it leaves out the fields that need a lookup per item, apart from a short progress. It has these keys:
- From the stored row:
id,title,description,repo,status,chain_template,current_node_id,bead_id,created_at,updated_at,retry_at,archived_atandarchived_by. chain_definition, as the chain's nodes, which the board draws as a stage bar.attachments, as a decoded list,[]when none.pending_gate, the gate waiting on a person, ornull.fallback, the fallback launch the item's latest session started on, ornull.display_status,stop,step,mr_refandprogress, as explained below.
It has no agent_overrides, node_overrides or policy_override, and none of the keys only the detail has.
The detail object
The detail object is the stored row, with chain_definition replaced by the chain's nodes and attachments by a decoded list, plus the keys below. Fields that need an explanation covers display_status, stop, test_result, budget_cap, running_time, summary, mr_ref, progress, worktree_exists, worker_sessions, scope_runs and fix_target.
| Key | Meaning |
|---|---|
effective_chain | The chain with the item's node overrides folded over it. |
node_overrides_count | How many nodes have overrides. |
rate_limit | {count, cap}: the relaunches used and allowed. null unless the item is rate_limited and has a current node. |
usage | The item's usage per node and in total: tokens, cost and wall time. |
repos | One entry per repository of a multi-repo item. [] for a single-repo item. |
escalation_threads | One entry per escalation thread the item has had, oldest first. |
worktree_path | Where the worktree is, or will be, on the server's disk. |
head_sha | The worktree's HEAD commit, or null when there is no worktree. |
pending_gate | The gate waiting on a person, or null. |
pending_rewind | A request-changes review waiting to be honored at its target node, or null. |
attempts | The review's compare picker: the pending gate's attempts. [] with no gate pending. |
last_review_sha | The commit the last submitted review was made on, or null. |
reject_default | The node a rejection would re-enter at. null with no gate pending. |
gate_artifact | The kind of document the pending gate decides. null with no gate pending, when the gate declares none, or when the file is not on disk. |
stop_reason | The stop's reason text, or null when the item is not stopped. |
suggested_action | {action, reason}: what the chain or a repair concluded a person should do, where action is skip, retry or abandon. null when none. |
deferred_findings | Findings that never entered the fix loop, listed for the person at the gate. |
judge_stop_note | Findings a judge chose to stop chasing since the last resolved gate. |
concerns | The done_with_concerns text of each session since the last resolved gate, oldest first. |
needs_context_question | The worker's question, while the item is stopped on one. null otherwise. |
steerable | Whether a note sent now to POST /api/work-items/{id}/steer or /resume would be accepted. |
Fields that need an explanation
| Field | Meaning |
|---|---|
display_status | List and detail. The board's status badge, one of archived, done, cancelled, paused, running, waiting, needs_you, escalated, failed. Read-only and computed on read rather than stored: see Displayed status. |
stop | List and detail. null unless the item is needs_human, waiting or rate_limited. See The stop field. |
test_result | Detail only. The latest changed-test-scope verification run. See The test_result field. |
budget_cap | Detail only. The item's effective dollar cap and spend. See The budget_cap field. |
running_time | Detail only. {running_s, cap_minutes}: the seconds any session ran since the last /retry a person made, against the item-wide time_cap_minutes (null for none). The whole field is null for an item with no frozen chain. |
summary | Detail only. A run's progress at a glance. See The summary field. |
step | List only. {index, count, name, task} or null, which lets the board draw a row. index and count are as in summary.step. name is the step's id, and task is the latest non-escalation session's task id in it. |
mr_ref | List and detail. The item's merge request, {number, url}, or null. The board draws "merged !139" from it. |
progress | List and detail. The item's place in its plan. See The progress field. |
worktree_exists | Detail only. See The worktree_exists field. |
worker_sessions | Detail only. One entry per session. repository is the workspace member the session ran in, or null for the item's own repository. |
scope_runs | Detail only. Every command a changed-test-scope task ran. See The scope_runs field. |
fix_target | Detail only. Where a request-changes review restarts, while a gate is pending. See The fix_target field. |
agent_overrides, node_overrides, policy_override | Stored row and detail, not the list. The item's overrides, null when the item has none, except node_overrides, which is {}. PATCH sets them: see Changing a work item. |
Why the item stopped
The stop field
stop is {kind, node, resume_at, reason} on the list. The detail adds task, attempt and facts. On a cap or budget stop it adds limit, and on a budget stop scope.
facts.cause names why an infra stop happened, when Kraft knows. The facts field lists the values. The failed card chooses its action from it, and an infra stop without one reads as a generic infrastructure stop.
A rate_limit stop's facts also carries fallback and fallback_allowed: the stopped task's declared fallback harnesses, and which of those its resolved policy still allows.
stop.kind
stop.kind is one of twelve values: gate, question, cap, budget, failed, conflict, mr_closed, config, infra, stuck, wait and rate_limit. Stop kinds says what each means, and Why did my item stop? gives each stop's reason with its fix.
A needs_human row saved before database migration 45 has no recorded kind. It reads the kind of its stop event, else question for a reason that starts needs_context:, budget where the event carries budget, cap where it carries capped, else failed. A waiting row with none reads wait and a rate_limited one rate_limit.
stop.limit
A cap or budget stop on the detail also carries limit: {path, key, value, maximum} when a PATCH of the item's policy can raise what stopped it, and omits it when none can.
key | What it caps | path |
|---|---|---|
max_attempts, timeout_minutes | A fix loop's attempts or its clock. | The node id. |
time_cap_minutes, total_time_cap_minutes | The work item's own cap. | "" |
budget_usd | On a budget stop, the item-wide policy dollar cap. | "" |
value is the limit that stopped it, in attempts, minutes or dollars. maximum is the maxima ceiling or null.
Raise it with PATCH /api/work-items/{id} {policy: {<key>: N}} (item-wide) or {policy: {paths: {<path>: {<key>: N}}}}, then POST /api/work-items/{id}/retry.
There is no limit for:
- a
budgetstop on the item's own cap (POST /api/work-items/{id}/budget/raiseraises that one), on a node, step or task'sbudget_usd, atoken_budget, the daily cap or spend a harness never reported; - a node, step or task's time cap;
- a gate's or wait's timeout;
- a
loops:cap inpolicy.yaml; - exhausted rate-limit retries;
- a fix loop whose bound the older
node_overridesset.
stop.scope
A budget stop on the detail also carries scope, the cap that stopped it:
scope | The cap |
|---|---|
work_item | The item's own dollar cap. |
usd | A budget_usd, item-wide or on a node, step or task, or spend a harness never reported. POST /api/work-items/{id}/budget/raise takes work_item and an item-wide usd. |
tokens | A token_budget. |
daily | budget.daily_usd. |
Tests and spend
The test_result field
test_result is {scopes: [{command, scope, passed, exit_code, session_id}], passed}, or null when no scope has finished.
- One entry per scope, passed or failed.
scopeisnullwhen the repo's table no longer declares the command, andexit_codewhen none was recorded.passedis true when every scope passed. - An area's setup appears only when it failed.
- A scope still running is left out.
- No test counts.
session_idis the scope's session. Read its log withGET /api/worker-sessions/{id}/log.
The budget_cap field
budget_cap is {cap_usd, source, key, spent_usd, daily}.
cap_usdis whichever cap stops the item first: the lower of its own cap and the item-widebudget_usdof its policy. It isnullwhen neither is set. This holds in the API and inkraft view show --json.keysays which cap it is, and thePATCHfield that changes it:budget_usdfor the item's own cap,policy.budget_usdfor the policy one.sourceisitemwhen the item itself set the reported cap, by its ownbudget_usdor by its ownpolicyoverride, andpolicywhen it comes frompolicy.yamlor the chain. Sosource: itemwithkey: policy.budget_usdmeans the item's policy override.spent_usdis the item's own, all-time spend.dailyis{spent_usd, cap_usd}: the instance's spend since local midnight againstpolicy.budget.daily_usd, the same two numbers asGET /api/budget/today.
POST /api/work-items/{id}/budget/raise (kraft item raise-budget) raises whichever of the two caps stopped the item.
Progress and the worktree
The summary field
summary is a run's progress at a glance:
{"nodes_done": 3, "nodes_total": 8, "gates_passed": 1, "step": {"index": 2, "count": 2} | null}
nodes_done and nodes_total count against the frozen chain. gates_passed is how many of the completed nodes carry a gate after them (gate_after). step is the current node's step (1-based) out of its own steps, read from its latest non-escalation session's task, when the node declares more than one, and null otherwise.
The progress field
progress is {current, total, title, tasks}, or null when the item has no plan to follow. Each task is {n, title, state, sha}. state is done, current or pending, and sha is the short hash of the newest commit on the item's branch that names the task, or null. Rows on the list carry only current, total and title.
The worktree_exists field
worktree_exists is whether worktree_path is a directory on disk. It is false before the item first runs and after its worktree was reclaimed or deleted.
open-worktree, mr-labels and the viewed routes answer 404 when the directory is missing. The message is "this work item has not started, so it has no worktree yet" for an item that never ran, and "this work item's worktree was removed from disk" for one that did. A retry or resume recreates the directory.
diff and compare check the item's base_ref first. Before the first run it is unset: diff answers 200 with an empty diff and base_ref: null, and compare answers 409. With a base_ref set and the directory gone, both answer 404.
The scope_runs field
scope_runs lists every command a changed-test-scope task ran in its node's current pass, in the order each started, across rounds and repositories. Each entry is {session_id, repository, round, command, passed, exit_code?, scope?, area?, setup?, order?, selected?, pending?, node_id, hook_point}. The node's view draws its scopes from it.
passedisnulluntil the command finishes.- A command its round picked that has not started yet comes last,
pending: truewith nosession_id, while the node is still running. roundis the session's fix-loop round,0for the first pass.-1is the repair anon_failurerecovery runs inside a fix-loop node, and the re-measure after it.- A retry starts a new pass, so the list keeps only the newest one.
- It is empty for a chain with no such task.
The fix_target field
fix_target is {gate, node, then, round} while a gate is pending, and null with none pending.
| Key | Meaning |
|---|---|
gate | The pending gate. |
node | The node a request-changes review restarts at. |
then | The nodes that run from there before the work returns to the gate. |
round | The round a rejection now would start, {n, max}, counted against the cap the gate's reject loop already snapshotted. null when no cap applies. |
GET /api/work-items/{id}/fix-target answers the same shape for a target the reviewer picked: see Fix target.
Related
- Filing, reading and changing work items and Gates, run control, ending and retry: the routes that answer these shapes.
- Events: the
stop.kindvalues, thefactsof a stop, and the events behind each field. - Work item statuses: what each stored and displayed status means.
Gates, run control, ending and retry
The board's routes for deciding a gate, pausing, resuming, skipping, escalating, ending, archiving and retrying a work item, and the routes a worker calls.
Budget, events, diff and documents
The board's routes for the daily spend total, raising a budget, the dry run of a create, an item's events, its diff and review, and its documents.