docs: delete internal add-agent-cli guide describing removed protocols (#3010)

Co-authored-by: nova28 <17953305+nova28@users.noreply.github.com>
This commit is contained in:
Henry
2026-08-25 07:14:30 +00:00
committed by GitHub
parent cc169a7ff9
commit c8aa40b8d7
2 changed files with 1 additions and 244 deletions
+1 -1
View File
@@ -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)* | | **Grok** | `grok` *(install `@xai-official/grok` with npm)* |
| **Hermes** | `hermes` *(install with the official Hermes installer)* | | **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, Kandev does not pin the managed npm runtimes for Claude, Codex, OpenCode,
Copilot, or Gemini. Normal launches can reuse npm's best-effort execution Copilot, or Gemini. Normal launches can reuse npm's best-effort execution
-243
View File
@@ -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) |