Install the adapter
Install claude-agent-acp globally or provide an equivalent launcher through command. AML does not download it at
runtime.
Built-in Agent provider
claudeAgent()Run Claude Code workflows from TypeScript through the Agent Client Protocol (ACP). AML launches the maintained claude-agent-acp adapter, which drives Claude Code through the official Claude Agent SDK, while AML owns evaluation, capability grants, structured results, cancellation, and cleanup.
claudeAgent() launches the command configured by command, defaulting to claude-agent-acp. That executable is the maintained Claude Agent ACP adapter (@agentclientprotocol/claude-agent-acp, Apache-2.0). The adapter is built on Anthropic’s official Claude Agent SDK, which ships a platform-specific Claude Code executable and runs Claude Code’s model loop and tools.
<Agent> AML normalizes model, system instructions, permissions, Tools, MCP, and output ↓ claude-agent-acp (or your configured command) ↓ Claude Agent SDK → bundled Claude Code executable ↓ Anthropic API, or the model provider selected through Claude Code's environmentClaude Code’s own CLI (claude -p) is not an ACP server, so AML launches the adapter instead of a one-shot CLI command. The session then follows the same shared ACP lifecycle as every other built-in Agent.
Every acquisition receives an invocation-private Claude configuration directory and home directory. AML never reads or copies the operator’s ~/.claude, and it removes the private directory when the session ends.
Install the adapter
Install claude-agent-acp globally or provide an equivalent launcher through command. AML does not download it at
runtime.
Provide credentials
Supply an Anthropic API key through apiKey, or a Claude Code OAuth token created with claude setup-token through
oauthToken. An interactive claude /login is not used.
Choose a runtime
Run on a trusted host or inside a Sandbox whose image contains Node.js 22+, the adapter with its platform-specific Claude Code executable, and network access to the model provider.
Install the repository baseline and verify the command from the environment where AML will launch it:
npm install --global @agentclientprotocol/claude-agent-acp@0.91.0claude-agent-acp --versionThe repository baseline is adapter 0.91.0 with Claude Agent SDK 0.3.300. This is a repeatable repository baseline, not a guarantee that every newer adapter is compatible. Re-run the live provider path when it changes.
The adapter requires Node.js 22 or newer; AML itself requires Node.js 26 on the application host. The adapter has no --help flag. Besides --version, it accepts --hide-claude-auth, which makes it refuse sessions and turns that a claude.ai subscription would pay for, and --cli, which passes through to the bundled claude executable. Add --hide-claude-auth through args when a deployment must bill only an API account.
For container execution, the Claude image variant includes this adapter baseline. The default full image includes it too. Local Sandbox still requires claude-agent-acp on the host.
This example uses the public SDK entrypoint and makes the Workspace/Sandbox boundary explicit. A real claude-agent-acp executable must be available in the selected environment. Local Sandbox requires read-write access to start any host process, including the adapter, so the Agent-level permissions only narrow Claude’s tool set. Use an enforcing Sandbox such as Docker when read-only access is a security requirement.
import { Agent, AmlRuntime, Sandbox, Workspace, claudeAgent, localSandbox, localWorkspace } from "@aml-jsx/sdk"
const apiKey = process.env.ANTHROPIC_API_KEYif (!apiKey) throw new Error("ANTHROPIC_API_KEY is required")
const provider = claudeAgent({ apiKey, model: "sonnet",})
const result = await new AmlRuntime({ agentProvider: provider,}).evaluate( <Workspace id="claude-review" provider={localWorkspace({ directory: "/absolute/path/to/repository" })} load={false} save={false} > <Sandbox provider={localSandbox()} access="read-write"> <Agent system="Return concise, evidence-based answers." permissions={{ filesystem: "read-only", shell: false, network: false }} > Summarize the repository structure and identify the highest-risk module. </Agent> </Sandbox> </Workspace>)
console.log(result)With those permissions, Claude Code starts without its Edit, Write, NotebookEdit, Bash, WebFetch, and WebSearch tools. Do not put credentials in a Workspace, prompt, or repository file.
| Option | Type | Default | Semantics |
|---|---|---|---|
apiKey | string | — | Writes ANTHROPIC_API_KEY, overriding env.ANTHROPIC_API_KEY. Cannot be combined with oauthToken. |
oauthToken | string | — | Writes CLAUDE_CODE_OAUTH_TOKEN; create one with claude setup-token. Cannot be combined with apiKey. |
command | string | "claude-agent-acp" | ACP adapter executable or application-owned launcher. |
args | readonly string[] | [] | Appended to the launch command exactly as supplied. Arguments cannot contain null bytes. |
env | Record<string, string> | {} | Additional launch environment. AML-owned variables are written after it. |
model | string | — | Provider-level model fallback written as ANTHROPIC_MODEL. |
reasoningEffort | string | — | Provider-native Claude Agent SDK effort value. |
workingDirectory | string | — | Fallback working directory when no Sandbox supplies the effective directory. |
command, apiKey, oauthToken, model, reasoningEffort, and workingDirectory must be non-empty, trimmed strings without null bytes; args entries may be empty but cannot contain null bytes. AML validates and snapshots the options when claudeAgent() is called, so later mutations to the original arrays or objects do not change the provider.
The effective values are resolved as follows:
<Agent model="..." /> overrides the factory model. AML writes the effective value as ANTHROPIC_MODEL; with neither set, Claude Code selects its default.session/new _meta.systemPrompt = { append }. It is a real system prompt, not a first-turn prelude. When AML JavaScript Tools are present, the appended text also lists their Claude Code names.reasoningEffort becomes the Claude Agent SDK effort option, sent as _meta.claudeCode.options.effort on session/new. Narrowed permissions add disallowedTools to the same options object.env, then writes its session-owned ANTHROPIC_MODEL, ANTHROPIC_API_KEY or CLAUDE_CODE_OAUTH_TOKEN when configured, CLAUDE_CONFIG_DIR, and HOME. Do not rely on overriding those variables through env.workingDirectory is used when the Agent is not running inside one.The adapter’s ACP authenticate method only supports gateway logins, so AML never calls it. Credentials travel in the launch environment instead:
apiKey → ANTHROPIC_API_KEYoauthToken → CLAUDE_CODE_OAUTH_TOKEN (create with claude setup-token)You can also place either variable in env; an explicit apiKey or oauthToken wins over the matching env entry. Because Claude Code receives a private configuration directory and home directory, an interactive claude /login, including a macOS Keychain login, is not available to AML sessions.
A launch without a Sandbox inherits the host process.env, so an ambient ANTHROPIC_API_KEY works for local development. A Sandbox receives only explicit configuration: pass the credential through apiKey, oauthToken, or env, or configure it through the Sandbox platform’s own secret mechanism.
Claude Code’s other model-provider variables, such as CLAUDE_CODE_USE_BEDROCK, CLAUDE_CODE_USE_VERTEX, ANTHROPIC_BASE_URL, and ANTHROPIC_AUTH_TOKEN, pass through env to Claude Code unchanged. AML does not test those paths; follow Claude Code’s settings documentation when you use them.
Without any credential, the session still starts and the first prompt fails with ACP error -32000 “Authentication required”. The evaluation rejects with an error naming Agent "claude" whose cause is an AcpAgentError.
| AML request | Claude launch mapping | Boundary that still matters |
|---|---|---|
filesystem: "read-write" | Claude Code’s standard tools; ACP permission requests answered allow_once. | The host or Sandbox still controls actual process and filesystem authority. |
filesystem: "read-only" | Disallows Edit, Write, and NotebookEdit. | Bash can still modify files unless shell: false; use an enforcing Sandbox. |
shell: false | Disallows Bash. | Sandbox process policy remains authoritative. |
network: false | Disallows WebFetch and WebSearch. | Sandbox or deployment egress policy must still contain other network paths. |
AML sends the disallowed tools as _meta.claudeCode.options.disallowedTools on ACP session/new, and Claude Code removes them from the model’s tool set. The enclosing Sandbox remains the process-level boundary.
AML answers every ACP permission request with allow_once. It never selects “allow always”, because the adapter would persist that rule into the project’s .claude/settings.local.json. AML does not use Claude Code’s bypass permission mode. The adapter disables Claude Code’s AskUserQuestion tool because AML does not offer ACP form elicitation.
For every acquired Claude session, AML creates a fresh temporary directory and launches the adapter with:
CLAUDE_CONFIG_DIR <invocation state directory>, or the staged .agents root when <Skill> packages are presentHOME <invocation state directory>Claude Code keeps settings, credentials, skills, and transcripts in its configuration directory. The adapter and Claude Code also resolve some paths through the home directory, so both are invocation-private. AML never reads or copies ~/.claude, and it removes the directory when the session ends. Reusing one claudeAgent() factory does not reuse Claude state between evaluations.
The adapter’s default Claude setting sources are user, project, and local. The user source resolves to AML’s private configuration directory, so the operator’s personal settings, CLAUDE.md, and skills are not loaded. Project sources still apply:
CLAUDE.md files;<cwd>/.claude/settings.json and <cwd>/.claude/settings.local.json;.claude/skills;/etc/claude-code/managed-settings.json on Linux.mcp__<server>__<tool>.- tool: mcp__aml__tool with the default aml server name.aml_submit_result bridge Tool is addressed as mcp__aml__aml_submit_result in the per-turn instruction. AML validates candidates and applies its single repair prompt exactly as for other ACP profiles.<Skill> packages are staged, CLAUDE_CONFIG_DIR points at the staged .agents root so Claude Code discovers each skills/<name>/SKILL.md itself.| Layer | Owns |
|---|---|
| AML | Launch profile, permission-to-disallowedTools mapping, state isolation, MCP bridge, structured output, FollowUps, cancellation, traces, and cleanup. |
claude-agent-acp adapter | The ACP server, session and configuration options, permission-request presentation, and model alias resolution. |
| Claude Agent SDK and Claude Code | The model loop, tools, loading of settings, CLAUDE.md, and skills, plus authentication and telemetry. |
AML does not change Claude Code’s telemetry. The adapter runs claude auth status --json when it initializes. Claude Code’s own telemetry and nonessential-traffic variables, such as DISABLE_TELEMETRY=1 or CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1, can be passed through env. AML’s own traces follow the shared Agent and ACP observability contract.
The adapter is Apache-2.0 licensed. The Claude Agent SDK, including the Claude Code executable it ships, is not open-source software: its use is subject to Anthropic’s legal agreements, including the Commercial Terms of Service. @aml-jsx/sdk does not bundle either package. The AML Agent Sandbox full and claude image variants include both unmodified and ship the SDK’s license statement at /usr/share/doc/aml-agent-sandbox/licenses/Anthropic-Claude-Agent-SDK-LICENSE.md.
Deterministic tests run a fake adapter process over stdio and exercise the MCP bridge, structured output, permission answers, cancellation, authentication errors, and a missing command without a paid request:
npm run test --workspace=@aml-jsx/agent-claudeThe opt-in live test launches npx -y @agentclientprotocol/claude-agent-acp@0.91.0 and requires ANTHROPIC_API_KEY or CLAUDE_CODE_OAUTH_TOKEN:
AML_CLAUDE_ACP_LIVE=1 npm run test:integration --workspace=@aml-jsx/agent-claudeThe credentialed smoke matrix runs Claude against each Sandbox with npm run smoke -- --agent claude --sandbox <local|docker|modal|daytona>. It reads AML_CLAUDE_API_KEY or ANTHROPIC_API_KEY, otherwise CLAUDE_CODE_OAUTH_TOKEN, and defaults to the haiku model; AML_CLAUDE_MODEL overrides it. These runs stay opt-in, and CI holds no Claude credentials.
command not found or ACP startup failure
Confirm that claude-agent-acp exists in the same host or Sandbox where AML calls spawn(), and that claude-agent-acp --version succeeds there. If the adapter was installed with --omit=optional, reinstall it without that flag so the platform-specific Claude Code executable is present. If you use a custom command, run that exact command with its args outside AML first.
Authentication required
The first prompt fails with ACP error -32000 when Claude Code has no credential. Pass apiKey or oauthToken, or set ANTHROPIC_API_KEY or CLAUDE_CODE_OAUTH_TOKEN in env. An interactive claude /login is not imported, and a Sandbox does not inherit host variables.
Configuration is rejected before launch
Set only one of apiKey and oauthToken. Remove leading/trailing whitespace and null bytes from strings.
Model unavailable
Use an alias such as "haiku" or "sonnet", or a full model id enabled for the account. AML forwards the value without validating it.
The Agent follows unexpected instructions or settings
Inspect project CLAUDE.md files, .claude/settings.json, .claude/settings.local.json, project hooks and skills, and managed policy files. Put evaluation instructions in <Agent system> or authored AML content.
The Agent can do more than expected
Check the effective permissions: read-only filesystem access does not remove Bash. ACP permission mapping is policy; the Sandbox is the security boundary.
These capabilities use AML’s shared Agent lifecycle and do not require Claude-specific setup: