Skip to content

Agents

agents-wire supports twelve local coding agents, all speaking ACP (Agent Client Protocol). The API surface is identical across all agents - the differences are in how you install and authenticate each one.

Overview

AgentIDProtocol modeNative session listingMCP http/sseMCP stdio
Claude Codeclaudebridge
Codex CLIcodexbridge
Cursorcursornative
GitHub Copilotcopilotbridge
Gemini CLIgeminibridge
OpenCodeopencodenative
Factory Droiddroidnative
Pipinative (non-ACP)
Clineclinenative
Kilokilonative
Qwen Codeqwennative
Augment Codeauggienative

Protocol mode:

  • bridge - the SDK includes or expects a peer-installed ACP bridge package that wraps the underlying CLI.
  • native - the agent speaks ACP directly.

MCP http/sse: whether the agent accepts HTTP or SSE MCP server configurations (checked via CapabilityNotSupportedError).

Model Selection by Agent

options.model and options.effort behave differently across agents. The table below documents what actually happens today so you can set expectations correctly.

AgentWhat options.model doesWhat options.effort doesModel sourceHow to verify
claudesent via ACP setSessionConfigOption (best-effort)sent via ACP setSessionConfigOption({ configId: "reasoning_effort" }) (Claude uses token-budget thinking; likely ignored)session-configcheck session.configOptions for the exact knobs Claude advertises
codexbecomes -c model="X" CLI arg (works)becomes -c model_reasoning_effort="X" (works; kind: enum, values: low / medium / high)session-configverified via codex-acp --help
cursorsent via ACP modelPreference (silently ignored by current cursor-agent acp)baked into model id (kind: variant, e.g. -low, -high, -xhigh suffix)live-listuse agent --list-models for the live list; configure default via the Cursor app
copilotsent via ACP modelPreference (best-effort)sent via ACP setSessionConfigOption (best-effort)session-config--
geminisent via ACP modelPreference (best-effort; gemini --acp does not take CLI flags)sent via ACP setSessionConfigOption (best-effort)session-config--
opencodesent via ACP modelPreference (silently ignored by current opencode acp)sent via ACP setSessionConfigOption (best-effort)live-listuse opencode models for the live list
droidnot honored (auto-selects)not honored (auto)static--
pinot honored (non-ACP; v0.73 incompatible)not honoredstatic--
clinesent via ACP setSessionConfigOption (best-effort; BYOK provider-dependent)sent via ACP setSessionConfigOption (best-effort)session-configcheck session.configOptions after init
kilosent via ACP setSessionConfigOption (best-effort)model-dependent (kind varies per upstream model)live-listuse kilo models for the live list
qwensent via ACP setSessionConfigOption (best-effort; BYOK provider-dependent)sent via ACP setSessionConfigOption (best-effort)session-configcheck session.configOptions after init
auggiesent via ACP setSessionConfigOption (best-effort; subscription required)sent via ACP setSessionConfigOption (best-effort)live-listuse auggie model list (login required)

When the agent silently ignores model, your call still succeeds - the agent just uses its configured default. To know what each agent actually accepts at runtime, read session.configOptions after creating a session. See session.configOptions for details and a code example.

Live model list (cursor and opencode)

For agents that expose a live model list command, IAgentDefinition.listAvailableModels() wraps the call and returns [] on any failure (binary missing, timeout, parse fail). Use it lazily in pickers and fall back to def.models (the static catalog) if it returns empty.

ts
import { definitionFor } from "@pivanov/agents-wire/catalog";
import { createSession } from "@pivanov/agents-wire";

// Live model list (cursor / opencode only - silently falls back to static)
const def = definitionFor("cursor");
const models = (await def.listAvailableModels?.()) ?? def.models ?? [];

// Agent-declared config options on an active session
const session = await createSession("claude");
const opts = session.configOptions ?? [];
const modelOpt = opts.find(
  (o) => o.configId === "model" && o.type === "select",
);
// modelOpt.options is the exact list the agent accepts

Detect What's Available

bash
bunx @pivanov/agents-wire detect
bash
npx @pivanov/agents-wire detect
bash
pnpm dlx @pivanov/agents-wire detect
bash
yarn dlx @pivanov/agents-wire detect
ts
import { detectAvailableAgents } from "@pivanov/agents-wire";

const available = await detectAvailableAgents();
console.log(available.map((e) => e.agent));
// ["claude", "cursor", "opencode"]

Install Table

AgentInstall commandAuth
ClaudeClaude Code setupclaude /login
CodexOpenAI Codex CLI on PATHSet OPENAI_API_KEY
CursorCursor Agent CLISign in to Cursor app
Copilotnpm i -g @github/copilotgh auth login
Gemininpm i -g @google/gemini-cligemini auth login
OpenCodenpm i -g opencode-aiProvider API keys
Droidnpm i -g droidSet FACTORY_API_KEY
Pinpm i -g @mariozechner/pi-coding-agentSet PI_API_KEY
Clinenpm i -g clinecline auth or provider keys
Kilonpm i -g @kilocode/clikilo auth login --provider <id> or set KILO_API_KEY
Qwennpm i -g @qwen-code/qwen-codeqwen auth qwen-oauth or set BAILIAN_CODING_PLAN_API_KEY
Auggienpm i -g @augmentcode/auggieauggie login (subscription required)

Pricing and Cost Tracking

Agents fall into two categories:

Token-priced (Claude, Codex, Gemini, OpenCode, Droid): report costUsd per turn. The SDK's cost tracker accumulates these and enforces maxCostUsd.

Provider-dependent (Cline, Kilo, Qwen): cost reporting depends on the configured provider. Token-priced providers report costUsd; subscription / free-tier providers do not. Check result.cost after each turn to see what is available.

Subscription-priced (Cursor, Copilot, Pi, Auggie): do not report per-turn cost. The SDK tracks turn counts instead. cost.snapshot.totalUsd stays at 0 for these agents; maxCostUsd will not trigger. Use cost.turnCount to count usage.

Catalog API

ts
import {
  definitionFor,
  listDefinitions,
  registerDefinition,
} from "@pivanov/agents-wire/catalog";

// Get the definition for one agent
const def = definitionFor("claude");
console.log(def.id, def.displayName, def.capabilities);

// List all built-in agents
const all = listDefinitions();

// Register a custom agent
registerDefinition({
  id: "my-agent",
  displayName: "My Agent",
  launchSpec: { command: "my-agent", args: ["acp"] },
  capabilities: { mcpCapabilities: { supportedTransports: ["stdio"] } },
});