A complete guide to using the kanban board programmatically. Create projects, manage tasks, run autonomous sprints, and build self-improving pipelines.
The kanban system is a Next.js app artifact published at /pub/main/kanban-v2/. It manages work through a hierarchy of projects, columns, and tasks, all backed by a shared SQLite database.
Top-level work containers. Each project has its own columns, tasks, settings, and agent mode configuration.
Workflow stages within a project. Typically: To Do, In Progress, Done. Customizable per project with definition-of-done rules.
Individual work items with title, description, priority, labels, subtasks, acceptance criteria, tests, comments, and images.
Tasks can depend on other tasks. Blocked tasks show a "deps" badge. Auto Mode respects dependency ordering.
All data lives in the shared SQLite database. Key tables:
| Table | Purpose |
|---|---|
kanban_projects | Project definitions with name, description, color, agent_mode |
kanban_columns | Columns per project with position and color |
kanban_tasks | Tasks with full metadata, agent_task_id for assignment tracking |
kanban_subtasks | Ordered subtask checklists per task |
kanban_acceptance_criteria | Verifiable outcomes per task |
kanban_tests | Manual or integration test definitions per task |
kanban_comments | Discussion thread per task |
task_dependencies | DAG of task-to-task dependencies |
kanban_settings | Global settings (auto_mode_enabled, etc.) |
research_sessions | AI research sessions attached to tasks |
All endpoints are relative to the kanban artifact base URL. From agents running in the same system, use the Dashboard API proxy.
http://localhost:4000/pub/main/kanban-v2/api/api/projects
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/projects | List all projects |
| POST | /api/projects | Create a project {name, description, color} |
| PATCH | /api/projects/[pid] | Update a project |
| DEL | /api/projects/[pid] | Delete a project and all its tasks |
| GET | /api/projects/[pid]/board | Full board state: columns + tasks |
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/tasks | Create a task {title, description, project_id, column_id, priority, labels, size_category} |
| PATCH | /api/tasks/[id] | Update task fields |
| DEL | /api/tasks/[id] | Delete a task |
| POST | /api/tasks/[id]/move | Move to column {column_id, position} |
| POST | /api/tasks/[id]/assign-agent | Spawn an agent to work on this task |
| POST | /api/tasks/[id]/unassign-agent | Remove agent assignment |
| POST | /api/tasks/[id]/auto-fill | AI generates subtasks, tests, and acceptance criteria |
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/tasks/[id]/subtasks | Add subtask {title} |
| PATCH | /api/subtasks/[sid] | Toggle done: {toggle: true} |
| POST | /api/tasks/[id]/tests | Add test {title, type} |
| PATCH | /api/tests/[tid] | Update test status: {status: "passed"} |
| POST | /api/tasks/[id]/acceptance-criteria | Add criterion {title} |
| POST | /api/tasks/[id]/comments | Add comment {content} |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/tasks/[id]/dependencies | List task dependencies |
| POST | /api/tasks/[id]/dependencies | Add dependency {depends_on_task_id} |
| DEL | /api/tasks/[id]/dependencies/[depId] | Remove dependency |
| GET | /api/dependencies/next | Get next unblocked task (for auto-mode) |
# Create the task
curl -s -X POST "http://localhost:4000/pub/main/kanban-v2/api/tasks" \
-H "Content-Type: application/json" \
-d '{
"title": "[Build] Add search to web3-skills explorer",
"description": "## Objective\nAdd fuzzy search...\n\n## Target Artifact\n/workspace/group/pub/web3-skills/",
"project_id": 11,
"column_id": 41,
"priority": "high",
"labels": "build, artifact, search",
"size_category": "M"
}'
# Add subtasks
curl -s -X POST "http://localhost:4000/pub/main/kanban-v2/api/tasks/735/subtasks" \
-H "Content-Type: application/json" \
-d '{"title": "Implement fuzzy search index"}'
# Add a dependency (depends on task 724)
curl -s -X POST "http://localhost:4000/pub/main/kanban-v2/api/tasks/735/dependencies" \
-H "Content-Type: application/json" \
-d '{"depends_on_task_id": 724}'
# Assign an AI agent to work on it
curl -s -X POST "http://localhost:4000/pub/main/kanban-v2/api/tasks/735/assign-agent"
[Build], [Discovery], [Review]low, medium, high, urgent"build, artifact, sprint-1"XS (1-2h), S (2-4h), M (4-8h), L (8-16h), XL (16h+)Move a task between columns using the move endpoint. This is how agents signal completion:
# Move task 721 to "Done" column (column_id 43)
curl -s -X POST "http://localhost:4000/pub/main/kanban-v2/api/tasks/721/move" \
-H "Content-Type: application/json" \
-d '{"column_id": 43, "position": 0}'
Assigning an agent to a task spawns a scheduled task that runs in the group's context. The agent reads the task description as its instructions.
POST /api/tasks/[id]/assign-agentThe agent receives a structured prompt built from the task. Write task descriptions that work as agent instructions:
## Objective
What the agent should accomplish in one sentence.
## Context
Background knowledge. Reference vault notes, previous tasks, existing code.
## Tasks
1. Specific step with file paths
2. Another step with expected output
3. Final step with verification
## Target Artifact
Path to the artifact this task modifies.
Include restart_artifact instructions.
## Acceptance Criteria
- Verifiable outcome 1
- Verifiable outcome 2
- Verifiable outcome 3
Dependencies create a directed acyclic graph (DAG) that enforces execution order. A task is "blocked" if any of its dependencies are not in the Done column.
You can also set dependencies directly via the database for bulk operations:
-- Add sequential dependencies for tasks 727-733
INSERT INTO task_dependencies (task_id, depends_on_task_id)
VALUES (728, 727), (729, 728), (730, 729),
(731, 730), (732, 731), (733, 732);
# Get the next unblocked task for a project
curl -s "http://localhost:4000/pub/main/kanban-v2/api/dependencies/next?project_id=11"
# Check which tasks are blocked
curl -s "http://localhost:4000/pub/main/kanban-v2/api/dependencies/blocked?project_id=11"
Auto Mode automatically assigns an agent to the next unblocked task when the current one completes. Combined with dependencies, this creates a fully autonomous pipeline.
# Toggle auto mode on
curl -s -X POST "http://localhost:4000/pub/main/kanban-v2/api/auto-mode/toggle" \
-H "Content-Type: application/json" \
-d '{"enabled": true}'
# Check status
curl -s "http://localhost:4000/pub/main/kanban-v2/api/auto-mode/status"
The kanban board includes a built-in research engine that can run multi-round AI research sessions attached to tasks. Research findings can be converted into new tasks.
A research session runs N rounds of AI analysis on a prompt, accumulating findings across rounds.
Each round produces typed findings: insights, action items, questions, recommendations, risks, opportunities.
Findings can generate task proposals. Accept them to create kanban tasks automatically.
Reusable research prompt templates. Fork, customize, and share across projects.
The most powerful pattern in the kanban system: tasks that create tasks. A task-designer task is like a Promise — unresolved at write time, it synthesizes all prior work just-in-time when executed.
Data producers. Audit, research, enumerate. Output: structured reports that downstream tasks consume.
Promise resolvers. Read accumulated context, create N implementation tasks with full descriptions.
Resolved work. Created by task-designers with precise file paths and acceptance criteria.
Quality gates. Audit all sprint outputs, flag gaps, validate architecture.
Knowledge consolidation. Process learnings into permanent vault notes.
Self-replication. Reads EVERYTHING from the current sprint, creates the next one.
Promise tasks become even more powerful when every task targets the same artifact:
Beyond the standard task types, Expansion tasks are a higher-order pattern. They don't just continue a project — they reimagine it. An expansion task takes the current state of an artifact and asks: what could this become?
Takes explicit goals as input. "Add multi-chain support." "Make it work for DAOs." The expansion task reads the current artifact and designs tasks to reach the goal.
No goals given — the agent synthesizes them. It reads the artifact, vault notes, user feedback, and research findings to identify the highest-value expansion direction.
The most creative mode. The agent challenges the artifact's fundamental assumptions. What if we rebuilt this with a different architecture? What if we merged it with another artifact?
## Objective
[Expand / Refine / Reimagine] the {artifact-name} artifact.
## Expansion Mode
[goal-driven | synthesized | reimagined]
## Goals (if goal-driven)
- Goal 1: ...
- Goal 2: ...
## Context Sources (read all before designing)
- Current artifact: /workspace/group/pub/{artifact-name}/
- Vault notes: search vault for related knowledge
- Research findings: check research_findings table for this project
- User feedback: check kanban_comments on completed tasks
- Shared vault: vault_search_shared("{domain}") for cross-group insights
## Tasks
1. Read and analyze the current artifact thoroughly
2. If synthesized mode: identify 3-5 expansion directions, rank by value
3. If reimagined mode: challenge 3 core assumptions, propose alternatives
4. Design 8-12 implementation tasks for the chosen direction
5. Each task must target the existing artifact (not create a new one)
6. Include a backup task BEFORE any destructive changes
7. End with a new expansion task for the next cycle
## Acceptance Criteria
- Expansion direction justified with evidence from context sources
- All new tasks reference the target artifact
- Backup created before any architectural changes
- Next expansion task created at the end
Expansion tasks create a second loop on top of the sprint loop:
The most powerful expansion pattern: merging two artifacts into one. When an expansion task notices that two artifacts serve overlapping purposes, it can propose a merge:
## Expansion: Merge web3-skills into idealabs
The web3-skills explorer (52 skills, filtering, taxonomy) would be
more valuable embedded in the ideaLabs platform as a "capabilities"
tab that links skills to hackathon ideas.
## Merge Plan
1. backup_artifact_db(name="web3-skills")
2. backup_artifact_db(name="idealabs")
3. Copy web3-skills data into idealabs schema
4. Build "Capabilities" tab in idealabs UI
5. Redirect web3-skills to idealabs/capabilities
6. Unpublish standalone web3-skills after verification
Every task that modifies an artifact should include safety checkpoints. Emblem:build provides backup, restore, and cross-publish tools that agents should use proactively.
backup_artifact_db(name) — dumps all declared tables to .emblem_build/db-backup.sql. Idempotent, re-runnable.
restore_artifact_db(name) — applies backup SQL. Validates against package.json manifest. Schema-only mode available.
cross_publish_artifact(peer_id, name, ...) — push artifact + data to a remote Emblem:build instance.
GET /api/projects/[pid]/export — export full project state (tasks, subtasks, deps) as JSON.
Before backup/restore works, tables must be registered in the artifact's package.json:
{
"name": "my-artifact",
"emblem_build": {
"tables": [
{
"name": "items",
"schema": "CREATE TABLE IF NOT EXISTS items (id TEXT PRIMARY KEY, name TEXT, data TEXT, created_at TEXT DEFAULT (datetime('now')))"
}
]
}
}
backup_artifact_db refuses to run if emblem_build.tables is missing or empty. Always register tables first. Tables not listed are invisible to backup/restore.
| Situation | Action | Command |
|---|---|---|
| Before risky schema migration | Full backup | backup_artifact_db(name="my-app") |
| Before expansion/reimagine task | Full backup | backup_artifact_db(name="my-app") |
| Before merging artifacts | Backup BOTH artifacts | Two backup calls |
| Before cross-publishing | Backup to ship data with artifact | backup_artifact_db then cross_publish_artifact |
| After successful sprint | Checkpoint backup | backup_artifact_db(name="my-app") |
| Shipping schema only (fresh start) | Schema-only backup | backup_artifact_db(name="my-app", schema_only=true) |
If something goes wrong during a sprint or expansion:
# 1. Before risky work — create checkpoint
backup_artifact_db(name="web3-skills")
# 2. Do the risky work...
# (schema migration, data transform, etc.)
# 3. If something broke — rollback
restore_artifact_db(name="web3-skills")
restart_artifact(name="web3-skills")
# 4. If everything worked — backup the new state
backup_artifact_db(name="web3-skills")
For critical artifacts, cross-publish to a linked peer as an off-site backup:
# 1. Backup database to include data in the push
backup_artifact_db(name="web3-skills")
# 2. Check available peers
list_peer_links()
# 3. Push to remote peer
cross_publish_artifact(
peer_id="peer-xxx",
name="web3-skills",
source_path="pub/web3-skills",
type="app",
entry_point="node server.js",
is_public=true
)
# Remote restores db-backup.sql automatically on boot
Every task description that modifies an artifact should include these safety steps:
backup_artifact_db before schema changes or data migrationsrestart_artifact and verify the artifact loadsbackup_artifact_db again after successful changes (new checkpoint)Export an entire project's state for archival, migration, or cross-instance transfer:
# Export full project state as JSON
curl -s "http://localhost:4000/pub/main/kanban-v2/api/projects/11/export" \
| jq . > /workspace/group/backups/recursiveWeb3-export.json
# Includes: project metadata, columns, tasks, subtasks,
# acceptance criteria, tests, comments, dependencies,
# research sessions, findings, proposals
The vault provides semantic backup — even if an artifact is lost, vault notes preserve the knowledge that built it:
Every artifact that persists data uses the shared SQLite database. Understanding how to design, document, and manage schemas is critical for building reliable artifacts.
db_schema(), db_query(sql), db_execute(sql) — direct access for agents. Use for schema setup, ad-hoc queries, and migrations.
GET /api/db/{group}/database/query?sql=... and POST /api/db/{group}/database/execute — server-side only, never from browser.
sqlite3 CLI, no direct file reads. Always use MCP tools (agents) or Dashboard API (app servers). Direct access causes locking issues and bypasses access controls.
kanban_tasks, research_sessions — avoids collisions in the shared databaseCREATE TABLE IF NOT EXISTS — idempotent schemas that can run on every bootcreated_at and updated_at on every table — essential for debugging and activity feedsON DELETE CASCADE explicitly — SQLite's default is NO ACTION, which blocks deletes on parent rowsEvery artifact's schema should be documented in three places:
---
description: Database schema for {artifact-name} — {N} tables covering {domain}
topics: [platform, database, {artifact-name}]
---
# {Artifact Name} Database Schema
## Overview
Brief description of what data the artifact manages and why.
## Tables
### {table_name}
Purpose: What this table stores and why.
Relationships: FK to {other_table}, referenced by {other_table}.
| Column | Type | Description |
|--------|------|-------------|
| id | INTEGER PK | Auto-increment primary key |
| name | TEXT NOT NULL | Display name |
| created_at | TEXT | ISO timestamp, defaults to now |
Key queries:
- List active items: `SELECT * FROM {table} WHERE status = 'active'`
- Count by category: `SELECT category, COUNT(*) FROM {table} GROUP BY category`
### {next_table}
...
## Migrations
| Date | Change | SQL |
|------|--------|-----|
| 2026-04-19 | Added status column | `ALTER TABLE items ADD COLUMN status TEXT DEFAULT 'active'` |
## Relationships Diagram
{table_a} 1──N {table_b} (via table_a_id FK)
{table_b} 1──N {table_c} (via table_b_id FK, CASCADE)
SQLite has limited ALTER TABLE support. Use these patterns:
# Adding a column (safe, always works)
db_execute("ALTER TABLE items ADD COLUMN status TEXT DEFAULT 'active'")
# Adding an index (safe)
db_execute("CREATE INDEX IF NOT EXISTS idx_items_status ON items(status)")
# Renaming a column (SQLite 3.25+)
db_execute("ALTER TABLE items RENAME COLUMN old_name TO new_name")
# Complex migration (recreate table)
# 1. Backup first!
backup_artifact_db(name="my-app")
# 2. Create new table with desired schema
db_execute("CREATE TABLE items_new (id INTEGER PRIMARY KEY, ...)")
# 3. Copy data
db_execute("INSERT INTO items_new SELECT ... FROM items")
# 4. Swap tables
db_execute("DROP TABLE items")
db_execute("ALTER TABLE items_new RENAME TO items")
# 5. Verify and backup new state
backup_artifact_db(name="my-app")
Published app artifacts access the database through the Dashboard API. The browser talks to your server, your server talks to the API:
const API = process.env.DASHBOARD_BASE || 'http://localhost:4000';
const TOKEN = process.env.DASHBOARD_TOKEN;
const GROUP = process.env.ARTIFACT_GROUP || 'main';
// Read endpoint
app.get('/api/items', async (req, res) => {
const sql = 'SELECT * FROM items WHERE status = ? ORDER BY created_at DESC LIMIT 50';
const r = await fetch(
`${API}/api/db/${GROUP}/database/query?sql=${encodeURIComponent(sql)}¶ms=${encodeURIComponent(JSON.stringify(['active']))}`,
{ headers: { Authorization: `Bearer ${TOKEN}` } }
);
const data = await r.json();
res.json(data.rows || []);
});
// Write endpoint
app.post('/api/items', express.json(), async (req, res) => {
const sql = 'INSERT INTO items (name, category) VALUES (?, ?)';
const r = await fetch(`${API}/api/db/${GROUP}/database/execute`, {
method: 'POST',
headers: { Authorization: `Bearer ${TOKEN}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ sql, params: [req.body.name, req.body.category] })
});
res.json(await r.json());
});
fetch('api/items') not fetch('/api/items'). Your artifact is served at /pub/{group}/{name}/ and the proxy strips that prefix. Absolute paths bypass your server entirely.
When working with an unfamiliar artifact, discover its schema:
# 1. Inspect the artifact (shows registered tables)
inspect_artifact(name="kanban-v2")
# 2. Get full schema from the database
db_schema()
# 3. Check package.json for the manifest
cat /workspace/group/kanban-v2/package.json | jq '.emblem_build.tables'
# 4. Run sample queries to understand the data
db_query("SELECT COUNT(*) as n, typeof(id) as id_type FROM kanban_tasks")
db_query("SELECT sql FROM sqlite_master WHERE type='table' AND name LIKE 'kanban_%'")
Task descriptions are agent instructions. The better they are, the better agents perform.
/workspace/group/pub/web3-skills/server.js not "the server file"restart_artifact(name="web3-skills")Tasks are allowed — and encouraged — to create other tasks. This is what makes the system recursive. But there are rules about when a task should spawn new tasks to protect sprint velocity.
By default, when an agent discovers additional work during a task, it should:
This prevents sprint blowout. A discovery task that finds 5 unexpected issues should not spawn 5 urgent tasks mid-sprint — it should document them and let the next sprint's task-designer prioritize them with full context.
Project notes (kanban_project_notes) can grant agents explicit permission to create tasks for the current sprint. This is the escape hatch for critical issues.
## Task Creation Policy
### Immediate (current sprint)
Agents may create and assign tasks in the current sprint ONLY for:
- Security vulnerabilities discovered during implementation
- Broken dependencies that block other tasks
- Data loss risks that need immediate mitigation
These tasks should be tagged "hotfix" and sized XS or S.
### Deferred (next sprint)
ALL other discovered work goes to the next sprint:
- Feature ideas discovered during implementation
- Refactoring opportunities
- Nice-to-have improvements
- Non-blocking bugs
Tag these "discovered, sprint-N+1" so the next task-designer
can incorporate them with full context.