From c8aa40b8d7a3d2fa06429212defb1bc0d9065085 Mon Sep 17 00:00:00 2001 From: Henry Date: Tue, 25 Aug 2026 07:14:30 +0000 Subject: [PATCH] docs: delete internal add-agent-cli guide describing removed protocols (#3010) Co-authored-by: nova28 <17953305+nova28@users.noreply.github.com> --- README.md | 2 +- docs/add-agent-cli.md | 243 ------------------------------------------ 2 files changed, 1 insertion(+), 244 deletions(-) delete mode 100644 docs/add-agent-cli.md diff --git a/README.md b/README.md index 43cf5edabf..6a5ade5c9a 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,7 @@ Connect Kandev to the tools your team already uses — pull issues into the kanb | **Grok** | `grok` *(install `@xai-official/grok` with npm)* | | **Hermes** | `hermes` *(install with the official Hermes installer)* | -> All agents communicate via [ACP](https://agentclientprotocol.com) (Agent Client Protocol). Some agents support ACP natively, while others use ACP adapter packages that bridge their native protocols. **CLI Passthrough mode** is available when an integration provides a passthrough command. If your agent isn't supported yet, open an issue or submit a PR with the integration. See [Adding a New Agent CLI](docs/add-agent-cli.md) for a step-by-step guide. +> All agents communicate via [ACP](https://agentclientprotocol.com) (Agent Client Protocol). Some agents support ACP natively, while others use ACP adapter packages that bridge their native protocols. **CLI Passthrough mode** is available when an integration provides a passthrough command. If your agent isn't supported yet, open an issue or submit a PR with the integration. See [Adding a New Agent CLI](docs/public/add-agent-cli.md) for a step-by-step guide. Kandev does not pin the managed npm runtimes for Claude, Codex, OpenCode, Copilot, or Gemini. Normal launches can reuse npm's best-effort execution diff --git a/docs/add-agent-cli.md b/docs/add-agent-cli.md deleted file mode 100644 index b0b345abf1..0000000000 --- a/docs/add-agent-cli.md +++ /dev/null @@ -1,243 +0,0 @@ -# Adding a New Agent CLI Integration - -This guide explains how to add support for a new coding agent CLI to Kandev. - -Agents are defined entirely in Go. The backend discovers them through a registry, and the frontend picks them up automatically via the API - **no frontend changes are needed**. - -For a clean reference implementation, see [`gemini.go`](../apps/backend/internal/agent/agents/gemini.go) (ACP protocol). For a CLI-only TUI agent, see the `TUIAgent` declarative type in [`tui_agent.go`](../apps/backend/internal/agent/agents/tui_agent.go). - ---- - -## CLI-Only Agent (Passthrough Only) - Recommended for TUI tools - -If an agent has a CLI but no structured protocol (no JSON-RPC, no streaming API), use the **`TUIAgent` declarative type**. The agent runs in a terminal session and input/output passes through a WebSocket - users interact with the full agent TUI directly. - -This is the simplest path. A complete agent definition is ~20 lines. - -### Step 1: Create the agent file - -Create `apps/backend/internal/agent/agents/{agent_id}.go`: - -```go -package agents - -func NewClaude() *TUIAgent { - return NewTUIAgent(TUIAgentConfig{ - AgentID: "claude", - AgentName: "Claude", - Command: "claude", - Desc: "Claude Code - an agentic coding tool by Anthropic.", - - // Optional: let users select a model in profile settings. - // The {model} placeholder is replaced with the user's chosen model at launch. - // Omit this if the CLI doesn't accept a model flag. - ModelFlag: NewParam("--model", "{model}"), - }) -} -``` - -Logos are optional - the UI shows a blank placeholder when none is provided. To add them, embed SVGs and pass `LogoLight` / `LogoDark`: - -```go -package agents - -import _ "embed" - -//go:embed logos/claude_light.svg -var claudeLogoLight []byte - -//go:embed logos/claude_dark.svg -var claudeLogoDark []byte - -func NewClaude() *TUIAgent { - return NewTUIAgent(TUIAgentConfig{ - AgentID: "claude", - AgentName: "Claude", - Command: "claude", - Desc: "Claude Code - an agentic coding tool by Anthropic.", - ModelFlag: NewParam("--model", "{model}"), - LogoLight: claudeLogoLight, - LogoDark: claudeLogoDark, - }) -} -``` - -`TUIAgentConfig` fields (all optional fields have sensible defaults): - -| Field | Required | Description | -|-------|----------|-------------| -| `AgentID` | Yes | Unique lowercase identifier (e.g. `"claude"`) | -| `AgentName` | Yes | Display name (e.g. `"Claude"`) | -| `Command` | Yes | Binary name to run (e.g. `"claude"`) | -| `Desc` | Yes | Description shown in the UI | -| `ModelFlag` | No | Model CLI flag, e.g. `NewParam("--model", "{model}")`. Lets users pick a model in profile settings. Omit if the CLI doesn't support model selection. | -| `CommandArgs` | No | Extra args appended after `Command` (e.g. `[]string{"--debug"}`) | -| `WaitForTerm` | No | When `true`, delays process start until the terminal WebSocket connects and sends its first resize event. Use this for TUI apps that need accurate terminal dimensions on startup (e.g. ncurses-based UIs). Most agents don't need this. Defaults to `false`. | -| `LogoLight` / `LogoDark` | No | Embedded SVG bytes for light/dark themes. The UI shows a blank placeholder if omitted. | -| `DetectOpts` | No | Custom detection options. Defaults to `WithCommand(Command)` which checks if the binary is in `$PATH`. | - -### Step 2: Register the agent - -Add your agent to `LoadDefaults()` in [`apps/backend/internal/agent/registry/registry.go`](../apps/backend/internal/agent/registry/registry.go): - -```go -func (r *Registry) LoadDefaults() { - all := []agents.Agent{ - // ... existing agents ... - agents.NewMyAgent(), // add here - } - // ... -} -``` - -### Step 3: Build and test - -```bash -make -C apps/backend build && make -C apps/backend test && make -C apps/backend lint -``` - -Note: passthrough-only agents provide terminal interaction only. There are no structured chat messages, tool call visibility, or progress tracking in the chat UI. - ---- - -## Adding a New Agent (Full Integration) - -For agents with a structured protocol (JSON-RPC, streaming JSON, etc.), implement the full [`Agent`](../apps/backend/internal/agent/agents/agent.go) interface. - -### Step 1: Create the agent definition file - -Create `apps/backend/internal/agent/agents/{agent_id}.go`. - -This file implements the [`Agent`](../apps/backend/internal/agent/agents/agent.go) interface. See the interface definition in `agent.go` for the full contract. - -Embed `StandardPassthrough` to get CLI passthrough support for free: - -```go -type MyAgent struct { - StandardPassthrough -} - -func NewMyAgent() *MyAgent { - return &MyAgent{ - StandardPassthrough: StandardPassthrough{ - PermSettings: myAgentPermSettings, - Cfg: PassthroughConfig{ - Supported: true, - Label: "CLI Passthrough", - Description: "Show terminal directly instead of chat interface", - PassthroughCmd: NewCommand("myagent"), - ModelFlag: NewParam("--model", "{model}"), - PromptFlag: NewParam("--prompt", "{prompt}"), - IdleTimeout: 3 * time.Second, - BufferMaxBytes: DefaultBufferMaxBytes, - }, - }, - } -} -``` - -Key implementation notes: - -- **`BuildCommand()`** returns the CLI command for structured protocol mode (the agent communicates via stdin/stdout with a protocol adapter). Include the protocol flag here (e.g. `--acp`, `--stream-json`). -- **`Runtime()`** returns configuration used when running the agent in Docker or as a standalone process. Set `Protocol` to tell the adapter factory which transport to use. -- **`IsInstalled()`** uses the `Detect()` helper with `WithFileExists()` to check for known installation paths. Set `SupportsMCP` and `MCPConfigPaths` on the result. -- **MCP servers in passthrough** — set `MCPStrategy` on `PassthroughConfig` so the agent receives kandev's own tools server (plus any profile-configured MCP servers) when run in passthrough mode. Omitting it means **no MCP servers are injected in passthrough**. Pick the strategy that matches how your CLI loads MCP servers: `mcpconfig.ClaudeStrategy{}` (temp JSON file + `--mcp-config` flag), `mcpconfig.CodexStrategy{}` (repeated `-c mcp_servers.…` overrides), `mcpconfig.CursorStrategy{}` (project-local `.cursor/mcp.json`), `mcpconfig.PiStrategy{}` (project-local `.pi/mcp.json`), or `mcpconfig.OpenCodeStrategy{}` (temp JSON + `OPENCODE_CONFIG` env var). To add a strategy for a CLI with a different mechanism, implement `mcpconfig.PassthroughMCPStrategy`. See ADR 0014, ADR 0020, and `internal/agent/mcpconfig/passthrough.go`. -- **MCP project files in protocol mode** — set `RuntimeConfig.ProjectMCPStrategy` only when the structured protocol adapter does not pass ACP `session/new` MCP servers through to the underlying CLI. Pi uses this to write `.pi/mcp.json` before the subprocess starts. -- **`ListModels()`** can return a static list or dynamically query the CLI. Use `execAndParse()` from `helpers.go` for dynamic model discovery. -- Use `Cmd()` builder for constructing commands fluently: `Cmd("myagent", "--flag").Model(...).Settings(...).Build()`. - -### Step 2: Add logos (optional) - -Logos are optional - the UI shows a blank placeholder when none is provided. To add them, place SVGs in: - -``` -apps/backend/internal/agent/agents/logos/{agent_id}_light.svg -apps/backend/internal/agent/agents/logos/{agent_id}_dark.svg -``` - -Embed them in your agent file: - -```go -//go:embed logos/myagent_light.svg -var myagentLogoLight []byte - -//go:embed logos/myagent_dark.svg -var myagentLogoDark []byte -``` - -### Step 3: Register the agent - -Add your agent to `LoadDefaults()` in [`apps/backend/internal/agent/registry/registry.go`](../apps/backend/internal/agent/registry/registry.go): - -```go -func (r *Registry) LoadDefaults() { - all := []agents.Agent{ - // ... existing agents ... - agents.NewMyAgent(), // add here - } - // ... -} -``` - -That's it for registration. The frontend discovers agents through the API automatically. - -### Step 4: Choose a protocol - -Check [`apps/backend/pkg/agent/protocol.go`](../apps/backend/pkg/agent/protocol.go) for available protocols: - -| Protocol | Constant | Transport | Used By | -|----------|----------|-----------|---------| -| ACP | `ProtocolACP` | JSON-RPC 2.0 over stdin/stdout | Gemini, Auggie | -| stream-json | `ProtocolClaudeCode` | Streaming JSON over stdin/stdout | Claude Code | -| Codex | `ProtocolCodex` | JSON-RPC variant over stdin/stdout | Codex | -| OpenCode | `ProtocolOpenCode` | REST/SSE over HTTP | OpenCode | -| Copilot | `ProtocolCopilot` | Go SDK (JSON-RPC internally) | GitHub Copilot | -| Amp | `ProtocolAmp` | Streaming JSON over stdin/stdout | Amp | - -**If an existing protocol fits your agent**, reuse it - set `Protocol` in `Runtime()`. The adapter factory in `factory.go` selects the right transport automatically based on this value. - -**If you need a new protocol**, you'll need to: - -1. Add a new `Protocol` constant in `apps/backend/pkg/agent/protocol.go` -2. Create a transport adapter in `apps/backend/internal/agentctl/server/adapter/transport/{protocol}/` -3. Add the case to the factory switch in [`apps/backend/internal/agentctl/server/adapter/factory.go`](../apps/backend/internal/agentctl/server/adapter/factory.go) - -### Step 5: Build and test - -```bash -make -C apps/backend build && make -C apps/backend test && make -C apps/backend lint -``` - -Start the dev server and verify: -- The agent appears in the agent selector in the UI -- Agent execution works (start a task, send a prompt) -- Passthrough mode works (toggle to CLI passthrough in the session) -- Model listing works - ---- - -## Updating an Existing Agent - -| Change | Where | -|--------|-------| -| Update CLI version | `BuildCommand()` and `Runtime().Cmd` in the agent file | -| Add/remove models | `ListModels()` - update static list or dynamic command | -| Update permissions | `PermissionSettings()` variable and `PassthroughConfig` | -| Update Docker image | `Runtime()` - change `Image`/`Tag` fields | -| Change protocol | `Runtime().Protocol` in the agent file | - ---- - -## File Reference - -| File | When to modify | -|------|---------------| -| `apps/backend/internal/agent/agents/{agent_id}.go` | Always - agent definition | -| `apps/backend/internal/agent/agents/logos/{agent_id}_{light,dark}.svg` | Optional - agent logos (UI shows blank placeholder if omitted) | -| `apps/backend/internal/agent/registry/registry.go` | Always - register in `LoadDefaults()` | -| `apps/backend/internal/agent/agents/tui_agent.go` | Never - provides `TUIAgent` declarative type (read-only reference) | -| `apps/backend/pkg/agent/protocol.go` | Only if adding a new protocol | -| `apps/backend/internal/agentctl/server/adapter/factory.go` | Only if adding a new protocol | -| `apps/backend/internal/agentctl/server/adapter/transport/{proto}/` | Only if adding a new protocol | -| `apps/backend/internal/agent/agents/passthrough.go` | Never - provides `StandardPassthrough` (read-only reference) | -| `apps/backend/internal/agent/agents/agent.go` | Never - defines the `Agent` interface (read-only reference) |