kiro-acp-ai-provider
v2.1.2
Published
Kiro ACP (AWS) provider for Vercel AI SDK
Downloads
1,989
Maintainers
Readme
kiro-acp-ai-provider
Kiro provider for the Vercel AI SDK that uses kiro-cli via the Agent Client Protocol (ACP). Implements LanguageModelV3 with streaming and tool calling.
Install
npm install kiro-acp-ai-provider @ai-sdk/providerNote: Your application also needs the
aipackage (Vercel AI SDK). Install it separately if you haven't already:npm install ai
Prerequisites
- Node.js 18+ or Bun
- kiro-cli installed and authenticated:
kiro-cli login - Kiro subscription (Pro, Pro+, Pro Max, or Power)
Quick Start
import { createKiroAcp } from "kiro-acp-ai-provider"
import { streamText } from "ai"
const kiro = createKiroAcp({ cwd: process.cwd() })
const result = streamText({
model: kiro("claude-sonnet-4.6"),
prompt: "Write a hello world function in TypeScript",
})
for await (const text of result.textStream) {
process.stdout.write(text)
}
await kiro.shutdown()How it works
Your App → AI SDK → kiro-acp-ai-provider → kiro-cli (ACP) → AWS Models
↕ IPC (HTTP)
MCP Bridge (per-session)The provider translates AI SDK calls into ACP messages sent to a kiro-cli subprocess over JSON-RPC stdio. Tool calls are relayed through an MCP bridge back to your application via IPC. The bridge does not execute tools, your application does.
Configuration
const kiro = createKiroAcp({
cwd: "/path/to/project", // Working directory (default: process.cwd())
model: "claude-sonnet-4.6", // Default model ID
agent: "my-agent", // Custom agent name (--agent flag)
trustAllTools: true, // Auto-approve all tool calls
agentPrompt: "You are a ...", // Custom system prompt
contextWindow: 200_000, // Max context window in tokens (default: 1_000_000)
mcpTimeout: 30, // MCP tool call timeout in minutes (default: 30)
sessionId: "previous-id", // Resume an existing session
env: { MY_VAR: "value" }, // Extra env vars for kiro-cli
clientInfo: { name: "my-app", version: "1.0.0" },
onPermission: (request) => ({ // Custom permission handler
outcome: { outcome: "selected", optionId: "allow_once" },
}),
})Session Management
Subagent Process Isolation
When the provider receives an x-parent-session-id header (indicating a subagent/child session), it spawns a separate kiro-cli process for that session. This prevents tool definitions from leaking between parent and child sessions. Isolated processes are auto-cleaned after 3 minutes idle.
Session Reset (Revert / Fork)
The x-session-reset: true header clears the persisted session and creates a fresh kiro session. The full conversation history is replayed as <context> text in a single message, since ACP doesn't support native fork/truncate. This enables revert-to-message and fork operations in consumers like opencode.
MCP Timeout
On startup, the provider sets mcp.noInteractiveTimeout to 30 minutes via kiro-cli settings. The default 5 minutes is too short for long-running tool calls (e.g., subagents that run for 8+ minutes).
Provider Methods
const model = kiro("claude-sonnet-4.6") // Create a LanguageModelV3
const model = kiro.languageModel("claude-sonnet-4.6") // Same thing
await kiro.shutdown() // Stop kiro-cli process
kiro.getClient() // Get underlying ACPClient
kiro.getSessionId() // Get session ID for persistence
await kiro.injectContext(summary) // Rehydrate session context
kiro.getTotalCredits() // Total credits consumedUtilities
Standalone functions that don't require a running provider:
import { verifyAuth, listModels, getQuota, reasoningEffortsFor } from "kiro-acp-ai-provider"
// Check if kiro-cli is installed and authenticated
const status = verifyAuth()
// { installed: true, authenticated: true, version: "1.2.3", tokenPath: "..." }
// List available models (starts/stops kiro-cli temporarily)
const models = await listModels({ cwd: process.cwd() })
// Get per-session credit usage
const quota = await getQuota({ client: kiro.getClient() })
// Native reasoning effort levels for a model, low to high ([] when unsupported)
const levels = reasoningEffortsFor("claude-opus-4.8")
// ["low", "medium", "high", "xhigh", "max"]verifyAuth() determines authentication solely from kiro-cli whoami, which abstracts the per-OS credential store. The on-disk SSO token file and its expiry are not consulted for the auth decision, so a stale token file never misreports a logged-in user. The returned tokenPath is provided only as an optional refresh hint for consumers.
Models
Available models depend on your subscription:
| Model ID | Description |
|----------|-------------|
| claude-opus-4.8 | Most capable |
| claude-sonnet-4.6 | Balanced |
| claude-haiku-4.5 | Fastest |
Use listModels() for the current list.
Reasoning effort
Reasoning effort is a supported per-turn option. Set it per request through providerOptions, keyed by the provider id kiro:
const result = streamText({
model: kiro("claude-opus-4.8"),
prompt: "Explain the tradeoffs",
providerOptions: { kiro: { reasoningEffort: "high" } },
})The same option works on generateText. You can also set a default at the provider level with createKiroAcp({ effort: "high" }) or per model with kiro("claude-opus-4.8", { effort: "high" }); a per-request providerOptions.kiro.reasoningEffort wins over both.
Levels are per model, and not every model has them:
| Model | Levels |
|-------|--------|
| claude-opus-4.8, claude-opus-4.7 | low, medium, high, xhigh, max |
| claude-opus-4.6, claude-sonnet-4.6 | low, medium, high, max (no xhigh) |
| everything else | none |
reasoningEffortsFor(modelId) returns a model's levels low to high (or [] when it has no effort control); defaultEffortFor(modelId) returns its native default (e.g. claude-opus-4.8 is high).
- Resets to the default: when a turn requests no effort, the SDK reapplies the model's native default instead of leaving the session stuck at the last value.
- Graceful no-op: an unsupported model or level is ignored. It never throws and never changes the result.
- No off switch: the lowest level still produces a reasoning trail; reasoning cannot be disabled.
Tools
Tools work through the standard AI SDK contract. The provider includes an MCP bridge that reads tool definitions from a JSON file and relays calls to your application via IPC. Pass custom tools through the AI SDK as usual; the provider handles the MCP bridge plumbing.
Image Support
The provider supports images in two paths:
User-attached images
Images pasted in chat are sent as ContentBlock[] with the prompt via ACP's session/prompt. This is the native path: kiro-cli handles image optimization and the model sees them directly.
Tool-returned images
When a tool (e.g., a file read tool) returns an image, the provider uses a follow-up prompt approach:
- The tool result is sent via IPC as text-only (so the MCP bridge flow completes)
- The first model response is aborted
- A follow-up
session/promptis sent with the images asContentBlock[], including the original user request for context
This is necessary because kiro-cli's MCP tool result path doesn't reliably handle large images; sending them through the user-message path (session/prompt) ensures proper image processing.
Note: The follow-up approach adds a small latency overhead (~1-2s) for tool results that contain images. Text-only tool results are unaffected.
Known Limitations
- System prompt: Kiro's base context is always present; yours is injected via
<system_instructions>tags - Limited per-turn options: Temperature and similar sampling parameters are controlled by kiro-cli. Reasoning effort is the exception (see Reasoning effort)
- Estimated token counts: Input tokens estimated from context usage %, output from character count
- Process model: One kiro-cli per provider instance (subagent sessions get their own isolated process); concurrent sessions use lane routing
- Revert-to-message: Requires the consumer to signal session reset via
x-session-resetheader as Kiro ACP doesn't support Checkpointing. - No ACP session/fork: Kiro ACP doesn't support native fork/truncate, so reverts replay the conversation history as context text
- Reasoning: Kiro always streams reasoning and it cannot be disabled. Effort is configurable per model (see Reasoning effort)
- Tool-returned images: Uses a follow-up prompt approach which adds ~1-2s latency and an extra synthetic message in kiro-cli's session history
Errors
When kiro-cli returns a JSON-RPC -32603 internal error and kiro-cli whoami reports you are logged out, the provider raises an actionable error asking you to re-authenticate with kiro-cli login (run kiro-cli doctor to help diagnose). Recent kiro-cli stderr is appended to the message to aid diagnosis.
License
MIT © Nacho F. Lizaur
