# Kandev Agents Guide > ⚠️ **IMPORTANT**: API documentation must be updated whenever the API changes. > When modifying any endpoint, request/response types, or ACP messages, update: > - This document (AGENTS.md) > - The OpenAPI spec (docs/openapi.yaml) πŸ“– **Full API Reference**: See [docs/openapi.yaml](docs/openapi.yaml) for the complete OpenAPI 3.0 specification. You can view it with Swagger UI, Redoc, or import it into Postman. ## Overview Kandev uses Docker containers to run AI agents that execute tasks from the Kanban board. Agents communicate with the backend using the **Agent Communication Protocol (ACP)**, a JSON-based streaming protocol. ## Architecture ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ HTTP Client │────▢│ Kandev Backend │────▢│ Docker Container β”‚ β”‚ (Frontend/CLI) β”‚ β”‚ (Port 8080) β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ auggie --acp β”‚ β”‚ β”‚ β”‚ β”‚ (ACP Mode) β”‚ β”‚ │◀─────────────▢│ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ JSON-RPC β”‚ β”‚ β”‚ stdin/stdout β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Event Bus β”‚ β”‚ (In-Memory) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` **Bidirectional Communication:** - Backend β†’ Agent: `session/prompt`, `session/cancel` - Agent β†’ Backend: `session/update` notifications ## Available Agent Types ### Augment Agent (`augment-agent`) The primary AI coding agent powered by Auggie CLI. | Property | Value | |----------|-------| | Image | `kandev/augment-agent:latest` | | Working Directory | `/workspace` | | Memory Limit | 4096 MB | | CPU Cores | 2.0 | | Timeout | 1 hour | | Capabilities | code_generation, code_review, refactoring, testing, shell_execution | **Required Environment Variables:** - `AUGMENT_SESSION_AUTH` - Augment CLI session authentication (from `~/.augment/session.json`) - `TASK_DESCRIPTION` - The task for the agent to execute **Optional Environment Variables:** - `AUGGIE_SESSION_ID` - Resume a previous session (for follow-up tasks) **Mounted Volumes:** - `{workspace}` β†’ `/workspace` - The project directory - `{augment_sessions}` β†’ `/root/.augment/sessions` - Session persistence --- ## Agent Communication Protocol (ACP) Kandev uses **ACP (Agent Client Protocol)** for bidirectional communication with agents. ACP is based on JSON-RPC 2.0 over stdin/stdout. ### ACP Mode Agents run in ACP mode using `auggie --acp`. This enables: - **Bidirectional communication**: Send prompts and receive updates - **Session management**: Create, load, and resume sessions - **Cancellation**: Cancel operations in progress ### JSON-RPC 2.0 Protocol #### Client β†’ Agent (Requests) **Initialize Connection:** ```json {"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": { "protocolVersion": "1.0", "clientInfo": {"name": "kandev", "version": "0.1.0"}, "capabilities": {"streaming": true} }} ``` **Create New Session:** ```json {"jsonrpc": "2.0", "id": 2, "method": "session/new", "params": {}} ``` **Resume Existing Session:** ```json {"jsonrpc": "2.0", "id": 3, "method": "session/load", "params": {"sessionId": "abc123"}} ``` **Send Prompt:** ```json {"jsonrpc": "2.0", "id": 4, "method": "session/prompt", "params": {"message": "Fix the bug in main.go"}} ``` **Cancel Operation (notification, no response):** ```json {"jsonrpc": "2.0", "method": "session/cancel", "params": {"reason": "user requested"}} ``` #### Agent β†’ Client (Notifications) **Session Update (progress, content, tool calls):** ```json {"jsonrpc": "2.0", "method": "session/update", "params": { "type": "content", "data": {"text": "I'm analyzing the code..."} }} ``` ```json {"jsonrpc": "2.0", "method": "session/update", "params": { "type": "toolCall", "data": {"toolName": "file_edit", "status": "running"} }} ``` ```json {"jsonrpc": "2.0", "method": "session/update", "params": { "type": "complete", "data": {"sessionId": "abc123", "success": true} }} ``` ### Legacy Message Format (for reference) ```json { "type": "progress", "agent_id": "uuid", "task_id": "uuid", "timestamp": "2026-01-10T12:00:00Z", "data": { ... } } ``` ### Legacy Message Types #### `progress` - Progress Updates ```json { "type": "progress", "data": { "progress": 50, "message": "Analyzing codebase...", "current_file": "src/main.go", "files_processed": 10, "total_files": 20 } } ``` #### `log` - Log Messages ```json { "type": "log", "data": { "level": "info", "message": "Starting code review", "metadata": { "file": "main.go" } } } ``` Levels: `debug`, `info`, `warn`, `error` #### `result` - Task Completion ```json { "type": "result", "data": { "status": "completed", "summary": "Task completed successfully", "artifacts": [ { "type": "report", "path": "/workspace/report.md" } ] } } ``` Status: `completed`, `failed`, `cancelled` #### `error` - Error Messages ```json { "type": "error", "data": { "error": "Failed to parse file", "file": "broken.go", "details": "syntax error on line 42" } } ``` #### `status` - Agent Status Changes ```json { "type": "status", "data": { "status": "running", "message": "Agent initialized" } } ``` Status: `started`, `running`, `paused`, `stopped` #### `heartbeat` - Keep-Alive ```json { "type": "heartbeat", "data": {} } ``` --- ## REST API Reference Base URL: `http://localhost:8080/api/v1` ### Health Check ``` GET /health ``` Response: ```json { "status": "ok" } ``` --- ## Boards API ### Create Board ``` POST /boards ``` Request: ```json { "name": "My Project", "description": "Project tasks" } ``` Response: `201 Created` ```json { "id": "uuid", "name": "My Project", "description": "Project tasks", "created_at": "2026-01-10T12:00:00Z", "updated_at": "2026-01-10T12:00:00Z" } ``` ### List Boards ``` GET /boards ``` Response: ```json { "boards": [...], "total": 5 } ``` ### Get Board ``` GET /boards/:boardId ``` ### Update Board ``` PUT /boards/:boardId ``` Request: ```json { "name": "Updated Name", "description": "Updated description" } ``` ### Delete Board ``` DELETE /boards/:boardId ``` --- ## Columns API ### Create Column ``` POST /boards/:boardId/columns ``` Request: ```json { "name": "To Do", "position": 0, "state": "TODO" } ``` Response: `201 Created` ```json { "id": "uuid", "board_id": "uuid", "name": "To Do", "position": 0, "state": "TODO", "created_at": "2026-01-10T12:00:00Z" } ``` ### List Columns ``` GET /boards/:boardId/columns ``` ### Get Column ``` GET /columns/:columnId ``` --- ## Tasks API ### Create Task ``` POST /tasks ``` Request: ```json { "board_id": "uuid", "column_id": "uuid", "title": "Fix login bug", "description": "Users cannot login with email", "priority": 1, "agent_type": "augment-agent", "metadata": {} } ``` Response: `201 Created` ```json { "id": "uuid", "board_id": "uuid", "column_id": "uuid", "title": "Fix login bug", "description": "Users cannot login with email", "state": "TODO", "priority": 1, "agent_type": "augment-agent", "position": 0, "created_at": "2026-01-10T12:00:00Z", "updated_at": "2026-01-10T12:00:00Z", "metadata": {} } ``` ### Get Task ``` GET /tasks/:taskId ``` ### Update Task ``` PUT /tasks/:taskId ``` Request (all fields optional): ```json { "title": "Updated title", "description": "Updated description", "priority": 2, "metadata": { "key": "value" } } ``` ### Delete Task ``` DELETE /tasks/:taskId ``` ### Update Task State ``` PUT /tasks/:taskId/state ``` Request: ```json { "state": "IN_PROGRESS" } ``` States: `TODO`, `IN_PROGRESS`, `BLOCKED`, `COMPLETED`, `FAILED`, `CANCELLED` ### Move Task ``` PUT /tasks/:taskId/move ``` Request: ```json { "column_id": "uuid", "position": 0 } ``` ### List Tasks in Board ``` GET /boards/:boardId/tasks ``` --- ## Agents API ### Launch Agent ``` POST /agents/launch ``` Request: ```json { "task_id": "uuid", "agent_type": "augment-agent", "workspace_path": "/path/to/project", "env": { "AUGMENT_SESSION_AUTH": "...", "TASK_DESCRIPTION": "Analyze this codebase" }, "priority": 1, "metadata": {} } ``` Response: `201 Created` ```json { "id": "uuid", "task_id": "uuid", "agent_type": "augment-agent", "container_id": "docker-container-id", "status": "starting", "progress": 0, "started_at": "2026-01-10T12:00:00Z" } ``` ### List Agents ``` GET /agents ``` Response: ```json { "agents": [...], "total": 3 } ``` ### Get Agent Status ``` GET /agents/:instanceId/status ``` Response: ```json { "id": "uuid", "task_id": "uuid", "agent_type": "augment-agent", "container_id": "docker-container-id", "status": "running", "progress": 50, "started_at": "2026-01-10T12:00:00Z", "finished_at": null, "exit_code": null, "error_message": "" } ``` Agent statuses: `starting`, `running`, `completed`, `failed`, `stopped` ### Get Agent Logs ``` GET /agents/:instanceId/logs?tail=100 ``` Response: ```json { "logs": [ { "timestamp": "2026-01-10T12:00:00Z", "message": "Starting agent...", "stream": "stdout" } ], "total": 50 } ``` ### Stop Agent ``` DELETE /agents/:instanceId ``` Request (optional body): ```json { "force": false, "reason": "User requested stop" } ``` ### List Agent Types ``` GET /agents/types ``` Response: ```json { "types": [ { "id": "augment-agent", "name": "Augment Coding Agent", "description": "Auggie CLI-powered autonomous coding agent", "image": "kandev/augment-agent", "capabilities": ["code_generation", "code_review", "refactoring", "testing", "shell_execution"], "enabled": true } ], "total": 1 } ``` ### Get Agent Type ``` GET /agents/types/:typeId ``` ### Send Prompt to Agent (ACP) ``` POST /agents/:instanceId/prompt ``` Request: ```json { "message": "Fix the bug in main.go" } ``` Response: `200 OK` ```json { "success": true, "message": "Prompt sent successfully" } ``` ### Cancel Agent Operation (ACP) ``` POST /agents/:instanceId/cancel ``` Request: ```json { "reason": "User requested cancellation" } ``` Response: `200 OK` ```json { "success": true, "message": "Cancel request sent" } ``` ### Get Agent Session (ACP) ``` GET /agents/:instanceId/session ``` Response: `200 OK` ```json { "instance_id": "uuid", "task_id": "uuid", "session_id": "abc123", "status": "running", "created_at": "2026-01-10T12:00:00Z" } ``` --- ## Orchestrator API Base: `/api/v1/orchestrator` ### Get Orchestrator Status ``` GET /orchestrator/status ``` ### Get Task Queue ``` GET /orchestrator/queue ``` Response: ```json { "tasks": [ { "task_id": "uuid", "priority": 1, "queued_at": "2026-01-10T12:00:00Z" } ], "total": 5 } ``` ### Trigger Task Execution ``` POST /orchestrator/trigger ``` Request: ```json { "task_id": "uuid", "force": false } ``` ### Start Task ``` POST /orchestrator/tasks/:taskId/start ``` ### Stop Task ``` POST /orchestrator/tasks/:taskId/stop ``` ### Pause Task ``` POST /orchestrator/tasks/:taskId/pause ``` ### Resume Task ``` POST /orchestrator/tasks/:taskId/resume ``` ### Get Task Execution Status ``` GET /orchestrator/tasks/:taskId/status ``` ### Get Task Logs ``` GET /orchestrator/tasks/:taskId/logs ``` ### Get Task Artifacts ``` GET /orchestrator/tasks/:taskId/artifacts ``` --- ## Session Resumption Agents can resume previous sessions for follow-up tasks: 1. **First task** - Launch agent normally, session ID stored in task metadata 2. **Get session ID** from task: `GET /tasks/:taskId` β†’ `metadata.auggie_session_id` 3. **Follow-up task** - Launch with `AUGGIE_SESSION_ID` env var Example: ```bash # Get session ID from completed task SESSION_ID=$(curl -s http://localhost:8080/api/v1/tasks/$TASK_ID | jq -r '.metadata.auggie_session_id') # Launch follow-up with session resumption curl -X POST http://localhost:8080/api/v1/agents/launch \ -H "Content-Type: application/json" \ -d '{ "task_id": "'$NEW_TASK_ID'", "agent_type": "augment-agent", "workspace_path": "/path/to/project", "env": { "AUGMENT_SESSION_AUTH": "...", "AUGGIE_SESSION_ID": "'$SESSION_ID'", "TASK_DESCRIPTION": "What was my previous question?" } }' ``` --- ## Error Responses All error responses follow this format: ```json { "error": "error_code", "message": "Human readable message", "details": "Additional details", "http_status": 400 } ``` Common error codes: - `bad_request` (400) - Invalid request body or parameters - `not_found` (404) - Resource not found - `validation_error` (400) - Validation failed - `internal_error` (500) - Server error --- ## Creating Custom Agents To create a new agent type: 1. **Create Dockerfile** in `backend/dockerfiles/your-agent/` 2. **Implement ACP** - Write JSON messages to stdout 3. **Register agent** in `backend/internal/agent/registry/defaults.go` 4. **Build image**: `docker build -t kandev/your-agent:latest .` Example agent script: ```bash #!/bin/bash echo '{"type":"status","agent_id":"'$AGENT_ID'","task_id":"'$TASK_ID'","timestamp":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'","data":{"status":"started"}}' echo '{"type":"progress","agent_id":"'$AGENT_ID'","task_id":"'$TASK_ID'","timestamp":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'","data":{"progress":50,"message":"Working..."}}' # Do work here echo '{"type":"result","agent_id":"'$AGENT_ID'","task_id":"'$TASK_ID'","timestamp":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'","data":{"status":"completed","summary":"Done!"}}' ``` --- ## Development Notes ### Running Locally ```bash cd backend make build ./bin/kandev ``` ### Running Tests ```bash cd backend go test ./... ``` ### Environment Variables | Variable | Default | Description | |----------|---------|-------------| | `KANDEV_DB_PATH` | `./kandev.db` | SQLite database path | | `PORT` | `8080` | HTTP server port | --- **Last Updated**: 2026-01-10