Skip to content

Kanban

What it is for

The kanban service keeps boards of cards in columns for your organization. People work on a board in the browser and their agents work on the same board through these tools: a card created by one is moved, edited or commented on by another, and every board shows who did what. Use it to plan work, see what is waiting, in progress and done, and keep each task's working detail on its card.

It offers a trial, a number of days of free use, and it can also be enabled in full. Enabled in full, it is billed as a subscription rather than per call: a monthly fee that includes a number of active users, and a fee for each further person who used it within the active-user window, in the browser or through an agent acting for them.

Every tool works on this system's own boards only; none reaches outside it.

Working agreements

A board's description, and each column's description, are its working agreements: how the people on the board want the work done. They come with every snapshot of the board, ahead of its cards, so read them first and follow them: what a card needs before it moves to the next column, what "done" means, who picks up what. Changing them is a change to the board's setup.

Active, open and blocked

Every count and line uses these three words one way:

  • An active card is one not archived or deleted, done ones included. A board's activeCardCount counts them, and services.kanban.max-open-cards limits them.
  • An open card is an active card in a column that is not done; its status is open. A card in a done column is done.
  • A card is blocked when it has a blocked reason (blockedReason), or an open blocker: an open card on the same board linked as blocking it, by the card's own blocked-by link or the other card's blocks link. Every card answered says whether it is blocked, either way, in isBlocked; a board open and the stand-up also list each card's open blockers in blockedBy. blockedReason is null on a card held only by an open blocker.

Its tools

Every tool is covered by the subscription: no call is charged on its own, and no tool has a price per call.

Setting a board up (creating, copying, updating or archiving a board, and adding, changing, moving or removing its columns) is for the organization's owners and admins. Working on cards, labels, checklists, links and comments, including moving or archiving a column's cards in bulk, is for any member. An organization's API key holds the admin role.

Every tool but two answers one line of text saying what happened, and the answer itself as structured content held to the output schema the tool declares: ids, etags, sequences and cursors are read from that structure, not from the line. kanban_card_body_read and kanban_card_search answer text, which is their content: a body's lines, and search hits.

