Skip to main content
Kanban enables agents to coordinate through persistent tasks, creating a shared workspace where work is tracked and distributed across multiple agents.
The user asks for a feature; the coordinator creates tasks workers pick up from the shared board.

Quick Start

1

Create Agent with Kanban Tools

2

Add Worker Agent


How It Works

Task coordination happens through a SQLite-backed persistent store that all agents and the UI share.

Concepts

Task Statuses

Tasks flow through 8 defined states from creation to completion:

Boards

Boards provide workspace isolation for different projects or contexts: Tasks form directed acyclic graphs through parent-child dependencies:

Claim/Release

Workers coordinate through atomic claim and release operations:

Agent Tools

Kanban tools are available through the SDK protocols. The wrapper implementation provides these agent tools:

Task Management

Status Changes

Coordination


Boards & Storage

Single Board (Default)

Multi-Board Layout

Environment Configuration


Attempt History & Retry

Each kanban task records every attempt, auto-blocks after repeated failures, and hands off a structured summary on completion.
1

Idempotent create with retry limit

2

Structured completion handoff

3

Read attempt history on retry

What the dispatcher does automatically

When a worker claims a task, the dispatcher opens a run with the claim — anything the worker writes via kanban_complete closes it as completed, anything that crashes closes it as crashed/failed. Below the max_retries limit, failed attempts release the claim and put the task back on ready for re-dispatch. At the limit, the task auto-blocks with gave_up so a human can step in. A successful completion resets the failure counter — the limit is consecutive, not cumulative.

New params on kanban_create

New params on kanban_complete

kanban_complete moves the task to done before recording the run. A move_task failure never leaves an orphaned completed run for a task that never reached done.

New tool: kanban_runs

Each row matches the KanbanRunProtocol shape:

New Task fields

Existing SQLite databases are auto-migrated on first open — no user action required.

Common Patterns

Automation-safe creation — pass idempotency_key derived from the trigger (f"github-issue-{n}", f"webhook-{uuid}"). Re-firing the webhook is a no-op instead of spawning duplicates. Idempotency is per-board, per-tenant — two tenants on the same board never collide on the same key. Long-running flaky network tasks — set max_retries=5 per task to absorb transient flakes without giving up too early. Watch consecutive_failures in kanban_show to spot stuck tasks. Retrying workers use prior failures — call kanban_runs(task_id) at the start of a retry attempt to read prior outcomes and errors. Use summary and metadata from the most recent failed run as context: “previous attempt crashed at line X; avoid path Y.”
Webhooks, schedulers, and GitHub-issue triagers should always pass an idempotency_key. The cost is one extra string; the value is zero duplicate tasks under retry.
Fast deterministic work: max_retries=1. Flaky network or integration tests: max_retries=3–5. Leave the rest at the board default (3).
Use summary and metadata in kanban_complete instead of free-text comments. Downstream child tasks and retrying workers consume the structured fields; humans still read them fine.
The structured run history is the cheapest “what went wrong last time” context a retrying worker can fetch. Call kanban_runs(task_id) at the start of every retry attempt.

Common Patterns

Coordinator-Worker Pattern

Background Processing

Worker with Heartbeat

Human-Agent Collaboration


Runs, Retries, and Structured Handoff

Kanban now tracks every execution attempt for each task via the task_runs table, supports per-task retry limits, and allows agents to pass structured data when completing a task.

kanban_complete — structured handoff

kanban_create — idempotency and retries

kanban_runs — per-task run history

List all execution attempts for a task:
Each run record contains:

Auto-block after max retries

When max_retries > 0 and the task accumulates that many "failure" run outcomes, the dispatcher automatically moves the task from running to blocked. The task must be manually unblocked (kanban_move(task_id, "ready")) after the root cause is resolved.

Per-Task Worktree Isolation

Give every kanban worker its own git worktree so parallel tasks never overwrite each other’s files.
For CLI, per-run isolation (not per-task), see praisonai run --worktree.
One keyword moves a task onto its own branch and working directory. Everything else — creation, merge-back, and cleanup — happens automatically.

Auto-upgrade for repo-linked tasks

