If you maintain an editor plugin, IDE extension, or other ACP client that starts kiro-cli acp, this guide covers what changes when you move from the CLI v2 ACP server to CLI V3: how to launch the new server, how capability negotiation works, and which v2 APIs have been replaced or removed.
| Area | CLI v2 | CLI V3 |
|---|---|---|
| Server launch | kiro-cli acp | Explicit V3 engine; authentication owned by the CLI or client |
| Agent, model, and effort | Launch flags | Session inputs and advertised configuration options |
| Optional methods | Fixed _kiro.dev/* catalog | Negotiate standard capabilities and agentCapabilities._meta.kiro.extensionMethods |
| Model selection | session/set_model | session/set_config_option with configId: "model" |
| Session discovery | Read ~/.kiro/sessions/cli/ | session/list and session/load |
| Live updates | Standard updates plus _kiro.dev/session/update | Standard session/update with additional update types and _meta.kiro |
| Slash commands | _kiro.dev/commands/execute | Client behavior, standard ACP methods, or a negotiated typed extension |
| Permissions | _meta.trustOptions requests and _meta.trustOption responses | Standard options[]; return _meta.kiro.consent for persistent choices |
| MCP state | Per-server _kiro.dev/mcp/* events | Full _kiro/mcp/status snapshots |
| Client settings | _kiro.dev/settings/list and set | Client-owned storage; send only agent-relevant settings |
Keep separate CLI v2 and CLI V3 adapters while you support both server generations. The ACP protocol version does not identify the server generation because both negotiate version 1.
Configure your client to start CLI V3 explicitly:
/full/path/to/kiro-cli acp --agent-engine=v3 --auth-method=cli
CLI V3 uses newline-delimited JSON-RPC 2.0 over standard input and standard output. Each JSON object occupies one line.
--auth-method=cli keeps access-token handling in the Kiro CLI process. If you omit it, your client must implement the agent-to-client _kiro/auth/getAccessToken request and protect token values from logs and diagnostics. Prefer CLI-owned authentication unless your client already owns Kiro authentication.
Remove these CLI v2-only launch flags from a v3 launch:
--agent--model--effort--trust-all-tools--trust-toolsCLI V3 rejects these flags on the acp command. Select the agent mode, model, and effort after initialization. Persist tool consent through the CLI V3 permission flow.
Call initialize, then use the returned capabilities to decide which UI and protocol behavior to enable. Do not infer support from a Kiro CLI version or a hard-coded method list.
CLI V3 can advertise these standard methods:
| Method | Purpose |
|---|---|
initialize | Negotiate the protocol, authentication, and capabilities |
authenticate | Use an advertised standard ACP authentication method |
session/new | Create a session |
session/list | Discover sessions through the server |
session/load | Restore a session and replay its state |
session/fork | Create a session from an earlier point |
session/prompt | Start a turn |
session/cancel | Cancel the active turn |
session/set_mode | Change the active mode |
session/set_config_option | Change an advertised option such as model or effort |
CLI V3 does not implement session/set_model. Change the model through the advertised model configuration option:
{ "jsonrpc": "2.0", "id": 7, "method": "session/set_config_option", "params": { "sessionId": "session-1", "configId": "model", "value": "claude-sonnet" } }
Use configId: "effortLevel" for effort. Change mode with session/set_mode or an advertised mode configuration option.
Read optional Kiro request methods from agentCapabilities._meta.kiro.extensionMethods. Also read advertised session sources, list scopes, execution targets, replay marking, and logging configuration when your client uses them.
The running server's advertisement is authoritative. Different deployments can return different arrays. Gate every optional request on the advertised method list, ignore unknown fields, and preserve unknown _meta data through relays and replay.
Register all required agent-to-client handlers before creating or loading a session:
session/update: required for all clients; register it before creating or loading a session because live updates are not buffered for future subscribers (replay delivers prior history, not missed live events)session/request_permission: required if the client presents tool approvals_kiro/auth/getAccessToken: required when the server was not started with --auth-method=cliCLI V3 accepts cwd, mcpServers, and standard top-level additionalDirectories on both session/new and session/load. Kiro-aware clients can also send initial values such as modeId, modelId, and effortLevel under _meta.kiro.
{ "jsonrpc": "2.0", "id": 8, "method": "session/new", "params": { "cwd": "/workspace/project", "additionalDirectories": ["/workspace/shared"], "mcpServers": [], "_meta": { "kiro": { "modeId": "vibe", "modelId": "claude-sonnet", "effortLevel": "high" } } } }
Read the returned modes and configuration options instead of hard-coding choices.
Client-supplied MCP server definitions are session inputs. CLI V3 does not persist those definitions in session.json, so send them again on session/load. Also send the current cwd and additional directories.
{ "jsonrpc": "2.0", "id": 9, "method": "session/load", "params": { "sessionId": "session-1", "cwd": "/workspace/project", "additionalDirectories": ["/workspace/shared"], "mcpServers": [] } }
Keep the requested session ID in client state. Do not depend on the load response repeating it.
Do not write Kiro session files directly or depend on the CLI V3 directory layout. Local and remote sessions do not share a client-readable filesystem model.
Use session/list to discover sessions and session/load to restore them. For file transfer or older history, use an advertised export or history method. Do not pass an archive path to session/load. A read-only CLI v2 file parser can remain in the v2 adapter while you support that generation.
CLI V3 emits updates with the existing snake-case discriminators and additional standard update types. The following values identify updates in the sessionUpdate field of a session/update notification.
| Update type | Client action |
|---|---|
user_message_chunk | Render echoed or replayed user content when supplied |
agent_message_chunk | Append streamed response content |
agent_thought_chunk | Render thought content according to the client's UX |
tool_call | Create or update a tool card by toolCallId |
tool_call_update | Apply progress, output, and terminal status to the same card |
available_commands_update | Replace the advertised command catalog |
current_mode_update | Update the active mode |
config_option_update | Replace the advertised configuration state |
session_info_update | Dispatch by _meta.kiro.kind: context_usage carries usagePercentage; turn_completion carries turn metering (promptTurnSummaries), elapsed time, and status; other kinds carry lifecycle state |
Match updates and permission requests to the original call using toolCallId, not the tool name. Route every notification by sessionId and process each session's updates in arrival order. Unknown update types and metadata fields must not fail the session.
When stable identity metadata is absent, render the standard kind and title. Never derive a built-in tool identity from a human-readable title, and never use displayed identity metadata to authorize an action.
Complete a pending session/prompt request only when it returns a response or error. Do not treat session_info_update with _meta.kiro.kind: "turn_end" as request completion. CLI V3 can emit it and continue working before the prompt returns, and it does not emit a TurnEnd update discriminator.
If the transport drops before the response arrives, reconnect and register the session/update handler before calling session/load. Replay updates arrive during loading, so registering afterward can miss them. Do not automatically resend the prompt. Even if replay shows that the prior turn completed, resending can repeat its changes, and loaded history cannot recover the lost response.
A replayed local update can carry _meta.kiro.replay: true in the update payload:
{ "jsonrpc": "2.0", "method": "session/update", "params": { "sessionId": "session-1", "update": { "sessionUpdate": "agent_message_chunk", "content": { "type": "text", "text": "Previously streamed response" }, "_meta": { "kiro": { "replay": true } } } } }
Remote replay is not guaranteed to mark every replayed update. Register the update handler before calling session/load because live updates are not retained for future subscribers. Rebuild state after reconnect or suspected delivery loss.
For local sessions, treat noReplay: true as transcript suppression, not as suppression of current-state updates. Remote loads also skip connecting the live update stream, so do not use noReplay for a remote session when your client needs subsequent updates.
session/request_permission remains an agent-to-client request. Treat the standard options[] list as authoritative and render only the choices supplied by the agent.
A CLI V3 request can add consent context under _meta.kiro.consent:
{ "method": "session/request_permission", "params": { "sessionId": "session-1", "toolCall": { "toolCallId": "call-1", "title": "Run tests", "status": "pending" }, "options": [ { "optionId": "accept", "name": "Allow", "kind": "allow_once" }, { "optionId": "always-accept", "name": "Always allow", "kind": "allow_always" }, { "optionId": "reject", "name": "Deny", "kind": "reject_once" }, { "optionId": "always-reject", "name": "Always deny", "kind": "reject_always" } ], "_meta": { "kiro": { "consent": { "capability": "shell", "resource": "npm run test", "triggeringResource": "npm run test", "workspaceRoot": "/workspace/project", "persistableConsent": true } } } } }
Never synthesize an option that the agent omitted. Return a one-time option immediately. For an offered persistent option, a Kiro-aware client can collect both a resource pattern and a persistence scope, then return the original optionId with canonical consent metadata:
{ "outcome": { "outcome": "selected", "optionId": "always-accept" }, "_meta": { "kiro": { "consent": { "scope": "workspace", "resource": "npm run *", "workspaceRoot": "/workspace/project" } } } }
CLI V3 validates the response, persists a valid rule, rebuilds policy, and re-evaluates the original invocation. A multi-resource operation can issue another permission request for the next uncovered resource.
| CLI v2 field | CLI V3 behavior |
|---|---|
Request _meta.trustOptions | Use the supplied standard options[] and _meta.kiro.consent |
Response _meta.trustOption | Return canonical _meta.kiro.consent for a persistent option |
Request _meta.fsReadPaths | CLI V3 evaluates every path before requesting permission |
Response _meta.feedback | Send text as conversational input, not permission metadata |
For text entered while a permission is pending, choose one explicit behavior:
session/cancel, wait for the original session/prompt response to resolve, then send a new session/prompt. Do not wait for a TurnEnd update discriminator.Keep a plain denial distinct from an interruption that carries a new instruction.
CLI V3 can include a versioned _meta.kiro.mcpTool envelope with host-resolved server and tool identity plus optional MCP behavior hints. Read version 1 when present, and fall back to CLI v2 flat mcpToolIdentity and mcpAnnotations fields only while supporting the legacy server.
{ "method": "session/request_permission", "params": { "sessionId": "session-1", "toolCall": { "toolCallId": "call-2", "title": "@example-server/search", "status": "pending" }, "options": [ { "optionId": "accept", "name": "Allow", "kind": "allow_once" }, { "optionId": "reject", "name": "Deny", "kind": "reject_once" } ], "_meta": { "kiro": { "mcpTool": { "version": 1, "identity": { "serverName": "example-server", "toolName": "search" }, "annotations": { "readOnlyHint": true, "openWorldHint": true } } } } } }
The annotations object is optional. The four supported hints are readOnlyHint, destructiveHint, idempotentHint, and openWorldHint. Preserve the difference between an omitted field and explicit false. Never use a hint alone to approve a call, suppress a prompt, lower risk, retry automatically, or bypass network policy.
Failed tool updates can include _meta.kiro.failureReason with cancelled, denied, or error. Use it when present, retain a legacy fallback when absent, and treat an unknown value as a generic failure.
CLI V3 removes the generic _kiro.dev/commands/execute and _kiro.dev/commands/options APIs. Do not replace them with a universal session/prompt transport. Use client-local behavior, standard ACP methods, advertised configuration, or a negotiated typed extension for each command.
| CLI v2 command | CLI V3 replacement |
|---|---|
/help | Build help from the client command registry |
/model | session/set_config_option with configId: "model" |
/agent | Change the advertised mode; keep profile editing client-local |
/context | Advertised _kiro/session/context |
/compact | Advertised _kiro/session/compact |
/clear | Create and adopt a new session |
/quit | Close the client locally |
/usage | Advertised _kiro/account/getUsage |
/paste | Read the client clipboard and send an ACP image block |
/mcp | Render _kiro/mcp/status; manage declarations outside the session panel |
/tools | Render _kiro/tools/didChange; persist consent through permissions |
/plan | Change to the planner mode, then send trailing text with session/prompt |
/feedback | Show client-owned choices and open the selected URL locally |
/chat | Compose session/list, session/new, and session/load |
/knowledge | Advertised _kiro/knowledge |
/prompts | Use available_commands_update and client-owned prompt sources |
/reply | Edit the last response locally, then call session/prompt |
/code | Advertised _kiro/codeIntelligence |
/voice | Capture and transcribe locally, then call session/prompt |
/hooks | Render the hook cache or call advertised _kiro/hooks/list |
/guide | Retired; remove it for CLI V3 |
/rewind | session/fork at the selected message, then load the fork |
/stats | Retired; remove it for CLI V3 |
/effort | session/set_config_option with configId: "effortLevel" |
/goal | Use advertised _kiro/workflow/* methods and lifecycle notifications |
Use available_commands_update for invocable commands, _kiro/tools/didChange for native tools, and _kiro/mcp/status for MCP inventory. Keep command discovery separate from invocation: display a command only when your client has a defined route for it.
The following table covers the remaining high-impact CLI v2 private APIs. Gate every CLI V3 extension on capability advertisement.
_session/steer intentionally keeps its existing _session/ method name in CLI V3. Do not rename it to _kiro/session/steer.
| CLI v2 API | CLI V3 migration |
|---|---|
_kiro.dev/session/update tool_call_chunk | Standard session/update with sessionUpdate: "tool_call" |
AgentExecutionUserMessageQueued | session_info_update with _meta.kiro.kind: "steering_queued" |
AgentExecutionSteeringInjected | session_info_update with _meta.kiro.kind: "steering_injected" |
AgentExecutionUserMessageCleared | session_info_update with _meta.kiro.kind: "steering_cleared" |
_kiro.dev/metadata | session_info_update by concern: context_usage for context-window usage and turn_completion for turn metering; config_option_update for configuration |
_kiro.dev/compaction/status | Summarization session_info_update kinds |
_kiro.dev/error/rate_limit | _kiro/error/rate_limit |
_message/send | session/prompt for an idle session; _session/steer during an active turn |
_session/spawn | session/new, optional _kiro/session/rename, then background session/prompt |
_kiro.dev/agent/switched | current_mode_update and config_option_update |
_kiro.dev/agent/not_found | _kiro/customAgent/not_found |
_kiro.dev/agent/config_error | _kiro/customAgent/config_error |
_kiro.dev/subagent/list_update | Render observable tool or subtask activity; no exact roster replacement |
_kiro.dev/goal/status | Advertised _kiro/workflow/* lifecycle notifications |
_kiro.dev/mcp/server_initialized | Connected entries in _kiro/mcp/status |
_kiro.dev/mcp/server_init_failure | Failed entries in _kiro/mcp/status |
_kiro.dev/mcp/oauth_request | Authentication-required state, explicit reset, and _kiro/openExternalUrl |
_kiro.dev/mcp/governance_disabled | _kiro/mcp/governance_disabled plus _kiro/governance/state |
_kiro.dev/webTools/governance_disabled | _kiro/governance/state |
_kiro.dev/settings/list | Read client-owned preferences and send typed agent settings when needed |
_kiro.dev/settings/set | Persist client-owned preferences locally |
_kiro.dev/clear/status | Treat a successful session/new as the acknowledgement |
_kiro.dev/telemetry/* | Remove from ACP; application telemetry is client-owned |
_kiro.dev/session/terminate | No current CLI V3 equivalent; use session/cancel only to stop an active turn |
The v2 retry_warning, stream_stall_notice, and stream_discarded updates are intentionally retired. Keep the turn active until an ordinary lifecycle or terminal signal arrives. Do not infer retry or stall state from latency, and do not retract streamed output heuristically.
Treat each _kiro/mcp/status notification as a full snapshot, not an event to append. Replace the prior snapshot by server name, render connected, failed, and disabled states, and avoid redisplaying an unchanged failure.
For a local CLI V3 session, an interactive OAuth flow uses three messages:
_kiro/mcp/status reports a failed server with failedAuthorization: true._kiro/mcp/resetServer with startOAuth: true after the user chooses to authenticate._kiro/openExternalUrl with the fresh authorization URL.Register _kiro/openExternalUrl before initialization and advertise clientCapabilities._meta.kiro.openExternalUrl: true. Open only the URL delivered by that request, use a visible user action, and never log or share the authorization URL.
resetServer starts forced reauthentication. It is not a standalone cancel or logout operation, and it does not guarantee revocation at the remote provider.
Verify the client against both adapters before removing CLI v2 support.
--agent-engine=v3 and the intended authentication owner.protocolVersion as the generation discriminator._meta siblings are ignored safely.session/new and session/load send all current client-owned inputs.session/list, not the filesystem.sessionId and every tool event by toolCallId.TurnEnd update.Use the full path to kiro-cli, confirm it is executable, and remove unsupported v3 launch flags. Check standard error for the exact CLI argument error.
Confirm the client writes one JSON-RPC object per line. If --auth-method=cli is absent, verify that the client answers _kiro/auth/getAccessToken. Any agent-to-client request with an id requires a response or an explicit JSON-RPC error.
Use only values from the current advertised configuration options. Do not reuse a value cached from another account, server generation, or deployment.
Send client-owned mcpServers definitions again on session/load. Do not assume the server persisted them with the session.
Settle the turn from the session/prompt response. Do not wait for a TurnEnd update discriminator. If a permission request is pending, the agent is waiting for the client's response.
Re-read the current initialize result. Call only methods listed in agentCapabilities._meta.kiro.extensionMethods and support deployments that advertise a smaller surface.
Migrate an ACP client to CLI V3