Answers name boards, columns, cards, checklists, items, links and comments by their ids, and a card also by its number on the board (#12). Every board and card answer carries its url, the address that opens it in the browser, but for the cards of a board snapshot, whose address is the board's url followed by /cards/<number>.

Tools that only read

  • kanban_board_list lists the organization's boards, most recently updated first, each with its id, link, column and active card counts and sequence; archived: true lists archived boards instead.
  • kanban_board_open opens one board: its working agreements, labels, columns and each column's first page of cards as summaries, never card bodies; each card says whether it is blocked in isBlocked and lists its open blockers in blockedBy. A first-page card leaves out its url, columnId and columnName, which the answer gives once: the page key in firstPages is the card's column id, board.columns names that column, and a card's page is <board.url>/cards/<number>. Its line counts the board's active cards, open and done, and how many of the open cards answered are blocked and how many of those by open blockers. A filter narrows the cards (by text, assignee, label, priority, due date, status, blocked, or mentioning you) and answers each column's match count; blocked: true keeps the cards with a blocked reason or an open blocker, blocked: false the cards with neither; a due of overdue or week also needs your own calendar date as its today.
  • kanban_column_cards reads one page of one column's cards, in board order: the first page, or the next one by following that column's cursor from the board snapshot, with the same filter.
  • kanban_board_activity lists what changed on a board, newest first: each write's sequence, who made it, and when. sinceSequence keeps only the writes after a sequence you read and answers an empty page when nothing has changed, so it is the cheap check of whether a board needs reading again. actor keeps only one member's writes and cardId only one card's. Every answer carries the board's current sequence.
  • kanban_board_standup is a board's stand-up digest: for each assignee, and for cards with none, what was completed since since, and what is in progress, due soon or overdue, and blocked. A card is listed in every section it qualifies for: an assigned card that is blocked or due is also in progress. Only open cards are listed as in progress, due or blocked, and blocked is decided by the same rule a board open's line uses: a blocked reason or an open blocker. Each card says whether it is blocked in isBlocked and lists its open blockers in blockedBy.
  • kanban_card_get reads a card by its cardId or by its number on the board (#12), exactly one of the two: its summary, properties, checklists, cardLinks (its links to other cards), inboundLinks (other cards' links to it) and webLinks (its web addresses), with its cardEtag; never its body. Each link carries the linkId that removes it.
  • kanban_card_body_read reads a card's markdown body, whole or from fromLine to toLine, with its bodyEtag, size and line count.
  • kanban_card_search looks for literal text in card bodies, on one board or on every live board, ignoring case, and answers matching lines (lines, with optional context lines either side), matching cards (cards) or a count of matching lines per card (counts). Archived and deleted cards are not searched.
  • kanban_comment_list lists a card's comments, oldest first, each with its author and commentEtag.
  • kanban_member_list lists the people and agents who can be assigned and mentioned, by display name and handle, and says which one is you.

Tools that add or change things

None of these drops anything a later call cannot set again.

  • kanban_board_create creates boards, several in one call, each with its columns and labels, all or none. A board sent without columns starts with To do, In progress and Done. A column may carry a WIP limit, the most cards it may hold, within the board's wipMin and wipMax; one left out starts at the board's wipDefault, and a WIP limit of 0 means no limit. A done column (done: true) marks its cards done, with doneStatus as their sub-status, such as shipped.
  • kanban_board_copy creates a new board with another board's description, columns and labels under a new name. It copies no cards.
  • kanban_board_update renames a board, replaces its description, or archives (archived: true) or restores (archived: false) it. Only the fields sent change.
  • kanban_column_bulk acts on every card in a column in one write: archive archives them all, and move moves them all to the end of toColumnId, in order. A move is refused, with no card moved, when the target's WIP limit would be passed. It answers the board as kanban_board_open does.
  • kanban_card_create creates whole cards in one column in one call, all or none: title, summary, markdown body, labels by name, assignees by handle, priority, dates, a blocked reason (blockedReason), checklists and web links (webLinks). Card links are added afterwards with kanban_card_links. It is refused when the column's WIP limit would be passed.
  • kanban_card_move places a card in a column after another card, first (afterCardId: null) or, with no afterCardId, last. It changes the card's position only, needs no etag, and is refused when the target column's WIP limit is full.
  • kanban_card_update changes a card in one write, all or none: its title, summary, priority, dates, cover color or blocked reason (blockedReason, null clearing it), the labels (by name) and assignees (by handle) to add and remove, and whether it is archived. Only the fields sent change. archived: true archives the card, the ordinary way to clear a finished card off the board; archived: false brings back an archived card at any time, or a deleted one within the undo window, at the end of its column, and is refused when that column's WIP limit is full. Until it is restored, an archived card's body can still be read with kanban_card_body_read and the card can be deleted, and kanban_card_update takes it (archived: false restores it and archived: true changes nothing); every other card tool answers it as not found, and a body search skips it.
  • kanban_card_copy creates a copy of a card right after it, on the same board only, with the next number: its properties, body, labels, assignees, checklists, card links and web links, never its comments.

More tools that add and change

These add or change and remove nothing; removals are kanban_remove's.

  • kanban_column_write makes one change to one column per call; owners and admins only. With no columnId it adds a column at the end of the board. With a columnId, its name, description, color, WIP limit, done flag or done sub-status change (only the fields sent), afterColumnId places it after another column, or first when null, and restore: true brings back a column removed within the undo window; two of these in one call are refused.
  • kanban_label_write writes one label, found by its name. A name the board has no label for creates one with color, a palette color; a label's name is unique on the board ignoring case. For an existing label, newName renames it on every card that carries it and color recolors it.
  • kanban_card_body_append adds text to the end of a card's body, with nothing put between: start it with a line break to begin a new line. It needs no etag and adds to whatever the body holds when it runs, so calling it twice appends twice. It answers the body's new bodyEtag.
  • kanban_checklist_edit changes a card's checklists by a list of operations, applied in order, all or none: add a checklist with its items (checklist_add), rename one (checklist_rename), add items to the end of one (item_add), or change an item's text, its own due date, its own assignee or whether it is done (item_update). To copy a checklist from another card, read that card and send its items.
  • kanban_card_links adds links to a card in one write, all or none. Each link is either a link to another card on the same board, by its number, as blocked-by, blocks or relates-to, or a web link, an http or https address with an optional title. A card cannot link to itself. The card answers them in cardLinks and webLinks.
  • kanban_comment_write comments on a card as you, in markdown, or edits a comment you wrote, with its commentEtag. An @handle in a comment records a mention of that member: the card then shows as mentioning them, and a filter with mentionsMe finds it for them. Nothing is sent to them. An edit replaces the comment's whole text, keeping no earlier version; another member's comment is refused.

Tools that replace or remove content

These two can drop something a later call cannot set again. A removed card and a removed column can be restored within the undo window, and a removed card is purged for good once the retention period after it passes. Nothing else they replace or remove can be brought back.

  • kanban_remove removes one kind of thing per call, named by kind, with the ids that kind takes and no others: a card (cardId), a comment you wrote (cardId, commentId), card links (card_link: cardId, linkIds from the card's cardLinks), web links (web_link: cardId, linkIds from its webLinks), a checklist (cardId, checklistId), checklist items (cardId, checklistId, itemIds), a column (columnId) or a label (labelName). A list removes all its ids or none. Columns are owners' and admins' only. A column that holds cards cannot be removed: empty it first with kanban_column_bulk; a board's last column cannot be removed. kanban_card_update with archived: false brings back a removed card, and kanban_column_write with restore: true a removed column, within the undo window. Archive a card instead to clear it off the board without losing it.
  • kanban_card_body_write rewrites a card's body with its bodyEtag: either the whole new body, or a list of edits, applied in order, each to the body the ones before it left, and all or none; exactly one of the two. An edit is a find copied exactly from the body with the replace that takes its place (an empty replace deletes the text). Each find must occur exactly once, unless that edit's replaceAll is true. Matching is literal and case-sensitive, spacing and line breaks included. If any find is not found, or is found more than once, nothing changes and the refusal names that edit's index and how many matches it had.

Read before you write

A card's properties, its body and each comment carry an etag of their own, named for what it guards: cardEtag, bodyEtag and commentEtag. Each changes whenever that part changes. Rewriting a card's body needs the bodyEtag from reading the body, from the create or copy that made the card, or from the last body write, and editing a comment needs the commentEtag from listing the comments or from the add. Updating a card checks the cardEtag from reading the card when you send it; left out, the fields sent are written over whatever the card holds. A write given an etag the row has moved on from is refused, naming the etag field and carrying currentEtag, the etag the row is at now, and changes nothing, so a change another person or agent made meanwhile is never overwritten unseen. What to do next depends on the write, and the refusal says which:

  • A body write sent as edits may be retried at once with currentEtag as its bodyEtag: each find is matched against the body as it is then, so an edit whose text has changed is refused rather than applied blindly.
  • Every other write, a whole body, a card update or a comment edit, would write over the change it was refused for: read again, look at what changed, then retry with the new etag.

Labels, assignees, archiving, moves and checklist changes leave the cardEtag as it was, so they never stale a read you are about to write from.

Work on a body in a loop of read, edit, re-read: read the lines you mean to change, edit them with the bodyEtag the read returned, and keep the new bodyEtag the write answers for the next edit, because the text has moved. A body read answers the text as stored, under a header naming the lines it holds, and a body search shows each line with its card number and line number in front: neither the header nor those prefixes are part of the body, so leave them out of a find, or it will not match.

What a write answers

A write answers the ids it created and the values the server decided, never what you sent:

  • kanban_card_create answers each card's cardId, number, cardEtag and bodyEtag, its checklists' checklistId with their items' itemIds, and its web links' linkIds, every list in the order you sent it, so you can tick an item, update the card or write its body with no read first.
  • kanban_card_copy answers the copy's cardId, number, cardEtag and bodyEtag, and each new checklist, item and link id paired with the source's (fromChecklistId, fromItemId, fromLinkId).
  • kanban_card_update, kanban_checklist_edit, kanban_card_links and kanban_remove of a card kind answer the card's cardId and cardEtag, plus the ids they made (checklists with itemIds for a checklist edit that added something, linkIds for links added) and isBlocked only when the write could change it: a blockedReason set or cleared, or a blocked-by link added or removed.
  • kanban_card_body_write and kanban_card_body_append answer the body's new bodyEtag, and a find-and-replace its replacements; send returnBody: true for the body itself.

Send returnCard: true on a card write when you want the whole card back, as kanban_card_get reads it, with every checklist and link; a create or copy then answers each whole card with its bodyEtag. Removing a column or a label answers the board and takes no returnCard. The tools that take returnCard are exactly kanban_card_update, kanban_checklist_edit, kanban_card_links, kanban_card_create, kanban_card_copy and kanban_remove of a card kind.

Working together

Repeating a create safely. The creates of boards, cards and columns, the board and card copies, and a card's checklist and link writes take an idempotencyKey: any string unique to that call (on a batch of boards or cards, only the first entry carries it). Repeat the call with the same key and it answers what the first call made, as it stands now, instead of making it again. A key whose first attempt failed, or is still running, is refused as in flight: read the board to see what is there, then retry with a new key if it is still needed. A label write and a comment take no key: a repeated label write finds the label it made, and a repeated comment is posted twice.

People and agents by handle. Members are named by opaque handles from the member list, never by id or email: an assignee, a checklist item's assignee, the actor of an activity read, and an @handle mention. me names you, for a person and for an agent the member list shows; for a caller the members do not list, the list's me is null and naming me is refused.

Changes that are safe to repeat. Adding a label a card already carries, assigning a member already assigned, removing what is not there and setting an item to the state it is already in are no change, so these calls are safe to repeat.

Who did what. Every write that changes the board raises its sequence and answers the new one: by one for each change it records, so a card create raises it once per card it creates. The board's activity names each write's actor by display name and handle and marks a person's change made through an agent "via AI", so people on the board can tell their own edits from their agents'. Before re-reading a board, read its activity since the sequence you hold: an empty page means nothing has changed.

Paging

The board list, a column's cards, a board's activity, a card's comments and a body search answer a page at a time, each with a cursor: while there is a next page, pass it back with every other argument unchanged to read it; a null cursor marks the last page. A body search, which answers text, ends with a "More" line naming the cursor while there is a next page, and has no "More" line on its last page.

A board snapshot holds each column's first page only, with that column's own cursor; read the rest of a column with kanban_column_cards.

A card body read whole is bounded by the read bound in the tool's description. A line range stops at that bound and answers truncated: continue from the line after the last one answered. A body search page likewise stops after a bounded amount of reported text and answers truncated with a cursor.

The activity feed keeps a board's history for the retention period only. Its answer's oldestRetained is the lowest sequence still kept; anything older has been purged, so a gap below it cannot be read.

The stand-up digest is judged against your dates, not the server's: send since (yesterday, for a daily stand-up) and today as your own calendar dates, and the answer states both. Each of its lists shows a bounded number of cards and counts the rest in more.

Its settings

Your organization's own limits, each capped by a platform ceiling of the same key with -ceiling added (services.kanban.max-boards-ceiling); the smaller of the two is the limit in force:

  • services.kanban.max-boards: the boards the organization may hold, archived boards included;
  • services.kanban.max-open-cards: the active cards one board may hold, done ones included;
  • services.kanban.max-cards: the cards one board may hold, archived cards included;
  • services.kanban.max-columns: the columns one board may have;
  • services.kanban.max-labels: the labels one board may define;
  • services.kanban.max-checklists: the checklists the cards of one board may hold in all;
  • services.kanban.max-checklists-per-card: the checklists one card may hold;
  • services.kanban.max-items-per-checklist: the items one checklist may hold;
  • services.kanban.max-attachments-per-card: the links one card may carry;
  • services.kanban.max-assignees-per-card: the assignees one card may have;
  • services.kanban.max-comments-per-card: the comments one card may hold;
  • services.kanban.max-body-bytes: the largest card body, in UTF-8 bytes;
  • services.kanban.max-comment-bytes: the largest comment, in UTF-8 bytes.

services.kanban.wip-default is the WIP limit a new column starts with, within the platform's lowest and highest WIP limits, services.kanban.wip-min and services.kanban.wip-max. A WIP limit of 0 means no limit.

The platform's own:

  • services.kanban.undo-window-ms: how long a deleted card or a removed column can still be restored;
  • services.kanban.retention-deleted-days: how long a deleted card or removed column is kept before it is purged;
  • services.kanban.retention-idempotency-hours: how long a create's idempotencyKey is kept, and so how long a repeat with it answers the first result;
  • services.kanban.retention-activity-days: how long a board's activity is kept;
  • services.kanban.trial-days: the days of free use a trial grants;
  • services.kanban.active-user-period-days: the trailing window within which a person or agent who used the service counts as an active user;
  • services.kanban.included-users: the active users the monthly fee covers.

Its limits

Each count and size refuses at its limit. A write that would take a board, a card or the organization past one of the limits above is refused, names the limit it would pass, and changes nothing; nothing already stored is lost. Lowering a limit deletes nothing either: it only refuses the next write past it. There is no warning level before a limit: a write either fits or is refused. The values are settings and can change, so they are not written here.

A WIP limit is a column's own. A card create, move, copy or restore, or a bulk move of a column's cards, that would put more cards in a column than its WIP limit is refused whole. The board in the browser shows each limited column's count against its limit.

One call is bounded. How many boards or cards one create makes, how many checklist operations or links one call applies, how many edits one body edit applies and how many replacements it makes, and how much one body read or search page returns are fixed bounds, each stated in its tool's description.

A body search is literal text, matched within one line and ignoring case, so it cannot contain a line break.

Bodies and comments are markdown, and a card or comment names another member with an @handle mention, which is recorded on the card; nothing is sent to that member.

Names, titles and other short text are one line. A board, column, label or checklist name, a card's title and summary, a checklist item's text, a done sub-status, a blocked reason and a web link's title cannot contain a line break. A description, a body and a comment can.

Kanban