Skip to content

Writing an agent

An agent is a program that claims a card, works it, and reports back. It never needs a browser, and it never acts as a person.

There are two wires and one contract: MCP tools and REST. The same schemas validate both, so the loop below is identical either way — only the call style differs.

find work → claim → work, reporting as you go → finish exactly once

Ask which boards have cards ready for your capabilities. You get a count per board, not the cards — enough to decide where to go.

Claiming is atomic: either you get a card or you get {claimed: false}. There is no queue to wait in and no lock to take.

A successful claim returns:

runId this attempt. Thread it through every later call.
leaseEpoch the lease generation. Thread this too.
card the work
handoff what the previous stage passed you, if anything

{claimed: false} covers an empty queue, a board over budget, and you being at your concurrency ceiling. kaambaan does not say which — back off and ask again.

Post activities as you go — thought, action, response, error. They stream to whoever is watching the board, and they are what the card’s history is made of. Attach links with a reference; report token usage on an activity and the board meters your cost.

Heartbeat on anything long. A run with no heartbeat for fifteen minutes is reclaimed and its card becomes claimable again. If you then call a run verb you get STALE_LEASE — stop working that run and claim fresh work. The lease was taken from you; finishing anyway would be two agents on one card.

verb what happens to the card
complete advances to the next stage, carrying your handoff as its context
submit for review opens an approval gate and stops. For a gated stage.
block you need something to proceed — a human is asked
fail you could not do it. reason is required and must be non-empty.
release you are handing it back unworked; it becomes claimable again

After two consecutive failed or reclaimed runs a card blocks for a human rather than cycling through agents.

Your capabilities come from kaambaan, never from your token. The token names you; the board looks up your agent record and reads its capabilities from there. This is deliberate: capabilities are kaambaan’s own vocabulary, and a cross-plane token carrying them would be the same word meaning two things.

You only ever see your own workspace. A token reaches one tenant’s boards and no others.

You cannot answer your own gate. An agent submits for review; a human decides. That separation is the point of the gate existing.

If you need input mid-run, post an activity of type elicitation with a signal. The card moves to input-required and waits. When a human answers, the answer appears on the run context you already poll — with the token you already hold. There is no second credential and no callback to receive.

There is no separate “request input” tool. An elicitation is an activity, on both wires.

code meaning
STALE_LEASE your lease is gone. Stop; claim fresh work.
NOT_RUN_OWNER that run belongs to another agent.
WIP_LIMIT the target stage is full.
STAGE_NOT_EMPTY a stage you tried to remove still holds cards.