Link a task to a git repo and the dispatcher gives it a worktree automatically — no keyword needed.
The built-in kanban_create agent tool (praisonai.tools.kanban_tools) accepts a fixed argument list — title, body, assignee, status, priority, board, max_retries, idempotency_key — and does not forward repo_path, auto_worktree, or workspace_kind. To opt a task into worktree isolation by linkage, call SQLiteKanbanStore().create_task({...}) directly as shown above.
The upgrade is triggered by linkage, not by task content — the task body is never inspected. Disable the upgrade per task (or per board via metadata) with auto_worktree=False:

How It Works

The dispatcher forks a worktree from the base branch, runs the worker inside it, then merges the branch back on success. On success the dispatcher auto-commits any uncommitted worker edits as kanban worker output for kanban/<task_id>, merges the branch into the base with git merge --no-ff, then tears the worktree down. On conflict the merge is aborted, so the base branch is never left half-merged.

Choosing default vs worktree

Pick isolation only when workers actually edit files in a git repo.

New Task fields

Existing SQLite boards auto-migrate to add the branch and worktree_path columns on first open — no user action required.

Environment configuration

Add these to the Environment Configuration table when the dispatcher runs outside the repo. The dispatcher branches from the current HEAD of PRAISONAI_KANBAN_REPO_DIR (defaulting to the process working directory). When HEAD cannot be detected, it falls back to PRAISONAI_KANBAN_BASE_BRANCH (default main).

Merge conflict handling

A conflict never touches the base branch — it routes the task to blocked for a human to resolve.
  • The merge is aborted; the base branch is left untouched.
  • The task moves to blocked with a comment listing the conflicted files.
  • The KANBAN_TASK_BLOCKED hook fires with conflicted_files: list[str].
  • The worktree is preserved on disk for inspection.
To recover, resolve the conflicts inside the kept worktree, then re-run or discard it:
Or discard the worktree entirely from the base repo:
Task IDs are validated (^[A-Za-z0-9._-]+$, no leading ., no path traversal) before use as a branch ref or path. An unsafe ID fails closed — the task refuses to spawn a worker rather than falling back to the shared cwd.

Lossless-only worktree teardown

The dispatcher never destroys work a worker produced but failed to integrate — a worktree with uncommitted changes or unmerged commits is preserved on disk with a worktree_preserved comment on the task. Every preserved worktree records its reason as a task comment, readable via kanban_show(task_id): To recover a preserved worktree, commit anything worth keeping first, then integrate or remove it from the base repo:
Inside a dispatcher-owned code path (e.g. a custom KanbanDispatcher subclass), the equivalent destructive teardown is an explicit force=True:
force=True is destructive by design — use it only when the outstanding work in the worktree is known to be throwaway. In normal operation the dispatcher never sets it.

Best Practices

Tasks that only call APIs or print reports gain nothing from isolation and pay the git overhead. Keep workspace_kind="default" for read-only work; reserve "worktree" for concurrent file edits.
The dispatcher falls back to os.getcwd() at start, which is wrong under systemd/supervisord. Export PRAISONAI_KANBAN_REPO_DIR=/path/to/repo so worktrees and merges run against the right checkout.
The dispatcher rejects .., /, leading ., spaces, and other invalid chars. Unsafe IDs fail closed (no isolation, no worker) — keep IDs to [A-Za-z0-9._-].
Both blocked-on-conflict tasks and clean-merge tasks with a worktree_preserved comment leave their worktree on disk by design. Read the comment for the reason (kanban_show <task_id>), integrate any recoverable work by hand, then git worktree remove --force ~/.praisonai/kanban/worktrees/<task_id> once resolved.
Linking a task to its repo (repo_path="/repos/foo") opts it into isolation and records the isolating repo in metadata so the dispatcher never loses the linkage. workspace_kind="worktree" still works for callers that already track the repo themselves.

Best Practices

Create tasks that can be completed in 15-30 minutes. Break larger work into linked subtasks using kanban_link for proper dependency tracking.
Move tasks through statuses systematically: todoreadyrunningdone. Use blocked for dependencies and review for human approval.
Use kanban_heartbeat during long-running tasks to signal liveness. Add detailed comments with kanban_comment to track progress and decisions.
Use separate boards for different projects or contexts. Default board works well for single-project setups.

Kanban CLI

CLI commands for viewing boards, tasks, and run history

Async Jobs

Asynchronous job processing and queuing

Background Tasks

Async job processing and scheduling

CLI Dispatcher

Command-line task orchestration