openapi: 3.0.3 info: title: Kandev API description: | Kandev is a Kanban board system with AI agent orchestration capabilities. ## Overview - **Task Service**: Manages tasks, boards, and columns - **Agent Manager**: Manages Docker container lifecycle for AI agents - **Orchestrator**: Coordinates agent execution ## Agent Communication Protocol (ACP) Agents communicate via JSON messages on stdout. See AGENTS.md for details. ⚠️ **This documentation must be updated when API changes.** version: 1.0.0 contact: name: Kandev Team license: name: MIT servers: - url: http://localhost:8080/api/v1 description: Local development server tags: - name: Health description: Health check endpoints - name: Boards description: Kanban board management - name: Columns description: Board column management - name: Tasks description: Task management - name: Agents description: AI agent lifecycle management - name: Agent Types description: Available agent type configurations - name: Orchestrator description: Task orchestration and execution control paths: /health: get: tags: [Health] summary: Health check operationId: healthCheck responses: '200': description: Service is healthy content: application/json: schema: $ref: '#/components/schemas/HealthResponse' # ============ BOARDS ============ /boards: get: tags: [Boards] summary: List all boards operationId: listBoards responses: '200': description: List of boards content: application/json: schema: $ref: '#/components/schemas/BoardsListResponse' post: tags: [Boards] summary: Create a new board operationId: createBoard requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateBoardRequest' responses: '201': description: Board created content: application/json: schema: $ref: '#/components/schemas/Board' '400': $ref: '#/components/responses/BadRequest' /boards/{boardId}: parameters: - $ref: '#/components/parameters/boardId' get: tags: [Boards] summary: Get a board by ID operationId: getBoard responses: '200': description: Board details content: application/json: schema: $ref: '#/components/schemas/Board' '404': $ref: '#/components/responses/NotFound' put: tags: [Boards] summary: Update a board operationId: updateBoard requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateBoardRequest' responses: '200': description: Board updated content: application/json: schema: $ref: '#/components/schemas/Board' '404': $ref: '#/components/responses/NotFound' delete: tags: [Boards] summary: Delete a board operationId: deleteBoard responses: '204': description: Board deleted '404': $ref: '#/components/responses/NotFound' /boards/{boardId}/columns: parameters: - $ref: '#/components/parameters/boardId' get: tags: [Columns] summary: List columns in a board operationId: listColumns responses: '200': description: List of columns content: application/json: schema: $ref: '#/components/schemas/ColumnsListResponse' post: tags: [Columns] summary: Create a column in a board operationId: createColumn requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateColumnRequest' responses: '201': description: Column created content: application/json: schema: $ref: '#/components/schemas/Column' '400': $ref: '#/components/responses/BadRequest' /boards/{boardId}/tasks: parameters: - $ref: '#/components/parameters/boardId' get: tags: [Tasks] summary: List tasks in a board operationId: listTasksInBoard responses: '200': description: List of tasks content: application/json: schema: $ref: '#/components/schemas/TasksListResponse' # ============ COLUMNS ============ /columns/{columnId}: parameters: - $ref: '#/components/parameters/columnId' get: tags: [Columns] summary: Get a column by ID operationId: getColumn responses: '200': description: Column details content: application/json: schema: $ref: '#/components/schemas/Column' '404': $ref: '#/components/responses/NotFound' # ============ TASKS ============ /tasks: post: tags: [Tasks] summary: Create a new task operationId: createTask requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/CreateTaskRequest' responses: '201': description: Task created content: application/json: schema: $ref: '#/components/schemas/Task' '400': $ref: '#/components/responses/BadRequest' /tasks/{taskId}: parameters: - $ref: '#/components/parameters/taskId' get: tags: [Tasks] summary: Get a task by ID operationId: getTask responses: '200': description: Task details content: application/json: schema: $ref: '#/components/schemas/Task' '404': $ref: '#/components/responses/NotFound' put: tags: [Tasks] summary: Update a task operationId: updateTask requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateTaskRequest' responses: '200': description: Task updated content: application/json: schema: $ref: '#/components/schemas/Task' '404': $ref: '#/components/responses/NotFound' delete: tags: [Tasks] summary: Delete a task operationId: deleteTask responses: '204': description: Task deleted '404': $ref: '#/components/responses/NotFound' /tasks/{taskId}/state: parameters: - $ref: '#/components/parameters/taskId' put: tags: [Tasks] summary: Update task state operationId: updateTaskState requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/UpdateTaskStateRequest' responses: '200': description: Task state updated content: application/json: schema: $ref: '#/components/schemas/Task' '404': $ref: '#/components/responses/NotFound' /tasks/{taskId}/move: parameters: - $ref: '#/components/parameters/taskId' put: tags: [Tasks] summary: Move task to different column operationId: moveTask requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/MoveTaskRequest' responses: '200': description: Task moved content: application/json: schema: $ref: '#/components/schemas/Task' '404': $ref: '#/components/responses/NotFound' # ============ AGENTS ============ /agents: get: tags: [Agents] summary: List all active agents operationId: listAgents responses: '200': description: List of agents content: application/json: schema: $ref: '#/components/schemas/AgentsListResponse' /agents/launch: post: tags: [Agents] summary: Launch a new agent operationId: launchAgent requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/LaunchAgentRequest' responses: '201': description: Agent launched content: application/json: schema: $ref: '#/components/schemas/AgentInstance' '400': $ref: '#/components/responses/BadRequest' /agents/types: get: tags: [Agent Types] summary: List available agent types operationId: listAgentTypes responses: '200': description: List of agent types content: application/json: schema: $ref: '#/components/schemas/AgentTypesListResponse' /agents/types/{typeId}: parameters: - $ref: '#/components/parameters/typeId' get: tags: [Agent Types] summary: Get agent type by ID operationId: getAgentType responses: '200': description: Agent type details content: application/json: schema: $ref: '#/components/schemas/AgentType' '404': $ref: '#/components/responses/NotFound' /agents/{instanceId}/status: parameters: - $ref: '#/components/parameters/instanceId' get: tags: [Agents] summary: Get agent status operationId: getAgentStatus responses: '200': description: Agent status content: application/json: schema: $ref: '#/components/schemas/AgentInstance' '404': $ref: '#/components/responses/NotFound' /agents/{instanceId}/logs: parameters: - $ref: '#/components/parameters/instanceId' get: tags: [Agents] summary: Get agent logs operationId: getAgentLogs parameters: - name: tail in: query description: Number of lines to return from end schema: type: string default: "100" - name: follow in: query description: Stream logs in real-time schema: type: boolean default: false responses: '200': description: Agent logs content: application/json: schema: $ref: '#/components/schemas/LogsResponse' '404': $ref: '#/components/responses/NotFound' /agents/{instanceId}: parameters: - $ref: '#/components/parameters/instanceId' delete: tags: [Agents] summary: Stop an agent operationId: stopAgent requestBody: content: application/json: schema: $ref: '#/components/schemas/StopAgentRequest' responses: '200': description: Agent stopped content: application/json: schema: $ref: '#/components/schemas/AgentInstance' '404': $ref: '#/components/responses/NotFound' /agents/{instanceId}/prompt: parameters: - $ref: '#/components/parameters/instanceId' post: tags: [Agents] summary: Send prompt to agent (ACP) description: Send a message/prompt to a running agent via ACP protocol operationId: sendAgentPrompt requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/SendPromptRequest' responses: '200': description: Prompt sent successfully content: application/json: schema: $ref: '#/components/schemas/SendPromptResponse' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalError' /agents/{instanceId}/cancel: parameters: - $ref: '#/components/parameters/instanceId' post: tags: [Agents] summary: Cancel agent operation (ACP) description: Send a cancellation request to a running agent via ACP protocol operationId: cancelAgent requestBody: content: application/json: schema: $ref: '#/components/schemas/CancelAgentRequest' responses: '200': description: Cancel request sent content: application/json: schema: $ref: '#/components/schemas/CancelAgentResponse' '404': $ref: '#/components/responses/NotFound' '500': $ref: '#/components/responses/InternalError' /agents/{instanceId}/session: parameters: - $ref: '#/components/parameters/instanceId' get: tags: [Agents] summary: Get agent ACP session description: Get the current ACP session information for an agent operationId: getAgentSession responses: '200': description: Session information content: application/json: schema: $ref: '#/components/schemas/GetSessionResponse' '404': $ref: '#/components/responses/NotFound' # ============ ORCHESTRATOR ============ /orchestrator/status: get: tags: [Orchestrator] summary: Get orchestrator status operationId: getOrchestratorStatus responses: '200': description: Orchestrator status content: application/json: schema: $ref: '#/components/schemas/OrchestratorStatus' /orchestrator/queue: get: tags: [Orchestrator] summary: Get task queue operationId: getQueue responses: '200': description: Task queue content: application/json: schema: $ref: '#/components/schemas/QueueResponse' /orchestrator/trigger: post: tags: [Orchestrator] summary: Manually trigger task execution operationId: triggerTask requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/TriggerTaskRequest' responses: '200': description: Task triggered '400': $ref: '#/components/responses/BadRequest' /orchestrator/tasks/{taskId}/start: parameters: - $ref: '#/components/parameters/taskId' post: tags: [Orchestrator] summary: Start task execution operationId: startTask requestBody: content: application/json: schema: $ref: '#/components/schemas/StartTaskRequest' responses: '200': description: Task started '404': $ref: '#/components/responses/NotFound' /orchestrator/tasks/{taskId}/stop: parameters: - $ref: '#/components/parameters/taskId' post: tags: [Orchestrator] summary: Stop task execution operationId: stopTask requestBody: content: application/json: schema: $ref: '#/components/schemas/StopTaskRequest' responses: '200': description: Task stopped '404': $ref: '#/components/responses/NotFound' /orchestrator/tasks/{taskId}/pause: parameters: - $ref: '#/components/parameters/taskId' post: tags: [Orchestrator] summary: Pause task execution operationId: pauseTask responses: '200': description: Task paused '404': $ref: '#/components/responses/NotFound' /orchestrator/tasks/{taskId}/resume: parameters: - $ref: '#/components/parameters/taskId' post: tags: [Orchestrator] summary: Resume task execution operationId: resumeTask responses: '200': description: Task resumed '404': $ref: '#/components/responses/NotFound' /orchestrator/tasks/{taskId}/status: parameters: - $ref: '#/components/parameters/taskId' get: tags: [Orchestrator] summary: Get task execution status operationId: getTaskExecutionStatus responses: '200': description: Task execution status content: application/json: schema: $ref: '#/components/schemas/TaskStatusResponse' '404': $ref: '#/components/responses/NotFound' /orchestrator/tasks/{taskId}/logs: parameters: - $ref: '#/components/parameters/taskId' get: tags: [Orchestrator] summary: Get task execution logs operationId: getTaskLogs responses: '200': description: Task logs content: application/json: schema: $ref: '#/components/schemas/OrchestratorLogsResponse' '404': $ref: '#/components/responses/NotFound' /orchestrator/tasks/{taskId}/artifacts: parameters: - $ref: '#/components/parameters/taskId' get: tags: [Orchestrator] summary: Get task artifacts operationId: getTaskArtifacts responses: '200': description: Task artifacts content: application/json: schema: $ref: '#/components/schemas/ArtifactsResponse' '404': $ref: '#/components/responses/NotFound' # ============ COMPONENTS ============ components: parameters: boardId: name: boardId in: path required: true description: Board ID schema: type: string format: uuid columnId: name: columnId in: path required: true description: Column ID schema: type: string format: uuid taskId: name: taskId in: path required: true description: Task ID schema: type: string format: uuid instanceId: name: instanceId in: path required: true description: Agent instance ID schema: type: string format: uuid typeId: name: typeId in: path required: true description: Agent type ID schema: type: string responses: BadRequest: description: Bad request content: application/json: schema: $ref: '#/components/schemas/Error' NotFound: description: Resource not found content: application/json: schema: $ref: '#/components/schemas/Error' InternalError: description: Internal server error content: application/json: schema: $ref: '#/components/schemas/Error' schemas: # ============ COMMON ============ Error: type: object properties: error: type: string description: Error code message: type: string description: Human readable message details: type: string description: Additional details http_status: type: integer description: HTTP status code required: [error, message, http_status] HealthResponse: type: object properties: status: type: string example: ok required: [status] # ============ BOARDS ============ Board: type: object properties: id: type: string format: uuid name: type: string description: type: string created_at: type: string format: date-time updated_at: type: string format: date-time required: [id, name, created_at, updated_at] CreateBoardRequest: type: object properties: name: type: string minLength: 1 description: type: string required: [name] UpdateBoardRequest: type: object properties: name: type: string description: type: string BoardsListResponse: type: object properties: boards: type: array items: $ref: '#/components/schemas/Board' total: type: integer required: [boards, total] # ============ COLUMNS ============ Column: type: object properties: id: type: string format: uuid board_id: type: string format: uuid name: type: string position: type: integer state: type: string enum: [TODO, IN_PROGRESS, DONE] created_at: type: string format: date-time required: [id, board_id, name, position, created_at] CreateColumnRequest: type: object properties: name: type: string minLength: 1 position: type: integer default: 0 state: type: string enum: [TODO, IN_PROGRESS, DONE] required: [name] ColumnsListResponse: type: object properties: columns: type: array items: $ref: '#/components/schemas/Column' total: type: integer required: [columns, total] # ============ TASKS ============ Task: type: object properties: id: type: string format: uuid board_id: type: string format: uuid column_id: type: string format: uuid title: type: string description: type: string state: type: string enum: [TODO, IN_PROGRESS, BLOCKED, COMPLETED, FAILED, CANCELLED] priority: type: integer agent_type: type: string position: type: integer created_at: type: string format: date-time updated_at: type: string format: date-time metadata: type: object additionalProperties: true description: Includes auggie_session_id after agent execution required: [id, board_id, column_id, title, state, created_at, updated_at] CreateTaskRequest: type: object properties: board_id: type: string format: uuid column_id: type: string format: uuid title: type: string minLength: 1 description: type: string priority: type: integer default: 0 agent_type: type: string metadata: type: object additionalProperties: true required: [board_id, column_id, title] UpdateTaskRequest: type: object properties: title: type: string description: type: string priority: type: integer agent_type: type: string metadata: type: object additionalProperties: true UpdateTaskStateRequest: type: object properties: state: type: string enum: [TODO, IN_PROGRESS, BLOCKED, COMPLETED, FAILED, CANCELLED] required: [state] MoveTaskRequest: type: object properties: column_id: type: string format: uuid position: type: integer required: [column_id] TasksListResponse: type: object properties: tasks: type: array items: $ref: '#/components/schemas/Task' total: type: integer required: [tasks, total] # ============ AGENTS ============ AgentInstance: type: object properties: id: type: string format: uuid task_id: type: string format: uuid agent_type: type: string container_id: type: string status: type: string enum: [starting, running, completed, failed, stopped] progress: type: integer minimum: 0 maximum: 100 started_at: type: string format: date-time finished_at: type: string format: date-time nullable: true exit_code: type: integer nullable: true error_message: type: string metadata: type: object additionalProperties: true required: [id, task_id, agent_type, status, progress, started_at] LaunchAgentRequest: type: object properties: task_id: type: string format: uuid agent_type: type: string example: augment-agent workspace_path: type: string description: Absolute path to the project directory env: type: object additionalProperties: type: string description: Environment variables (AUGMENT_SESSION_AUTH, TASK_DESCRIPTION, etc.) priority: type: integer default: 0 metadata: type: object additionalProperties: true required: [task_id, agent_type, workspace_path] StopAgentRequest: type: object properties: force: type: boolean default: false reason: type: string SendPromptRequest: type: object properties: message: type: string description: The prompt message to send to the agent required: [message] SendPromptResponse: type: object properties: success: type: boolean message: type: string required: [success] CancelAgentRequest: type: object properties: reason: type: string description: Reason for cancellation CancelAgentResponse: type: object properties: success: type: boolean message: type: string required: [success] GetSessionResponse: type: object properties: instance_id: type: string task_id: type: string session_id: type: string status: type: string enum: [initializing, ready, running, completed, failed] created_at: type: string format: date-time required: [instance_id, status, created_at] AgentsListResponse: type: object properties: agents: type: array items: $ref: '#/components/schemas/AgentInstance' total: type: integer required: [agents, total] AgentType: type: object properties: id: type: string name: type: string description: type: string image: type: string capabilities: type: array items: type: string enabled: type: boolean required: [id, name, image, enabled] AgentTypesListResponse: type: object properties: types: type: array items: $ref: '#/components/schemas/AgentType' total: type: integer required: [types, total] LogsResponse: type: object properties: logs: type: array items: type: object properties: timestamp: type: string format: date-time message: type: string stream: type: string enum: [stdout, stderr] total: type: integer required: [logs, total] # ============ ORCHESTRATOR ============ OrchestratorStatus: type: object properties: running: type: boolean queue_size: type: integer active_tasks: type: integer QueueResponse: type: object properties: tasks: type: array items: $ref: '#/components/schemas/QueuedTask' total: type: integer required: [tasks, total] QueuedTask: type: object properties: task_id: type: string format: uuid priority: type: integer queued_at: type: string format: date-time estimated_start: type: string format: date-time nullable: true required: [task_id, priority, queued_at] TriggerTaskRequest: type: object properties: task_id: type: string format: uuid force: type: boolean default: false required: [task_id] StartTaskRequest: type: object properties: agent_type: type: string priority: type: integer default: 0 StopTaskRequest: type: object properties: reason: type: string force: type: boolean default: false TaskStatusResponse: type: object properties: task_id: type: string format: uuid state: type: string agent_instance_id: type: string format: uuid agent_type: type: string started_at: type: string format: date-time nullable: true progress: type: integer current_operation: type: string estimated_completion: type: string format: date-time nullable: true required: [task_id, state, progress] OrchestratorLogsResponse: type: object properties: logs: type: array items: type: object properties: timestamp: type: string format: date-time level: type: string enum: [debug, info, warn, error] message: type: string metadata: type: object additionalProperties: true total: type: integer required: [logs, total] ArtifactsResponse: type: object properties: artifacts: type: array items: $ref: '#/components/schemas/Artifact' Artifact: type: object properties: id: type: string name: type: string type: type: string enum: [report, code, log] size: type: integer format: int64 created_at: type: string format: date-time download_url: type: string required: [id, name, type, size, created_at]