Agent output format¶
Agent mode (--agent, or --format agent) is a compact, stable text contract
for coding agents. It exists alongside JSON, not instead of it: agent mode is
for short action acknowledgements that a human can scan and an agent can
pattern-match without a JSON parser, while --json remains the complete
machine-readable API. See output modes for
the high-level picture and the CLI reference for per-command flags.
This page documents the agent format as a contract. Tooling may rely on the guarantees described here.
Selecting the mode¶
kata list --agent # agent text
kata list --json # full JSON envelope
kata list --format agent # equivalent to --agent
kata list --format human # default terminal output
--jsonand--agentare aliases for--format jsonand--format agent.- Passing several output-mode flags that resolve to the same mode is valid
(
--format agent --agent). Flags that resolve to different modes are a usage error before the command runs. --quietis orthogonal: a suppression flag, not a mode. In agent mode it may suppress theOK ...success header where a command already has quiet behavior, but it never suppresses anERR ...line.--formatis reserved globally for output mode.kata importselects its source format with--source-format <kata|beads>.
Stability contract¶
Agent output is plain UTF-8 with no ANSI styling. Its shape is stable:
- In non-quiet agent mode the first token is always
OKfor success orERRfor failure. Success goes to stdout; failure goes to stderr with a nonzero exit code. - The second token is the command or record kind:
create,comment,list,show,event, and so on. The literalkataappears only on a top-level parse error before a subcommand runs. - Remaining first-line fields are stable positional fields where this document
specifies them, and
key=valueotherwise. Field order is part of the contract. - New fields may be appended to a line or block. Existing field names, first tokens, and their meanings do not change without an agent-format version bump.
- List-valued fields are comma-separated with no spaces (
labels=bug,safari). - Nullable free-form fields are omitted when absent. Agent output never
emits sentinel values such as
owner=nullorowner=unowned, because a user could legitimately choose those exact strings as an owner name. - Values containing whitespace, quotes, or control characters are double-quoted with Go/JSON-style escaping; simple tokens stay unquoted.
Version¶
The current agent format version is 1. A breaking change bumps this integer.
Discover it without parsing JSON:
The same value appears as agent_format in kata version --json; the complete
JSON schema is documented in the CLI reference.
Ordinary command output does not repeat the version, to keep transcripts small.
Errors¶
ERR list not_found: no .kata.toml ancestor and no git ancestor
Hint: run "kata init --project <name>" in the workspace root, or pass --project <name>
- The first line is
ERR <command> <kind>: <message>. - Create idempotency and look-alike conflicts append the existing issues'
qualified refs, for example
ERR create conflict: 1 existing issue matches this title (example-project#abc4). <kind>reuses the CLI error taxonomy:usage,validation,not_found,conflict,confirm,daemon_unavailable,checks_failed,internal.checks_failedmeanskata doctorcompleted and found failed checks; consult its findings for the setup problems and suggested fixes.- An optional second line,
Hint: <next step>, names a command or flag that can resolve the error. It is always a single line. - A top-level parse error, before any subcommand runs, uses
kataas the command token:ERR kata usage: unknown command "cretae". - In
--format jsonerrors include daemon-provided details inerror.dataand next-step guidance inerror.hintwhen present. An absent or empty hint is omitted. Human errors print that guidance on a secondhint:line; agent errors use a separateHint:line.
Success shapes¶
Mutations¶
A mutation line names what happened and which issue changed, with changed= and
reused= flags where they apply, followed by block lines:
An Undo: line is emitted only when the follow-up is factual and mechanically
correct. Generic Next: guidance is intentionally not part of the format.
Reads¶
A read emits an OK <command> count=<n> header followed by one row per record:
OK list count=3
- issue=abc4 status=open priority=2 owner=agent-a labels=bug,safari title="Fix login race" revision=4
- issue=def7 status=open labels=architecture title="Control channel" revision=1
- issue=j9k2 status=closed title="Old task" revision=3
List and search headers include complete=true|false when the daemon returns
page metadata. A page with continuation adds next_cursor=...; a list requested
with --include-total also adds total=<n>. Treat the cursor as opaque and
continue with the same filters. See CLI reference for the
CLI flags and HTTP listing for the scan contract.
Empty reads emit the header with count=0 and no rows:
kata update --check --agent appends package ownership fields after the
existing result fields, in this order:
OK update update_available=true current=v0.14.1 latest=v0.14.2 distribution=homebrew upgrade_hint="brew upgrade kata" package_release_may_lag=true
The field order is update_available, current, latest, distribution,
optional upgrade_hint, then package_release_may_lag. Ordinary archives emit
distribution="" package_release_may_lag=false and omit upgrade_hint.
Install-capable forms on package-managed builds use the existing usage error
shape and exit code 2:
The check reads Kata's GitHub release feed, so a reported release can appear before the owning package manager publishes it.
Federation quarantine discovery¶
kata federation quarantine list --agent emits one row per active quarantine:
OK federation-quarantine-list count=1
- project=spoke-project project_id=7 quarantine_id=3 direction=push first_event=41 last_event=44 event_count=4 created_at=2026-07-10T12:00:00Z error="hub rejected batch"
The row field order is project, project_id, quarantine_id, direction,
first_event, last_event, event_count, created_at, and error. An empty
list emits only OK federation-quarantine-list count=0.
kata federation quarantine show <id> --agent emits the owning project and
batch summary followed by one row per quarantined event UID:
OK federation-quarantine-show quarantine_id=3
- project=spoke-project project_id=7 direction=push first_event=41 last_event=44 event_count=4 created_at=2026-07-10T12:00:00Z error="hub rejected batch"
- event_uid=01HZNQ7VFPK1XGD8R5MABCD4EA
- event_uid=01HZNQ7VFPK1XGD8R5MABCD4EB
The event UID rows preserve the order recorded for the quarantined batch.
Operators can inspect these read-only commands before invoking the separately
confirmed quarantine retry or quarantine skip mutation.
kata search appends a mode= field to its header (lexical, hybrid, or
semantic) reporting the strategy actually run. When the embedding endpoint is
configured but could not serve a query, the search falls back to lexical and a
degraded=<reason> field follows mode=; it is omitted when the query was not
degraded. Result rows carry matched= listing the contributing sources (FTS
column names), and a row gains semantic in that list when the vector leg
matched it:
OK search count=1 query="auth redirect duplicates" mode=hybrid
- issue=abc4 score=0.0312 status=open matched=title,semantic title="Login callback double-submits on Safari" owner=agent-a priority=1 revision=4 excerpt="The callback can submit twice after the auth redirect."
Search rows append owner, priority, revision, and a body excerpt when present.
The excerpt is at most 160 characters and centers the first query match when
possible, folding case and diacritics like lexical search. kata show <ref>
--agent remains the complete record and emits Revision: after Priority:.
List rows append revision after title. Existing fields keep their names,
positions, and meanings, so agent_format stays 1.
A daemon without [search.embeddings] reports mode=lexical and omits
degraded=. It includes the same added issue context.
Teams, project access, bridges and root keys¶
The team and project-access commands follow the mutation and read shapes.
teams list is a read with one row per team; teams show reports its
members as a comma-separated list and omits members= when the team is
empty, as projects access omits teams= for visibility=all:
OK teams count=1
- team=reviewers uid=01HZNQ7VFPK1XGD8R5MABCD4EA revision=2
OK teams-create team=reviewers uid=01HZNQ7VFPK1XGD8R5MABCD4EA
OK teams-show team=reviewers uid=01HZNQ7VFPK1XGD8R5MABCD4EA revision=2 members=alice,bob
OK teams-members-add team=01HZNQ7VFPK1XGD8R5MABCD4EA actor=alice
OK teams-members-remove team=01HZNQ7VFPK1XGD8R5MABCD4EA actor=alice
OK projects-access project=spoke-project visibility=teams revision=3 teams=01HZNQ7VFPK1XGD8R5MABCD4EA
The bridge and root-key commands emit one line each. warning= appears only
when the daemon reported one, and key_file= only when the daemon has a key
file path:
OK federation-bridge-connect project=spoke-project status=ready direction=bidirectional hub=example-hub upstream_account=member local_account=local-member
OK federation-bridge-status project=spoke-project state=connected direction=bidirectional credential_status=active hub=example-hub upstream_account=member local_account=local-member
OK federation-bridge-disconnect project=spoke-project status=disconnected warning="the hub grant was not revoked"
OK federation-root-key-repin project=hub-project status=ready method=unsigned_repin key_id=01HZ... previous_key_id=01HY... creates_key_file=true active_relay_enrollments=2 key_file=/srv/kata/federation-root.key
Single-result next¶
kata next --agent is an intentional exception to the usual read shape of a
count=<n> header followed by n rows. It emits exactly one compact record
when a ready issue is selected:
The field order is issue, optional priority, optional owner, then
title. Absent priority and owner values are omitted rather than rendered as
sentinels. A cross-project selection uses a qualified value such as
issue=example-project#abc4.
An empty ready set is also a successful single record:
With --full, the success header identifies the selected ref and is followed
by the same detail fields and sections as kata show --agent:
The show sections for labels, body, metadata, links, comments, and leases are included when present. Their existing ordering and omission rules apply.
Compact issue status¶
kata status <ref> --agent keeps the authenticated identity, assignment, and
lease state separate on one line:
OK status issue=abc4 project=example-project issue_status=open revision=4 actor=agent-a actor_source=daemon auth=db_token instance=01HZNQ7VFPK1XGD8R5MABCD4AB owner=agent-a assignment_expires_on=2026-09-02T12:30:00Z hold=assigned
The fixed field order is issue, project, issue_status, revision,
actor, actor_source, auth, instance, optional owner, optional
assignment_expires_on, and hold. An
active or expired lease then appends optional holder, holder_instance,
lease_kind, and expires_at; pending leases append pending_leases. Hold
state is one of active, expired, pending, assigned, unassigned, or
closed. assigned identifies an open issue with a live owner assignment and
without a live or pending lease. A successful temporary kata claim yields
hold=assigned and assignment_expires_on; once due it yields hold=expired
until cleanup records the expiry, then hold=unassigned until another hold
applies.
actor_source is daemon when the daemon authenticated the actor; otherwise it
is the client-side source reported by kata whoami. Use
kata show <ref> --agent when the body, comments, metadata, links, or lease
violations are needed.
Events¶
Non-tail reads use a header plus rows; tail mode is stream-safe and emits exactly one line per event:
OK events count=2 next_after_id=44
- id=42 type=issue.created issue=abc4 actor=agent-a
- id=43 type=issue.commented issue=abc4 actor=codex
kata events --tail --json is newline-delimited JSON; kata events --tail
--agent is one agent line per event and never emits multi-line blocks.
Multiline text¶
Bodies and comments are preserved in fenced text blocks:
OK show abc4
Issue: abc4 "Fix login race"
Status: open
Revision: 4
Body:
```text
Safari can double-submit the callback.
```
- No silent truncation is allowed. If truncation is ever introduced, the
metadata fields immediately precede the field they describe and are emitted as
a pair,
<Field>-Truncated: trueand<Field>-Bytes: <full-byte-count>, never one without the other. - A fenced block uses at least three backticks and the
textinfo string. If the content itself contains a triple-backtick sequence, a longer fence is chosen so the block stays valid Markdown.
Guarantees¶
--jsonis never weakened or removed; it stays the complete structured API.- Agent mode does not change daemon API responses; it is purely a CLI rendering of the same data.
- Agent mode is not the default.
- Interactive commands (
kata tui) and daemon startup (kata daemon start) reject agent mode with a usage error rather than launching.