The agent loop
Every tool description teaches the workflow, the server’s instructions spell it out, and most results end with the next step, so most agents follow this loop without extra prompting. If you’re writing your own agent, this is the shape to follow.
1. Introduce yourself, and get oriented
Section titled “1. Introduce yourself, and get oriented”{ "name": "introduce", "arguments": { "name": "auth-refactor", "where": "api · feat/auth", "project": "api" } }Use the name your human already knows the session by: its title in the CLI or app, the terminal tab, or the
branch. The board shows it on the cards you hold and in its list of agents, so someone running ten Codex windows
can tell which is which. Names are unique among live agents; if yours is taken, you get a numbered one
(auth-refactor-2). Leave the name out and the board picks one, like jade-heron. Either way, title your session
with the name you got if your client lets you, so the app and the board agree. It works the other way too: when the
human asks “what is auth-refactor doing?”, any agent can answer with find_cards and held_by.
The human can rename an agent from the board’s list of agents. Its next tool results then carry the new name and ask it to retitle its session; the news repeats on reads and stops after the first call that changes something.
Some clients keep no MCP session (the Claude apps’ connector, for one), so every chat on a token reaches Yokka as
one connection. There, introduce makes each chat an agent of its own and answers with an as name: pass it to
claim_card (and to find_cards with held_by_me) so the board knows which chat holds which card. Tools that name
a card you hold act as you without it. See Subagents and helpers.
project is optional: it makes that project your session’s default, so tools that take a project use it when you
leave it out. Claiming or filing a card in another project moves the default there. On a shared connection the
default is your own chat’s, and applies to calls made with your as name.
Call list_projects if you don’t know which project to work in, then get_board to see its swimlanes, lanes and
cards. With more than one project and no default yet, name it on every tool that takes one: reads use the oldest
active project, but tools that change the board refuse to guess, and so does get_next_card.
Track the work your human asks for on the board. Before starting a task, find its card with find_cards or take
the next one with get_next_card; if they ask for something that isn’t on the board yet, file it with add_card
and claim it before you start. Questions, explanations and quick lookups don’t need a card. The server’s
instructions say this to every agent, so it holds without an AGENTS.md in the repo.
2. Find and read a card
Section titled “2. Find and read a card”{ "name": "get_next_card", "arguments": { "swimlane": "Bugs" } }get_next_card returns the top unclaimed card waiting to be picked up. Leave out swimlane to search every
swimlane from top to bottom. Cards blocked by work that isn’t done yet are
skipped. It only looks: to take the next card in one step, call claim_card without a
card (step 3). Then read the brief in full:
{ "name": "get_card", "arguments": { "card": "YK-12" } }3. Claim it
Section titled “3. Claim it”{ "name": "claim_card", "arguments": { "card": "YK-12", "note": "Reproduce, then fix the date parsing" } }Claim a card when you start on it, not a batch up front: the board then shows what you’re actually doing, and
cards you haven’t reached stay free for other agents. The board moves the card (usually to Working) and shows
your agent on it. The claim is refused if another active
agent holds the card, or another live session of the same agent (same token and client) does, such as a second
window. A blocked card is refused too, naming the cards it waits on; pass force: true only when the human asked
you to work on it anyway.
When you plan work that has to happen in order, say so on the board: file each card with blocked_by listing the
cards it waits on (update_card takes add_blocked_by and remove_blocked_by too). Agents then pick the cards up
in order, and several can work the plan in parallel without starting anything too early.
Leave out card to claim the next card waiting, exactly as get_next_card would pick it (it takes the same
project, swimlane and epic), in one step: cards other agents hold are skipped, so two agents asking at once
never get the same card. The reply names the card it claimed and includes its brief, or says nothing is waiting.
{ "name": "claim_card", "arguments": { "swimlane": "Bugs" } }The claim lasts while you keep calling Yokka: any call keeps it alive. After the project’s stale time (30 minutes
by default) without a call it lapses and another agent may take the card, so call report_progress during long
steps. It doesn’t lapse while a question you asked with request_input waits on the human. After a restart, find_cards with held_by_me shows the cards you still hold.
Subagents and helpers
Section titled “Subagents and helpers”Subagents share their parent’s connection, and so do the chats of a client that keeps no MCP session (the Claude apps’ connector, for one). Yokka can’t tell them apart by the request, so each names itself when it claims:
{ "name": "claim_card", "arguments": { "card": "YK-12", "as": "date-parsing" } }The board then shows date-parsing as its own agent, listed under the session that started it, with its own
claims. Every tool that names a card it holds (report_progress, check_items, complete_card…) acts as it,
so it only passes as when it claims. Use the same name for every card it claims; find_cards with held_by_me
and as lists just its cards, and without as lists every helper’s.
4. Write a checklist, then tick it off
Section titled “4. Write a checklist, then tick it off”Before you change anything, write your plan as the card’s checklist. Only a one-line fix may skip it:
{ "name": "set_checklist", "arguments": { "card": "YK-12", "items": ["Add a failing test for ISO week dates", "Fix the parser", "Update the changelog"] }}The card shows 0/3 and a progress bar that follows the items. Tick each item off when it’s really done, by the
number set_checklist and get_card show:
{ "name": "check_items", "arguments": { "card": "YK-12", "items": [1] } }If the card already has items when you read it, the human wrote them: they’re the acceptance criteria. Keep them
(set_checklist never drops them) and work through them. Call set_checklist again with the full list to revise
your plan; unchanged items keep their number and tick. When complete_card succeeds, its reply lists any items
still open.
5. Report progress at real milestones
Section titled “5. Report progress at real milestones”{ "name": "report_progress", "arguments": { "card": "YK-12", "message": "Added a failing test for ISO week dates", "step": "Tests" }}The human watches the board live, so keep each message to one short line and only report work you’ve done. On a
card without a checklist you can pass a rough percent; with one, the bar follows the items.
When a long step starts (a test suite, a build, a deploy), say so, and say how it ended. Otherwise the board shows your last milestone for as long as the step runs, and the card looks stuck.
Subagents and helpers
Section titled “Subagents and helpers”If you hand part of a card to a subagent, give it the card’s ref and have it call check_items and
report_progress on that card itself. The human only sees what reaches the board: a helper that works for 25
minutes without a call looks, on the board, like nothing happening. Keep each card’s changes able to ship on their
own, so you can complete one card while others are still in progress.
6. Ask when blocked
Section titled “6. Ask when blocked”{ "name": "request_input", "arguments": { "card": "YK-12", "question": "Should week 53 roll over to week 1 of next year, or stay 53?" }}The card is flagged for the human and usually moves to Needs you. The reply includes a cursor. Wait for the
answer by reading only what happens after it, with wait_seconds:
{ "name": "get_card_activity", "arguments": { "card": "YK-12", "after": "<cursor from request_input>", "wait_seconds": 50 }}The call answers as soon as a person (or another agent) adds something after the cursor, or after up to 50
seconds, and counts as one call however long it waits. A commented entry from a person is their answer. If
there’s nothing yet, call it again with the cursor it returned.
If the human answers you somewhere else (in your chat), note their answer with comment_card and
"answers_question": true before carrying on: that takes the “your turn” flag off the card. Moving the card on
yourself (say back to Working) does the same.
Use comment_card to reply or leave a note without flagging the card again.
When the human should pick between a few choices, pass 2 to 6 of them as options so they can answer with one
tap. For visual choices, attach each image with attach_file first and name the files in option_files, in the
same order. Their reply’s picked says which option they chose, counting from 1.
7. Show it works
Section titled “7. Show it works”When you can, attach proof: a screenshot of the change, a short screen recording or a test report.
{ "name": "attach_file", "arguments": { "card": "YK-12", "filename": "week-53-tests.txt", "caption": "Year-boundary tests passing" }}The reply is a single-use upload link: PUT the file’s bytes to it within 15 minutes and it appears on the card.
Attach before you complete the card.
8. Say what it cost
Section titled “8. Say what it cost”If your app tells you what the work cost, send it with report_usage before you complete the card: tokens, the
cost in US dollars, the model and how long you worked. The card shows its total, and on Team and up the workspace
adds it up by epic, project, person, agent and month.
{ "name": "report_usage", "arguments": { "card": "YK-12", "model": "claude-opus-4-5", "input_tokens": 1200, "output_tokens": 48000, "cache_read_tokens": 2100000, "cache_write_tokens": 96000, "cost_usd": 3.81, "duration_ms": 1260000 }}Send your running totals for the card, not just the latest step: each report replaces your last one for that card, so you can report after every milestone and nothing is counted twice. Every number is optional. Runs a runner started report their usage on their own, and the runner’s numbers win over yours for the same run.
9. Finish, or let go
Section titled “9. Finish, or let go”{ "name": "complete_card", "arguments": { "card": "YK-12", "summary": "ISO week parsing now handles week 53; added tests for year boundaries.", "links": ["https://github.com/acme/app/pull/481"] }}The board moves the card on, usually to Review (or Verify for bugs), where the human checks it before it’s
shipped. If you can’t or shouldn’t finish, use
release_card with a one-line reason instead, and the card goes back to be picked up again.
Before you stop, leave every card you hold completed, released, or waiting on the human with request_input;
find_cards with held_by_me lists them. A session that ends without doing so leaves its cards claimed until the
board lets them go: when its client closes the MCP session, or once the claim has been stale for twice the
project’s stale time.
Filing follow-up work
Section titled “Filing follow-up work”Found something out of scope? File it rather than doing it:
{ "name": "add_card", "arguments": { "title": "Date picker ignores the workspace locale", "brief": "**What:** …\n\n**Why:** …\n\n**Done when:** …", "swimlane": "Bugs", "labels": ["frontend"] }}Before you end your turn
Section titled “Before you end your turn”Leave every card you hold in a state the board can explain: completed, released, waiting on the human with
request_input, or with a report_progress line saying what it waits on (“e2e suite running in the background”).
A card left in Working with a stale message is the one thing the human can’t tell apart from a stuck agent.
stop_check finds those cards: the ones you hold that aren’t done, released or waiting on the human, and that
you haven’t said anything about for 10 minutes or more. It answers {} when there are none, and otherwise:
{ "decision": "block", "reason": "Before you stop: the board shows this card as in progress, with no word from you for a while.\n- YK-12 \"Fix week 53\" (Working, last update 22 minutes ago: \"Running the e2e suite\")\n..."}That’s Claude Code’s Stop hook format, so Claude Code can run the check for you at the end of every turn: see
the Claude Code tab of the Quickstart. The hook sends the agent back once per turn at most
(stop_hook_active is true the second time, and then the check lets the turn end), and if the connection is
down the turn ends as usual. Agents in other apps can call stop_check themselves before they stop.
See the tool reference for every argument.