# Toban — Complete Documentation Generated: 2026-04-05T22:00:54.164Z --- # Getting Started ## What is Toban? Toban is an AI agent orchestration platform that organizes coding agents as a team. You define sprints with tasks, and Toban assigns them to Builder agents that work in isolated git branches. You review and approve or reject each agent's work from a real-time dashboard, keeping humans in control of every change that lands in your codebase. All workspaces include the full Pro feature set. No credit card required -- sign in with GitHub and start. AI agent usage (Claude Code API credits) is billed separately by Anthropic. A typical task consumes roughly 50K-200K tokens depending on complexity. This guide walks you through creating your first Toban Project and running AI agents on your codebase. ## Prerequisites - Node.js 20+ - A GitHub account - [Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code) installed and authenticated: `npm install -g @anthropic-ai/claude-code` then run `claude` once to sign in with your Anthropic account ## 1. Sign Up Visit [toban.dev](https://toban.dev) and sign in with your GitHub account. Toban uses GitHub OAuth -- no separate password required. ## 2. Create a Project After signing in, you will be guided through the setup wizard. The Project is not created until you complete the wizard, so you can go back and change settings at any step. ### Name Your Project Give your Project a name and optional description. This appears in the dashboard header and agent prompts. ### Connect a GitHub Repository Enter the GitHub repository URL for your project (e.g., `https://github.com/your-org/your-repo`). Toban will: - Clone the repository when agents start - Create isolated branches for each task - Auto-merge completed work back to the base branch You can add additional repositories later in Settings > Repositories. ### Choose Your Agent Engine Select the engine for your worker agents: | Engine | Description | |--------|-------------| | Claude Code CLI | Anthropic's official coding CLI. Primary and recommended engine. | Currently, Claude Code is the only fully supported engine. Support for additional engines (Codex, Gemini) exists in the provider system but is not yet production-ready. ### Configure Agents The default setup creates a **Manager** and a **Builder** agent. The Manager coordinates sprint planning and task proposals via chat. The Builder implements code changes in isolated git worktrees. ## 3. Set Your Project Spec After Project creation, go to the **/spec** page to write your project specification. This is a free-text document that describes: - What your project does - Target users - Tech stack and architecture - Key constraints or conventions The spec is injected into every agent prompt, giving agents the context they need to make good decisions. A well-written spec significantly improves agent output quality. ## 4. Configure Repositories Go to **Settings > Repositories** to register repositories that agents should work with: - **Main repository**: The primary codebase (set during wizard) - **Sub repositories**: Additional repos agents may need access to - **Access control**: Restrict which agent roles can access each repo ## 5. Install the CLI The CLI (`toban-cli`) runs on your local machine and orchestrates agent execution. No global install is needed -- `npx` downloads the latest version on the fly. ```bash # Install Claude Code CLI (required as the agent engine) npm install -g @anthropic-ai/claude-code # Run the Toban CLI (no global install needed) npx toban-cli@latest start --api-url --api-key ``` > **Tip:** On the **Sprint page**, click the **"$ run"** / **"CLI"** button in the header to copy the full command with the API URL and key pre-filled for your Project. ### CLI Options ``` --api-url Toban API base URL (or TOBAN_API_URL env) --api-key API key (or TOBAN_API_KEY env) --working-dir Repository root (default: cwd) --branch Base branch (default: main) --model AI model for Manager chat --engine Agent engine (default: claude-code) --ws-port WebSocket port (default: 4000, 0=auto) --debug Verbose output (or DEBUG=1 env) ``` ## 6. Create a Sprint Back on the **Sprint page** in the dashboard: 1. Click **+ Sprint** to create a new sprint (starts as **Active** immediately -- no planning phase) 2. Set a **Sprint Goal** and optional **Deadline** (click next to the phase stepper) 3. Open the **Chat Panel** and ask the Manager to propose tasks (e.g., "Propose tasks for this sprint") 4. The Manager analyzes your project spec and backlog, then proposes tasks as interactive cards 5. Click **Sprint** or **Backlog** on each card to add to the current sprint or save for later 6. Adjust priorities and assignments on the Kanban board if needed You can also create tasks manually by clicking **Add Task** on the sprint board. **Tips for good task descriptions:** - Be specific: "Add user login with GitHub OAuth" not "Add auth" - Include acceptance criteria when possible - Reference relevant files or documentation ## 7. Run Agents Once the sprint has tasks and the CLI is connected, agents start automatically: - Tasks owned by agent roles (builder) are **automatically picked up** by the CLI - The CLI transitions them from `todo` to `in_progress` and spawns the agent - Tasks owned by `user` are never auto-started -- those are for you - Watch agent progress in the **Terminal Panel** (tool use, file edits, bash commands) The CLI handles the full lifecycle: 1. Creates an isolated git worktree for the agent 2. Injects agent memories, ADRs, and task context into the prompt 3. Spawns the Claude Code CLI process 4. Monitors progress and streams activity to the Dashboard via WebSocket 5. On completion: merges the agent's branch to main, pushes to remote, generates structured review report > **Important**: The CLI auto-merges completed work to main, but the task moves to **Review** status -- not Done. **You must explicitly Approve or Reject every task** before it is marked as complete. Rejected tasks go back to the agent with your feedback. Nothing is considered "done" without your approval. > > This trunk-based workflow is the current default. Support for other branching strategies (e.g. GitHub Flow with pull requests) is planned. ## 8. Review Completed Work When an agent finishes a task, it moves to **Review** status on the sprint board: 1. Click the task card to expand the **Structured Review Report** (requirement match, code quality, test coverage, risks, verdict) 2. Click **Approve** to mark as done, or **Reject** with feedback (the agent will rework the task) 3. Rejected tasks go back to the agent with your feedback attached ## 9. Track Progress - **Sprint Board** shows real-time task status via WebSocket (no reload needed) - **Analytics page** has Velocity charts, Burndown, Daily Activity, and Agent contribution - **Sprint Goal** and **Deadline countdown** are visible in the sprint header ## Prompt Transparency Want to see exactly what instructions your agents receive? Go to **Agents > Prompts** in the sidebar to preview the full prompt for any agent role. The preview shows all injected content: - Role description and security rules - Project Spec (vision, tech stack, constraints) - ADR summaries - Task-specific instructions This lets you verify and tune the prompt before agents start working. The preview is also available via the API: `GET /api/v1/agents/:name/prompt-preview`. ## Tips: Working with Claude Code Directly The dashboard chat (Manager) is useful for quick task proposals and sprint management. For deeper work -- architecture discussions, debugging, code reviews, strategic planning -- **use Claude Code CLI directly** in your terminal. To give Claude Code full context about your Toban project, feed it the documentation: ``` Read https://app.toban.dev/llms-full.txt ``` Combined with your project's `CLAUDE.md`, this gives Claude Code everything it needs to act as your senior engineering partner while Toban handles the sprint management and agent orchestration. ## Next Steps - [Architecture Guide](./architecture.md) -- How Toban works under the hood - [Setup Guide](./setup-guide.md) -- Detailed setup and configuration reference - [ADR Guide](./adr-guide.md) -- Architecture Decision Records for agent governance - [Error Reference](./error-reference.md) -- Error codes and troubleshooting - [Security Guide](./security.md) -- Security model and guarantees --- # Setup Guide Detailed configuration reference for Toban Projects, agents, repositories, and the CLI. ## Prerequisites - Node.js 20+ - A GitHub account (for OAuth login) - [Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code): `npm install -g @anthropic-ai/claude-code` ## GitHub App and OAuth Toban uses two GitHub integrations: ### GitHub OAuth App Used for user authentication. When you sign in at toban.dev, you authorize Toban to read your GitHub identity. This creates a session cookie used by the dashboard. ### GitHub App Used for repository operations. The GitHub App is installed on your organization or personal account and grants Toban: - Read access to repository metadata - Write access for creating branches and pushing commits - Token generation for git operations (installation tokens, 1hr expiry) When you connect a repository during Project setup, Toban checks that the GitHub App is installed with access to that repository. If not, it prompts you to install or reconfigure the App. ## Project Creation The setup wizard collects all configuration before creating anything. The Project is **deferred** -- it is only created in the database after you complete the final step. This prevents orphaned Projects if you abandon the wizard. ### Wizard Steps 1. **Project name and description** -- Display name for the Project 2. **GitHub repository** -- The primary repo agents will work on 3. **Agent engine** -- Currently Claude Code is the only production-ready engine 4. **Confirmation** -- Review and create After creation, you land on the Sprint page. The next steps are: - Write your project spec at `/spec` - Add additional repositories at Settings > Repositories ## Repository Configuration ### Main Repository Set during Project creation. This is the primary codebase that agents clone and work on. The repository URL is stored as `github_repo` (format: `owner/repo`). ### Sub Repositories Additional repositories can be registered at **Settings > Repositories**. Each entry has: | Field | Description | |-------|-------------| | `repo_name` | Display name | | `repo_path` | GitHub path (`owner/repo`) or local path | | `description` | Optional description | | `access_agents` | Which agent roles can access this repo (empty = all) | The CLI clones all registered repositories at startup and creates worktrees in the appropriate repo for each task. ### Access Control By default, all agents can access all repositories. To restrict access: 1. Go to Settings > Repositories 2. Edit the repository 3. Add specific agent roles to the access list (e.g., only `builder`) ## Agent Configuration ### Engine Selection Each agent has an engine configuration that determines how it runs: | Setting | Description | |---------|-------------| | `engine` | Engine type: `claude-code` (recommended), `claude-api`, `gemini`, `codex`, `custom` | | `execution_mode` | Currently `local` only (BYOK mode is not yet functional) | | `command_template` | Custom command template for the `custom` engine | Configure agents at the **Agents** page or via `PUT /api/v1/agents/:name/config`. ### Agent Roles | Role | Capabilities | |------|-------------| | **Manager** | Sprint coordination, task proposals, chat interaction (read-only repo access) | | **Builder** | Full code read/write, test execution, commits | The Manager is created automatically during Project setup. The Builder is the primary worker agent. ## Sprint Configuration ### Creating a Sprint Sprints can be created from the dashboard Sprint page or via the API: ```bash POST /api/v1/sprints { "number": 1 } ``` ### Sprint Status Sprints start as **Active** by default -- there is no planning phase in the UI. The `planning` status exists in the API for backward compatibility but is not used in the current UX. The phase flow is: Active -> Review -> Retrospective -> Completed. ### Manager Interaction The Manager is an LLM-powered agent that coordinates the sprint. It: - Proposes tasks based on the project spec and backlog - Responds to user chat messages - Requests approval before spawning worker agents - Tracks task progress and suggests status transitions The Manager uses the enriched context from `GET /api/v1/manager/context`, which includes tasks, agent statuses, the project spec, backlog items, and retrospective data from previous sprints. ## CLI Configuration ### Environment Variables | Variable | Required | Description | |----------|----------|-------------| | `TOBAN_API_URL` | Yes | Toban API base URL | | `TOBAN_API_KEY` | Yes | Project API key | | `LLM_BASE_URL` | No | OpenAI-compatible API URL for Manager (overrides Claude CLI) | | `LLM_API_KEY` | No | API key for the LLM provider | | `DEBUG` | No | Set to `1` for verbose output | ### CLI Flags All environment variables can be overridden with CLI flags: ```bash npx toban-cli@latest start \ --api-url https://api.toban.dev \ --api-key tb_wsXXX_sk_XXX \ --working-dir /path/to/your/repo \ --branch main \ --model claude-sonnet-4-20250514 \ --ws-port 4000 ``` ### WebSocket Port The CLI starts a WebSocket server (default port 4000) that the Dashboard connects to for real-time communication. If port 4000 is unavailable, use `--ws-port 0` for automatic port selection. The CLI registers its port with the API so the Dashboard can discover it. ## Project Settings | Setting | Description | |---------|-------------| | `name` | Project display name | | `description` | Project description | | `language` | AI communication language (`en` or `ja`) | | `workflow` | Workflow type: `scrum`, `kanban`, or `checklist` | | `github_repo` | Connected GitHub repository (`owner/repo`) | | `spec` | Project specification (editable at `/spec`) | | `terminal_emulator` | Preferred terminal for local agent execution | Update via the Settings page or `PUT /api/v1/workspace` (the API uses `workspace` internally). ## Backend Deployment ### Cloudflare Workers (API) The API runs on Cloudflare Workers with D1 (SQLite) storage. ```bash cd toban/api npm install # Configure wrangler.jsonc with your Cloudflare account # Set secrets: # GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET # GITHUB_APP_ID, GITHUB_PRIVATE_KEY # APP_URL (frontend URL for OAuth redirect) # Run migrations npx wrangler d1 migrations apply toban-db # Deploy npm run deploy ``` ### Frontend (Next.js) The dashboard is a Next.js application deployed to any Node.js hosting platform. ```bash cd toban npm install # Create .env.local: # API_URL=https://your-api.example.com # API_KEY=internal-proxy-key npm run build npm run start ``` ### Infrastructure (Terraform) The `terraform/` directory manages Cloudflare resources: - D1 database - Workers deployment - Custom domain configuration - Monitoring and alerting --- # Architecture Overview Toban has three main components that work together: ``` Browser Your Machine +-----------------+ +------------------+ | Dashboard | WebSocket | Toban CLI | | (toban.dev) | <---------> | (toban-cli) | | | | | | Sprint Board | | Manager Agent | | Chat Panel | | Builder Agents | | Terminal View | | Git Operations | | Review Flow | | | +-----------------+ +------------------+ | | | REST API | Git Push v v +-----------------+ +------------------+ | Toban API | | GitHub | | (Cloudflare) | | Repositories | | | +------------------+ | Quality Scores | | Failure DB | | Knowledge | +-----------------+ ``` ## Dashboard The web interface where you manage sprints, review agent work, and chat with the Manager. - **Sprint Board** -- Kanban-style task management with drag-and-drop - **Chat Panel** -- Talk to the Manager agent to plan sprints, propose tasks, and coordinate - **Terminal Panel** -- See what agents are doing in real-time (file reads, edits, commands) - **Review Flow** -- Approve or reject completed work with one click ## Toban CLI Runs on your machine and orchestrates the AI agents. - **Manager Agent** -- An AI that reads your codebase, proposes tasks, and manages the sprint - **Builder Agents** -- AI agents that implement tasks in isolated git worktrees - **Templates** -- Configurable prompt templates that control agent behavior (implementation, reviewer) The CLI connects to the Dashboard via WebSocket for real-time communication. When the Dashboard is not open, it falls back to API polling. ## Toban API Hosted on Cloudflare Workers. Stores all data (tasks, sprints, agents, messages) and handles authentication via GitHub OAuth. - **Quality Scores** -- Review results are aggregated into per-agent quality scores - **Failure DB** -- Past failures and review rejections are stored to prevent recurring issues - **Knowledge** -- Shared memory entries for cross-agent context preservation ## How a Task Gets Done 1. You create a task (or the Manager proposes one) 2. Move the task to "In Progress" on the Sprint Board 3. The CLI picks it up and spawns a Builder agent in a git worktree 4. The Builder implements the change and commits 5. The CLI runs a reviewer template to perform structured code review 6. The CLI merges to main, pushes, and writes a review report 7. You review and approve (or reject) on the Sprint Board 8. Results feed back into Quality Scores and Failure DB ## Communication - **Real-time**: WebSocket between Dashboard and CLI (chat, agent activity, proposals) - **Persistent**: REST API for task/sprint/agent data storage - **Git**: Agents commit in worktrees, CLI pushes to GitHub ## Security - Agents run in isolated git worktrees (not your working directory) - The Manager has read-only access to repositories - Worker agents auto-start on tasks assigned to agent roles (manual approval mode planned) - GitHub App tokens are refreshed automatically (1-hour expiry) For more details, see the [Setup Guide](./setup-guide.md) and [Getting Started](./getting-started.md). --- # Toban API Reference Base URL: `https://api.toban.dev` ## Authentication All `/api/v1/*` endpoints require a Bearer token: ``` Authorization: Bearer tb_wsXXX_sk_XXX ``` API keys are Project-scoped and automatically generated on login. Copy the CLI connection command from the Sprint page header. User session keys expire after 7 days of inactivity (sliding window). Agent keys do not expire. --- ## Health ### `GET /api/health` Health check. No auth required. **Response:** `200 OK` ```json { "status": "ok" } ``` --- ## Site Status ### `GET /api/site/status` Public site status (maintenance mode, banner). No auth required. **Response:** ```json { "maintenance": false, "maintenance_message": "The system is currently under maintenance.", "banner": false, "banner_message": "", "banner_scheduled_at": "" } ``` --- ## Auth ### `GET /api/auth/github` Redirect to GitHub OAuth authorization. No auth required. ### `GET /api/auth/github/callback` GitHub OAuth callback. Exchanges code for token, creates/finds workspace, sets session cookie. ### `GET /api/auth/github/installed` GitHub App post-installation callback. Links the GitHub App installation to the workspace. ### `POST /api/auth/logout` Invalidate the current session and clear the session cookie. ### `GET /api/auth/me` Check if the current session is valid. Returns minimal session info (no workspace data). For user profile data (GitHub login, avatar), use `GET /api/v1/auth/me` instead (requires workspace-scoped auth). --- ## Config ### `GET /api/v1/config/constants` Public configuration constants. No workspace-specific data. Returns available roles, engines, templates, and other UI configuration. **Response:** ```json { "roles": ["manager", "builder"], "engines": ["claude-code", "claude-api", "gemini", "codex", "custom"], "templates": ["implementation", "reviewer"], "priorities": ["p0", "p1", "p2", "p3"], "task_statuses": ["todo", "in_progress", "review", "done", "blocked"] } ``` --- ## Workspace ### `GET /api/v1/workspace` Get current workspace details including name, description, connected repo, language, workflow type, and spec. **Response:** ```json { "id": "ws-abc123", "name": "My Project", "description": "A web application", "github_org": "my-org", "github_repo": "my-org/my-repo", "agent_type": "claude-code", "language": "en", "workflow": "scrum", "spec": "Project specification text...", "created_at": "2026-01-01T00:00:00", "updated_at": "2026-01-02T00:00:00" } ``` ### `PUT /api/v1/workspace` Update workspace settings. **Body:** ```json { "name": "string (optional)", "description": "string (optional)", "language": "en | ja (optional)", "workflow": "scrum | kanban | checklist (optional)", "github_repo": "owner/repo (optional)", "spec": "string (optional)", "terminal_emulator": "auto | terminal.app | iterm2 | ghostty | ... (optional)" } ``` ### `DELETE /api/v1/workspace` Delete workspace and all associated data. --- ## Workspace Repositories ### `GET /api/v1/workspace/repositories` List registered repositories. **Response:** ```json [ { "id": "repo-abc123", "workspace_id": "ws-abc123", "repo_path": "my-org/my-app", "repo_name": "my-app", "description": "Main application", "access_agents": ["builder"], "created_at": "2026-01-01T00:00:00" } ] ``` ### `POST /api/v1/workspace/repositories` Add a repository. **Body:** ```json { "repo_path": "owner/repo", "repo_name": "repo-name", "description": "optional description", "access_agents": ["builder"] } ``` ### `PUT /api/v1/workspace/repositories/:id` Update a repository configuration. ### `DELETE /api/v1/workspace/repositories/:id` Remove a repository. --- ## Workspace Export / Import ### `GET /api/v1/workspace/export` Export workspace configuration as JSON. Includes agents and task templates. **Response:** ```json { "version": 1, "exported_at": "2026-01-01T00:00:00.000Z", "workspace": { "name": "My Project", "description": "...", "language": "en", "workflow": "scrum" }, "agents": [ { "name": "builder", "engine": "claude-code", "execution_mode": "local", "system_prompt": null } ], "task_templates": [ { "title": "Setup repo", "description": "...", "priority": "p0", "owner": "builder", "labels": "[]" } ] } ``` ### `POST /api/v1/workspace/import` Import workspace configuration from JSON. **Body:** ```json { "version": 1, "mode": "merge | replace (optional, default: merge)", "agents": [], "task_templates": [] } ``` **Response:** ```json { "ok": true, "mode": "merge", "stats": { "agents_imported": 2, "templates_imported": 3 } } ``` --- ## Workspace User Tasks ### `GET /api/v1/workspace/user-tasks` List user tasks (manual/human tasks separate from agent sprint tasks). Supports query param `status` to filter by `todo`, `in_progress`, or `done`. **Response:** ```json [ { "id": "utask-abc12345", "workspace_id": "ws-abc123", "title": "Review deployment guide", "description": "", "status": "todo", "related_tasks": ["task-uuid-1"], "created_at": "2026-01-01T00:00:00", "completed_at": null } ] ``` ### `GET /api/v1/workspace/user-tasks/blockers` List incomplete user tasks that block active sprint tasks (tasks whose `related_tasks` overlap with current sprint task IDs). **Response:** ```json [ { "id": "utask-abc12345", "title": "Review deployment guide", "status": "todo", "related_tasks": ["task-uuid-1"], "blocked_sprint_tasks": [ { "id": "task-uuid-1", "title": "Deploy to prod", "status": "todo", "owner": "builder" } ] } ] ``` ### `POST /api/v1/workspace/user-tasks` Create a user task. **Body:** ```json { "title": "string (required, max 200)", "description": "string (optional, max 2000)", "related_tasks": ["task-id-1"] } ``` ### `PUT /api/v1/workspace/user-tasks/:id` Update a user task. **Body:** ```json { "title": "string (optional)", "description": "string (optional)", "status": "todo | in_progress | done (optional)", "related_tasks": ["task-id"] } ``` ### `DELETE /api/v1/workspace/user-tasks/:id` Delete a user task. --- ## Git Token ### `GET /api/v1/workspace/git-token` Return a short-lived GitHub App installation token for git operations (clone, push, pull). Tokens expire after 1 hour. **Response:** ```json { "token": "ghs_xxxxxxxxxxxx", "expires_at": "2026-01-01T01:00:00Z" } ``` Used by the CLI's credential helper script to authenticate git operations on demand. --- ## Workspaces (Multi-Project) ### `GET /api/v1/workspaces` List all workspaces for the current user (by GitHub login). **Response:** ```json [ { "id": "ws-abc123", "name": "My Project", "github_org": "my-org", "github_avatar": "https://..." } ] ``` ### `POST /api/v1/workspaces` Create a new workspace and switch to it (sets session cookie). **Body:** ```json { "language": "en | ja (optional)" } ``` ### `POST /api/v1/workspaces/:id/switch` Switch to another workspace owned by the same user. Returns a new API key and sets session cookie. **Response:** ```json { "key": "tb_xxx_sk_xxx", "workspace": { "id": "ws-abc123", "name": "My Project" } } ``` --- ## Projects ### `POST /api/v1/projects/setup` Complete project setup for the current workspace. Creates the manager agent, Sprint 0, initial tasks, and a welcome message. Optionally creates additional agents with per-role engine configuration. **Body:** ```json { "name": "string (optional)", "github_repo": "owner/repo (optional)", "agent_type": "claude-code | codex | custom (optional, default: claude-code)", "language": "en | ja (optional, default: ja)", "description": "string (optional)", "agents": [ { "name": "builder", "engine": "claude-code | claude-api | gemini | codex | custom (optional)", "execution_mode": "local | byok (optional)", "api_key": "string (optional)", "command_template": "string (optional)" } ] } ``` **Response:** `201 Created` ```json { "workspace": { "id": "ws-abc123", "name": "My Project", "..." : "..." }, "manager_agent": { "name": "manager", "status": "active", "..." : "..." }, "sprint": { "number": 0, "status": "active" } } ``` --- ## Manager ### `GET /api/v1/manager/context` Returns enriched context for the Manager agent. This is the primary endpoint the CLI uses to build the Manager's system prompt. Includes: - Current sprint info and status - All tasks with their statuses and assignments - Agent statuses and activity - Project spec - Backlog items - Previous sprint retrospective data --- ## Tasks ### `GET /api/v1/tasks` List all tasks. Supports query params: | Param | Description | |-------|-------------| | `status` | Filter by status: `todo`, `in_progress`, `review`, `done`, `blocked` | | `sprint` | Filter by sprint number | | `owner` | Filter by agent name | ### `POST /api/v1/tasks` Create a task. **Body:** ```json { "title": "Implement login page", "description": "Create OAuth login flow with GitHub", "owner": "builder (optional, auto-inferred from type)", "priority": "p0 (optional, default: p1)", "status": "todo (optional)", "type": "feature (optional, auto-inferred from title/description)", "sprint": 1, "branch": "string (optional)", "labels": ["feature", "auth"], "blocks": [], "blocked_by": [], "context_notes": "string (optional)", "target_repo": "string (optional)", "parent_task": "uuid (optional)", "story_points": 3 } ``` ### `PATCH /api/v1/tasks/:id` Update a task. Common fields: ```json { "status": "in_progress", "owner": "builder", "review_comment": "Completed implementation with tests", "commits": "abc1234,def5678", "story_points": 3 } ``` The `review_comment` field is used by agents to describe what they did. The `commits` field records commit hashes produced during the task. ### `DELETE /api/v1/tasks/:id` Delete a task (soft delete). ### `POST /api/v1/tasks/:id/approve` Approve a task in review status (moves to done). ### `POST /api/v1/tasks/:id/reject` Reject a task in review status (moves back to in_progress with feedback). **Body:** ```json { "reason": "Tests are failing" } ``` ### `POST /api/v1/tasks/:id/review-action` Combined review action endpoint. Supports `approve` (marks task done, unblocks children) or `fix` (creates a fix sub-task). **Body:** ```json { "action": "approve | fix", "comment": "string (optional)", "fix_description": "string (optional, used when action is fix)" } ``` **Response (approve):** ```json { "ok": true, "status": "done", "unblocked_children": [{ "id": "...", "title": "..." }] } ``` **Response (fix):** ```json { "ok": true, "status": "review", "fix_task": { "id": "...", "title": "Fix: original title" } } ``` ### `POST /api/v1/tasks/:id/review-report` Submit a structured review report for a task. If the task is currently `in_progress`, it is automatically transitioned to `review`. **Body:** ```json { "summary": "string (required)", "changes": "string (optional, description of changes made)", "test_results": "string (optional)", "commits": "string (optional, comma-separated commit hashes)", "notes": "string (optional)" } ``` **Response:** ```json { "ok": true } ``` --- ## Stories ### `GET /api/v1/stories` List all stories in the workspace. Stories group related tasks. ### `POST /api/v1/stories` Create a story. Auto-creates a Builder task for the story. **Body:** ```json { "title": "string (required)", "description": "string (optional)", "sprint": 1, "priority": "p1 (optional)" } ``` ### `GET /api/v1/stories/:id` Get a single story with its tasks. ### `PATCH /api/v1/stories/:id` Update a story. ### `DELETE /api/v1/stories/:id` Delete a story. ### `GET /api/v1/stories/:id/tasks` List tasks belonging to a story. --- ## Agents ### `GET /api/v1/agents` List all agents in the workspace with their current status. By default, finished child processes are excluded. | Param | Description | |-------|-------------| | `all` | Set to `true` to include all agents (including finished child processes) | ### `POST /api/v1/agents` Create an agent. **Body:** ```json { "name": "builder" } ``` ### `PUT /api/v1/agents` Upsert agent status. Used by the CLI to report agent state. This is an upsert -- if the agent does not exist, it is created. **Body:** ```json { "name": "builder", "status": "active", "activity": "Working on task-123", "parent_agent": "string (optional)", "ws_port": 4000 } ``` The `ws_port` field registers the CLI's WebSocket server port so the Dashboard can connect. ### `PUT /api/v1/agents/:name/config` Update agent engine configuration. **Body:** ```json { "engine": "claude-code", "execution_mode": "local", "api_key": "sk-... (optional, encrypted at rest)", "system_prompt": "Custom instructions..." } ``` ### `DELETE /api/v1/agents/:name` Remove an agent. Cannot delete `manager` or agents that have been active or have assigned tasks. ### `GET /api/v1/agents/:name/context` Return the assembled agent context (for debugging). Shows the full context that would be injected into the agent's system prompt. **Response:** ```json { "agent_name": "builder", "context": "Full context string...", "parts": { "..." : "..." } } ``` ### `GET /api/v1/agents/:name/api-docs` Return the API reference prompt for CLI/agent consumption. ### `GET /api/v1/agents/:name/prompt-preview` Return the full prompt that would be sent to the agent, for transparency. | Param | Description | |-------|-------------| | `mode` | `compact` (default) or `full` | **Response:** ```json { "agent_name": "builder", "role": "builder", "mode": "compact", "prompt": "...", "length": 5000, "token_estimate": 1250 } ``` ### `POST /api/v1/agents/check-stalls` Detect stalled agents (no heartbeat within the configured timeout). Updates their status to `stalled`. **Response:** ```json { "stalled": [{ "name": "builder", "last_seen": "2026-01-01T00:00:00" }], "count": 1 } ``` --- ## Agent Progress ### `POST /api/v1/agents/progress` Report agent progress (called by agent-runner during task execution). **Body:** ```json { "agent_name": "builder", "task_name": "string (optional)", "step": "string (optional)", "file": "string (optional)", "detail": "string (optional)" } ``` ### `GET /api/v1/agents/:name/progress` Get latest progress entries for a specific agent (up to 20). **Response:** ```json [ { "id": "...", "agent_name": "builder", "task_name": "Implement login", "step": "writing tests", "file": "src/auth.test.ts", "detail": "Added 3 test cases", "created_at": "2026-01-01T00:05:00" } ] ``` ### `GET /api/v1/agents/progress/latest` Get the latest progress entry per agent across the workspace. ### `DELETE /api/v1/agents/progress/purge` Purge progress data older than 24 hours. --- ## Agent Memories (Knowledge) ### `GET /api/v1/agents/memories` List all memory entries across all agents in the workspace. | Param | Description | |-------|-------------| | `type` | Filter by type: `identity`, `feedback`, `project`, `reference` | | `agent` | Filter by agent name | **Response:** ```json { "memories": [ { "id": "...", "workspace_id": "ws-abc123", "agent_name": "builder", "key": "preferred-framework", "type": "project", "content": "Use Next.js for all frontend work", "version": 1, "last_validated_at": "2026-01-01T00:00:00", "expires_days": 7, "updated_at": "2026-01-01T00:00:00", "created_at": "2026-01-01T00:00:00" } ], "count": 1 } ``` ### `GET /api/v1/agents/memories/shared` List shared memory entries visible to all agents in the workspace. ### `GET /api/v1/agents/memories/expired` List expired memory entries in the workspace (entries past their `expires_days` since `last_validated_at`). ### `GET /api/v1/agents/memories/search` Search memory entries by keyword across key and content fields. | Param | Description | |-------|-------------| | `q` | Search keyword (required) | | `type` | Filter by type (optional) | | `agent` | Filter by agent name (optional) | ### `GET /api/v1/agents/:name/memories` List all memory entries for a specific agent. Optional query param `type` to filter. ### `PUT /api/v1/agents/:name/memories/:key` Create or update a memory entry (upsert by agent name + key). Supports optimistic locking via `version`. **Body:** ```json { "content": "string (required, max 2000)", "type": "identity | feedback | project | reference (required)", "version": 1, "expires_days": 7 } ``` ### `POST /api/v1/agents/memories/:id/revalidate` Refresh `last_validated_at` to now, extending the memory's expiration window. ### `DELETE /api/v1/agents/:name/memories/:key` Delete a memory entry. --- ## Sprints ### `GET /api/v1/sprints` List all sprints. ### `POST /api/v1/sprints` Create a sprint. **Body:** ```json { "number": 1 } ``` The sprint defaults to `active` status. The `planning` status is accepted for backward compatibility but is not used in the current UX. The UI creates sprints as Active immediately. ### `POST /api/v1/sprints/current/start` Start the current sprint. This is the primary endpoint the CLI calls at startup. It: 1. Activates the sprint (sets status to `active`) 2. Sets assigned agents to `starting` status 3. Returns the full sprint context (tasks, agents, workspace info) **Response:** ```json { "sprint": { "number": 1, "status": "active" }, "agents": [{ "name": "builder", "status": "starting", "engine": "claude-code", "execution_mode": "local" }], "skippedAgents": [], "tasks": [...] } ``` ### `PATCH /api/v1/sprints/:number` Update sprint status or metadata. **Body:** ```json { "status": "review (optional)", "goal": "string (optional)", "deadline": "string (optional)" } ``` Status values: `planning`, `active`, `review`, `retrospective`, `completed` Valid transitions: `planning` -> `active` -> `review` -> `retrospective` -> `completed` (and `review` -> `active` for re-opening). > **Note**: `planning` exists for API backward compatibility. The UI starts sprints as Active by default. The primary phase flow is: Active -> Review -> Retrospective -> Completed. ### `GET /api/v1/sprints/current/tasks` Get tasks, agents, sprints list, latest agent progress, and repositories for the current active sprint. Supports query param `sprint` to specify a sprint number. ### `GET /api/v1/sprints/:number/review` Get sprint review data with summary, completion stats, tasks grouped by owner, and retrospective comments. ### `GET /api/v1/sprints/:number/retro` Get retrospective comments for a sprint. ### `POST /api/v1/sprints/:number/retro` Submit a retrospective comment. **Body:** ```json { "agent_name": "builder", "went_well": "Fast implementation of auth flow", "to_improve": "Need better test coverage", "suggested_tasks": [ { "title": "Add e2e tests for auth", "priority": "p1" } ] } ``` --- ## Analytics ### `GET /api/v1/sprints/:number/analytics` Sprint analytics data for charts. Includes summary stats, breakdowns by agent/type/priority, and burndown data. **Response:** ```json { "sprint": { "number": 1, "status": "active", "created_at": "...", "completed_at": null }, "summary": { "total": 10, "done": 6, "review": 2, "in_progress": 1, "todo": 1, "completion_rate": 60, "total_points": 30, "done_points": 18 }, "by_agent": { "builder": { "total": 5, "done": 3, "points": 15 } }, "by_type": { "feature": 6, "bug": 2, "chore": 2 }, "by_priority": { "p0": 3, "p1": 5, "p2": 2 }, "burndown": [ { "date": "2026-01-01", "remaining": 10 }, { "date": "2026-01-02", "remaining": 8 } ], "tasks": [ { "id": "...", "title": "...", "status": "done", "owner": "builder", "type": "feature", "story_points": 3 } ] } ``` ### `GET /api/v1/analytics/velocity` Cross-sprint velocity data. Shows task and story point completion across sprints. | Param | Description | |-------|-------------| | `limit` | Number of sprints to include (default: 10) | **Response:** ```json { "velocity": [ { "sprint": 1, "status": "completed", "total": 10, "done": 8, "total_points": 30, "done_points": 24 } ] } ``` ### `GET /api/v1/analytics/daily` Daily activity data including hourly task activity, cumulative completion trend, and scorecard. | Param | Description | |-------|-------------| | `date` | Date in YYYY-MM-DD format (default: today) | **Response:** ```json { "date": "2026-01-15", "scorecard": { "tasks_done": 5, "points": 12, "agents_active": 2, "types": { "feature": 3, "bug": 2 } }, "hourly": [ { "hour": 0, "done": 0, "started": 0, "total": 0 }, { "hour": 14, "done": 3, "started": 1, "total": 5 } ], "cumulative": [ { "date": "2026-01-14", "total": 20, "daily": 4 }, { "date": "2026-01-15", "total": 25, "daily": 5 } ], "tasks": [ { "id": "...", "title": "...", "owner": "builder", "type": "feature", "completed_at": "2026-01-15T14:30:00" } ] } ``` --- ## ADR (Architecture Decision Records) ### `GET /api/v1/adr` List all ADR records for the workspace, ordered by number descending. **Response:** ```json [ { "id": "uuid", "workspace_id": "ws-abc123", "number": 1, "title": "Use PostgreSQL for primary database", "status": "accepted", "context": "We need a relational database...", "decision": "Use PostgreSQL via Supabase", "rationale": "Strong SQL support, good ecosystem...", "consequences": "Need to manage migrations...", "author": "builder", "superseded_by": null, "created_at": "2026-01-01T00:00:00", "updated_at": "2026-01-01T00:00:00" } ] ``` ### `GET /api/v1/adr/prompt` Get ADR summary formatted as prompt text for agent injection. Returns accepted and proposed ADRs as a concise reference block. **Response:** ```json { "prompt": "\n### Architecture Decisions (ADR)\n..." } ``` ### `GET /api/v1/adr/:id` Get a single ADR by ID. ### `POST /api/v1/adr` Create a new ADR. The `number` is auto-assigned. **Body:** ```json { "title": "string (required)", "context": "string (required)", "decision": "string (required)", "rationale": "string (required)", "consequences": "string (optional)", "author": "string (optional)", "status": "proposed | accepted | deprecated | superseded (optional, default: proposed)" } ``` **Response:** `201 Created` ```json { "id": "uuid", "number": 1 } ``` ### `PATCH /api/v1/adr/:id` Update an ADR. All fields are optional. **Body:** ```json { "title": "string (optional)", "status": "proposed | accepted | deprecated | superseded (optional)", "context": "string (optional)", "decision": "string (optional)", "rationale": "string (optional)", "consequences": "string (optional)", "superseded_by": "uuid | null (optional)" } ``` ### `DELETE /api/v1/adr/:id` Delete an ADR. --- ## Messages ### `GET /api/v1/messages` Get messages. Supports query params: | Param | Description | |-------|-------------| | `channel` | Filter by channel (agent name) | | `mode` | `team` for team-wide messages | ### `POST /api/v1/messages` Send a message. **Body:** ```json { "from": "user", "to": "manager", "content": "Please prioritize the login feature" } ``` Messages are the API-polling fallback for communication. When the Dashboard is connected via WebSocket, messages flow through the WS server instead. --- ## Failures ### `GET /api/v1/failures` List failure records for the workspace. Failures are recorded when tasks fail or are rejected during review. ### `POST /api/v1/failures` Record a failure. --- ## Activity ### `GET /api/v1/activity` Get activity timeline for the workspace. --- ## Audit Logs ### `GET /api/v1/audit-logs` Get security audit logs (prompt injection attempts, auth events, agent spawns). --- ## Search ### `GET /api/v1/search?q=query` Search tasks and messages. --- ## Repos (GitHub) ### `GET /api/v1/repos` List repositories from the connected GitHub account/organization. ### `POST /api/v1/repos` Create a new GitHub repository. ### `GET /api/v1/repos/orgs` List GitHub organizations the user has access to. ### `GET /api/v1/repos/pulls` List pull requests for the connected repo. --- ## User Info ### `GET /api/v1/auth/me` Get current user info (GitHub login and avatar) from the workspace. This is the workspace-scoped variant; `GET /api/auth/me` (without `/v1/`) is the session-only check used by the auth flow. **Response:** ```json { "github_login": "octocat", "github_avatar": "https://avatars.githubusercontent.com/u/..." } ``` --- ## Assistant ### `GET /api/v1/assistant/templates` List available agent and project templates. **Response:** ```json { "agents": [{ "name": "builder", "..." : "..." }], "projects": [{ "..." : "..." }] } ``` ### `POST /api/v1/assistant/suggest-agents` Suggest agent composition based on project type. **Body:** ```json { "projectType": "web-app" } ``` **Response:** ```json { "agents": ["builder"], "details": [{ "name": "builder", "..." : "..." }] } ``` ### `POST /api/v1/assistant/translate-task` Convert a natural language instruction into a structured task. **Body:** ```json { "instruction": "Add dark mode to the settings page" } ``` **Response:** ```json { "task": { "title": "...", "description": "...", "type": "feature", "owner": "builder", "priority": "p1" } } ``` ### `POST /api/v1/assistant/generate-sprint0` Generate Sprint 0 tasks and create them in the database. **Body:** ```json { "projectName": "My App", "selectedAgents": ["builder"], "templateKey": "web-app (optional)", "language": "en | ja (optional)" } ``` **Response:** `201 Created` ```json { "tasks": [{ "id": "...", "title": "...", "description": "...", "owner": "builder", "priority": "p0" }], "agents": ["builder"] } ``` --- ## Admin (Site Owner Only) These endpoints require site owner access (the user who created the first workspace). ### `GET /api/v1/admin/settings` Get all site settings. ### `PUT /api/v1/admin/settings` Update site settings. **Body:** ```json { "maintenance_enabled": "true | false", "maintenance_message": "string", "banner_enabled": "true | false", "banner_message": "string", "banner_scheduled_at": "string" } ``` ### `GET /api/v1/admin/workspaces` List all workspaces (admin view). ### `GET /api/v1/admin/stats` Site-wide statistics. **Response:** ```json { "workspaces": 42, "active_workspaces_7d": 15, "total_tasks": 1200, "total_agents": 85 } ``` --- ## API Keys (Internal) These endpoints are mounted at `/api/keys` (no `/v1/` prefix, no workspace auth). ### `POST /api/keys` Generate a new API key for an agent. **Body:** ```json { "workspace_id": "ws-abc123", "agent_name": "builder" } ``` ### `GET /api/keys/:workspace_id` List keys for a workspace (prefix only, no secrets). ### `DELETE /api/keys/:id` Revoke an API key. --- ## Rate Limits | Endpoint Type | Limit | |--------------|-------| | Auth endpoints | 60 requests/minute | | API endpoints | 600 requests/minute | | Per-workspace | 600 requests/minute | | Write operations (per IP) | 60/minute per workspace | Rate limit headers are included in responses: - `X-RateLimit-Limit` - `X-RateLimit-Remaining` - `X-RateLimit-Reset` --- # ADR Guide (Architecture Decision Records) ADRs record important decisions about your project's architecture, process, and policies. They explain *why* a decision was made and *what* its consequences are — providing context that helps agents make better choices. ## When to Write an ADR Write an ADR when you make a decision that has lasting consequences: | Situation | ADR? | |---|---| | "We chose D1 over Postgres because of Cloudflare integration" | Yes (architecture decision) | | "System core tasks are assigned to user, not agents" | Yes (process decision) | | "Authentication uses GitHub App, not OAuth App" | Yes (design decision) | | "Use Zod for all API validation" | Yes (coding standard with rationale) | **Simple test**: Does the decision have a "because" or "rationale"? Write an ADR. For simple conventions without rationale, use your project's CLAUDE.md or Knowledge entries instead. ## How ADRs Work ADRs are injected into both the Manager and worker agent prompts. When making decisions (e.g., which tasks to propose, who to assign them to), agents consult ADRs as binding guidelines. The injection flow: 1. API builds an ADR summary from all `accepted` and `proposed` records 2. The summary is included in agent prompts under "## Architecture Decision Records" 3. Agents treat `ACCEPTED` ADRs as mandatory constraints ## ADR Structure Each ADR has: | Field | Description | |---|---| | **Title** | Short description of the decision | | **Status** | `proposed`, `accepted`, `deprecated`, `superseded` | | **Context** | Why this decision was needed (the problem) | | **Decision** | What was decided (the solution) | | **Rationale** | Why this approach was chosen over alternatives | | **Consequences** | What changes as a result (trade-offs) | ## Creating ADRs ### Via the Dashboard 1. Go to **Settings > ADR** 2. Click **New ADR** 3. Fill in the fields 4. Set status to `proposed` or `accepted` ### Via the API ```bash curl -X POST /api/v1/adr \ -H "Authorization: Bearer $TOBAN_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "title": "System core tasks assigned to user", "status": "accepted", "context": "AI agents modifying their own behavior logic creates safety risks", "decision": "Tasks involving prompts, CLI flow, auth, or DB schema changes are assigned to user", "rationale": "Core changes require design intent understanding that agents lack", "consequences": "Slower implementation of core features, but safer and more consistent" }' ``` ## Status Lifecycle ``` proposed → accepted → deprecated → superseded (by a newer ADR) ``` - **Proposed**: Under discussion, agents see it but it's not mandatory - **Accepted**: Binding, agents must follow it - **Deprecated**: No longer relevant, removed from prompts - **Superseded**: Replaced by a newer ADR ## Examples ### ADR-001: System Core Tasks Assigned to User - **Context**: AI agents modifying agent behavior logic, prompts, or security rules could cause unpredictable changes - **Decision**: Tasks involving (1) agent prompts/templates, (2) CLI execution flow, (3) Manager logic, (4) auth/security, (5) DB schema changes are assigned to `user` - **Rationale**: These require understanding of design intent that agents cannot reliably infer - **Consequences**: Core features take longer but remain safe and consistent ### ADR-002: Database Uses Cloudflare D1 - **Context**: Need a database for the API backend - **Decision**: Use Cloudflare D1 (SQLite-based) for all persistent storage - **Rationale**: Zero-config with Workers, no separate infrastructure to manage, generous free tier - **Consequences**: Limited to SQLite syntax, no full-text search, max 10GB per database ## Viewing ADR Prompts To see exactly what agents receive: ```bash curl $TOBAN_API_URL/api/v1/adr/prompt \ -H "Authorization: Bearer $TOBAN_API_KEY" ``` --- # Error Reference When you encounter an error, note the **error code** and **request ID** shown in the error message. These help us diagnose issues quickly. ## How to Read Errors API errors return: ```json { "error": "Human-readable message", "code": "ERR_TASK_NOT_FOUND", "request_id": "abc123def456" } ``` The `request_id` is also in the response header `X-Request-Id`. CLI errors are logged to `~/.toban/logs/error.log` in JSON format: ```json {"timestamp":"2026-03-18T10:00:00Z","code":"CLI_AGENT_SPAWN_FAILED","message":"...","context":{}} ``` --- ## API Error Codes ### Authentication (ERR_AUTH_*) | Code | HTTP | Cause | User Action | |---|---|---|---| | ERR_AUTH_MISSING | 401 | No API key or session cookie | Log in again or check API key | | ERR_AUTH_INVALID | 401 | API key not found in database | Regenerate API key in Settings | | ERR_AUTH_EXPIRED | 401 | Session older than 7 days | Log in again | | ERR_AUTH_FORBIDDEN | 403 | Agent trying to access other agent's resources | Check task ownership | ### Tasks (ERR_TASK_*) | Code | HTTP | Cause | User Action | |---|---|---|---| | ERR_TASK_NOT_FOUND | 404 | Task ID does not exist | Check the task ID, it may have been deleted | | ERR_TASK_VALIDATION | 400 | Invalid field values (bad priority, status, etc.) | Check the request body matches the schema | | ERR_TASK_DUPLICATE | 201 (warning) | Similar task title exists in same sprint | Consider using update_task instead | | ERR_TASK_UPDATE_FAILED | 500 | Database error during update | Retry; if persistent, check logs | ### Sprints (ERR_SPRINT_*) | Code | HTTP | Cause | User Action | |---|---|---|---| | ERR_SPRINT_NOT_FOUND | 404 | Sprint number does not exist | Check sprint number | | ERR_SPRINT_TRANSITION | 400 | Invalid phase transition (e.g., skipping review) | Follow the flow: active -> review -> retrospective -> completed. Cannot skip phases. | | ERR_SPRINT_VALIDATION | 400 | Invalid sprint data | Check request body | ### Agents (ERR_AGENT_*) | Code | HTTP | Cause | User Action | |---|---|---|---| | ERR_AGENT_NOT_FOUND | 404 | Agent name not in database | Check agent name spelling | | ERR_AGENT_FORBIDDEN | 403 | Agent trying to modify another agent's task | Assign the task to the correct agent | | ERR_AGENT_SPAWN_BLOCKED | 409 | Same agent already running | Wait for the current task to finish | ### Review (ERR_REVIEW_*) | Code | HTTP | Cause | User Action | |---|---|---|---| | ERR_REVIEW_VALIDATION | 400 | Missing required review fields | Include all fields: requirement_match, files_changed, code_quality, test_coverage, risks, verdict | | ERR_REVIEW_TASK_NOT_FOUND | 404 | Task not found for review submission | Check task ID | ### General | Code | HTTP | Cause | User Action | |---|---|---|---| | ERR_VALIDATION | 400 | Request body failed Zod validation | Check the `details` array for specific field errors | | ERR_NOT_FOUND | 404 | Resource not found | Check the URL and ID | | ERR_RATE_LIMITED | 429 | Too many requests (600/min API, 60/min auth) | Wait a moment and retry | | ERR_INTERNAL | 500 | Unexpected server error | Note the request_id and report it | | ERR_MAINTENANCE | 503 | System is in maintenance mode | Wait for maintenance to complete | --- ## CLI Error Codes ### Agent Lifecycle (CLI_AGENT_*) | Code | Cause | Action | |---|---|---| | CLI_AGENT_SPAWN_FAILED | Claude CLI failed to start | Check `claude --version`, ensure Claude Code is installed | | CLI_AGENT_TIMEOUT | Agent exceeded time limit | Task may be too large; split into smaller tasks | | CLI_AGENT_CRASH | Agent process exited unexpectedly | Check agent stdout in terminal panel for details | ### Git Operations (CLI_GIT_*) | Code | Cause | Action | |---|---|---| | CLI_GIT_CLONE_FAILED | Repository clone failed | Check GitHub App permissions and repo URL | | CLI_GIT_MERGE_FAILED | Merge conflict or worktree issue | Check if files were modified concurrently | | CLI_GIT_PUSH_FAILED | Push rejected after rebase retry | Remote may have diverged; pull and retry manually | | CLI_GIT_WORKTREE_FAILED | Worktree creation failed | Check disk space and git status | ### API Communication (CLI_API_*) | Code | Cause | Action | |---|---|---| | CLI_API_REQUEST_FAILED | API request returned error | Check API URL and network connectivity | | CLI_API_AUTH_FAILED | API key rejected | Regenerate API key in dashboard Settings | | CLI_API_TIMEOUT | API did not respond in time | Check if Cloudflare Workers is running | ### Review (CLI_REVIEW_*) | Code | Cause | Action | |---|---|---| | CLI_REVIEW_LLM_FAILED | Claude CLI review process failed | Check `claude` is accessible and API quota | | CLI_REVIEW_LLM_TIMEOUT | Review took longer than 120s | Diff may be too large; this is non-fatal (fallback to text review) | | CLI_REVIEW_PARSE_FAILED | LLM output was not valid JSON | Non-fatal; falls back to text review | | CLI_REVIEW_API_FAILED | Review report API returned error | Check API logs with request_id | ### Template Actions (CLI_ACTION_*) | Code | Cause | Action | |---|---|---| | CLI_ACTION_FAILED | Pre/post action threw an error | Check ~/.toban/logs/error.log for details | | CLI_MEMORY_INJECT_FAILED | Failed to inject memories into CLAUDE.md | Non-fatal; agent runs without memories | | CLI_MEMORY_COLLECT_FAILED | Failed to collect memories after task | Non-fatal; memories not saved | --- ## Troubleshooting ### "Auto-review failed. Please review manually." This means the `review_changes` post-action failed. Common causes: 1. Worktree was deleted before review could run 2. Claude CLI timed out (120s limit for large diffs) 3. LLM returned non-JSON response Check `~/.toban/logs/error.log` for the specific CLI_REVIEW_* code. ### Sprint phase won't change Valid transitions: active -> review -> retrospective -> completed. You cannot skip phases (e.g., active -> completed returns ERR_SPRINT_TRANSITION). ### Agent not picking up tasks 1. Check CLI is running (`curl localhost:4000/health`) 2. Task must have `owner` set to an agent role (builder, cloud-engineer, etc.) 3. Task must be in the current active sprint 4. Same agent cannot run two tasks simultaneously ### Error log location CLI errors: `~/.toban/logs/error.log` API errors: Cloudflare Workers dashboard > Logs --- # Security Guide Toban is designed with security as a core principle. This guide explains the security model, isolation mechanisms, and best practices for running AI agents safely on your codebase. ## Security Model Overview Toban enforces security at multiple layers: 1. **Authentication** -- GitHub OAuth for users, workspace-scoped API keys for CLI 2. **CSRF protection** -- Token-based CSRF defense on all dashboard API calls 3. **Agent isolation** -- Each agent runs in its own git worktree 4. **Role boundaries** -- Agents can only perform role-appropriate actions 5. **Input validation** -- All data validated and sanitized via Zod schemas 6. **Workspace-scoped access** -- API keys and data are isolated per workspace ## Authentication ### GitHub OAuth Flow 1. User clicks "Sign in with GitHub" on the dashboard 2. Browser redirects to GitHub's authorization page 3. User approves, GitHub redirects back with an authorization code 4. The API exchanges the code for an access token 5. The API creates a session and sets a secure HTTP-only cookie 6. Subsequent dashboard requests include the session cookie The session cookie is HTTP-only and secure (HTTPS-only in production). The dashboard never has direct access to the GitHub token. ### CSRF Protection All state-changing requests from the dashboard include a CSRF token: 1. The dashboard fetches a CSRF token from the API on page load 2. The token is included in a custom header on every POST/PUT/PATCH/DELETE request 3. The API validates the token against the session before processing the request The API proxy route (`/api/proxy/[...path]`) handles CSRF token injection automatically. ### API Key Authentication CLI and programmatic access uses Bearer tokens in the format `tb_ws{workspace_id}_sk_{secret}`: - Each key is scoped to a **single Project** (workspace) - Keys cannot access data from other Projects - User session keys are auto-generated on login and expire after 7 days of inactivity (sliding window) - Agent keys (used by the CLI) expire after 24 hours of inactivity (sliding window extends on use) ## Agent Sandboxing ### Git Worktree Isolation Every agent task runs in an isolated git worktree: ``` your-repo/ ├── src/ <-- Your working directory (untouched) └── .worktrees/ └── builder-task-123/ <-- Agent's isolated copy ├── src/ └── ... ``` This means: - Agents cannot modify your working directory directly - Each agent has its own branch and working copy - Failed or rejected work is discarded without affecting your code - Multiple agents can work simultaneously without conflicts ### Branch Isolation Each agent creates a dedicated branch: ``` agent/builder-task-123 agent/cloud-eng-task-456 ``` Completed work is merged back to the base branch with `--no-ff` (no fast-forward), preserving a clear merge history. ### Automatic Cleanup When an agent finishes (or fails), its worktree is automatically cleaned up. No stale branches or orphaned directories are left behind. ### Manager Permission Mode The Manager agent (which coordinates sprints and responds to chat) runs with restricted permissions. When using the Claude Code CLI engine, the Manager is launched with `--permission-mode plan`, which limits its ability to execute arbitrary tools. The Manager can analyze and plan but relies on ACTION blocks to request changes, which require user approval. Other engines may have different permission models. ### Task Auto-Start When the CLI is connected, tasks assigned to agent roles (builder, cloud-engineer, etc.) are automatically picked up and executed. Tasks assigned to `user` are never auto-started. To prevent agents from working on a task, set its owner to `user` before connecting the CLI. > **Note**: Auto-start is the recommended workflow for fast iteration. A manual approval mode (approve/reject before each agent starts) will be available as an opt-in setting in a future release. ## Credential Management ### GitHub App Installation Tokens Toban uses a **git credential helper** that fetches fresh GitHub App installation tokens on demand: 1. At CLI startup, a shell script is written to `~/.toban/git-credential-helper.sh` (mode `0700`, owner-only executable) 2. The script calls `GET /api/v1/workspace/git-token` with the workspace API key 3. The API returns a short-lived GitHub App installation token (1 hour expiry) 4. Git invokes this helper automatically on push/pull operations This avoids: - Storing long-lived tokens on disk - Embedding tokens in git remote URLs (which are visible in `.git/config`) - Token expiry issues during long-running agent tasks After initial clone, any embedded tokens in remote URLs are cleaned and replaced with plain `https://github.com/...` URLs. ## Role Boundaries Each agent role has strictly defined capabilities enforced in the system prompt: | Role | Can Do | Cannot Do | |------|--------|-----------| | **Manager** | Coordinate sprints, propose tasks, review backlog | Write code directly | | **Builder** | Write code, run tests, commit changes | Modify infrastructure | If an agent is asked to perform work outside its role, the prompt instructs it to refuse and suggest the appropriate agent. ## Input Validation All data entering the system is validated with Zod schemas: | Context | Max Length | Validation | |---------|-----------|------------| | Project spec | 10 KB | HTML sanitized | | Task description | 2 KB | HTML sanitized | | Message content | 2 KB | HTML sanitized | | Agent name | 64 chars | Alphanumeric + hyphens only | ### HTML Sanitization All user input is sanitized to remove: - `