Skip to main content

Built-in Adapter Implementations

Specification v1.0 | @a5c-ai/agent-mux

SCOPE EXTENSION: hermes-agent (@NousResearch/hermes-agent) is included as a 10th supported agent per explicit project requirements from the project owner. It extends the original scope document's 9 built-in agents. All hermes-specific content in this spec is marked with this same scope extension note.

SCOPE EXTENSION (2026-04): agent-mux-remote (11th, transport-only) and qwen (12th, Alibaba Qwen Code — a gemini-cli fork with MCP support) were added beyond the original 10. See agents/qwen.md for qwen usage.


1. Overview

This specification defines the implementation details for all 13 built-in adapter implementations in @a5c-ai/agent-mux. Each adapter extends BaseAgentAdapter (spec 05 §4) and translates between the unified AgentAdapter interface and the native CLI of its target agent.

This is the reference document for adapter authors and consumers who need to understand per-agent behavioral differences. It covers CLI arguments, event parsing, session formats, thinking normalization, install methods, auth detection, plugin delegation, and platform-specific notes for each adapter.

1.1 Cross-References

Type / ConceptSpecSection
AgentAdapter interface05-adapter-system.md2
BaseAgentAdapter abstract class05-adapter-system.md4
SpawnArgs type05-adapter-system.md3.1
AdapterRegistry05-adapter-system.md5
AgentCapabilities06-capabilities-and-models.md2
ModelCapabilities06-capabilities-and-models.md5
Thinking normalization tables06-capabilities-and-models.md8
Install metadata06-capabilities-and-models.md7
Capability profiles (complete)06-capabilities-and-models.md12
Plugin support per agent06-capabilities-and-models.md9
Config file locations08-config-and-auth.md7
Auth detection strategies08-config-and-auth.md10.1
AuthMethod, AuthState08-config-and-auth.md10, 9
Session formats07-session-manager.md5
Process lifecycle, PTY11-process-lifecycle-and-platform.md6
Platform support matrix11-process-lifecycle-and-platform.md5
AgentEvent union04-agent-events.md4
ErrorCode union01-core-types-and-client.md3.1
Scope §20 summary tableagent-mux-scope.md20

2. Built-in Adapter Summary

From scope §20, extended with hermes-agent:

AdapterCLIcliCommandSessionStreamResumeForkThinkingMCPSkillsPluginsACPPlatforms
Claude CodeclaudeclaudeJSONLyesyesyesyesyesyespartialnoall
Codex CLIcodexcodexJSONLyesnonoyesyesnononoall
Gemini CLIgeminigeminiJSONLyesnonoyesyesnononoall
Copilot CLIgh copilotcopilotJSONyesnononononononoall
CursorcursorcursorSQLitepartialnonomodel-depyesnoyesnoall
OpenCodeopencodeopencodeSQLiteyesyesyesmodel-depyesyesyesyesall
OpenCode HTTPopencode serveopencode-httpSQLiteyesyesyesmodel-depyesyesyesyesall
PipipiJSONL treeyesyesyesmodel-depnoyesyesyesall
ompompompJSONL treeyesyesyesyesnoyesyesyesall (Win partial)
OpenClawopenclawopenclawJSONpartialnonomodel-depyesyesyesnoall
hermeshermeshermesSQLiteyesyesnonoyesyesyesyesdarwin/linux

SCOPE EXTENSION: hermes-agent row added.

Column notes:

  • CLI: The actual command invoked. For copilot, the command is gh with args ['copilot', ...] (see §5).
  • cliCommand: The AgentAdapter.cliCommand property value (logical agent name).
  • Stream: "yes" = full text+tool+thinking streaming; "partial" = text streaming only.
  • Resume: Whether canResume: true in capabilities.
  • Fork: Whether canFork: true in capabilities.
  • Thinking: "yes" = always supported; "model-dep" = depends on ModelCapabilities.supportsThinking; "no" = not supported.
  • Plugins: "partial" for Claude = limited to skill-directory and mcp-server formats via --add-dir.
  • Platforms: "all" = darwin, linux, win32; "all (Win partial)" = all three platforms but with reduced Windows functionality; "darwin/linux" = no native Windows support.

3. Claude Code Adapter

Implementation note (2026-04): The claude adapter now uses Claude Code's real --print + --input-format stream-json + --output-format stream-json subprocess transport for live sessions. That lets agent-mux keep a single Claude subprocess alive and deliver later user turns over stdin while continuing to parse structured stream-json events from stdout. claude remote-control is now modeled separately as the claude-remote-control adapter: an external-host bridge surface for Claude.ai / Claude app sessions, not a local browser chat transport. Claude channels remain a separate MCP-mediated Claude surface and are still not represented as a first-class adapter.

3.1 Identity

PropertyValue
agent'claude'
displayName'Claude Code'
cliCommand'claude'
minVersion'1.0.0'

3.2 buildSpawnArgs

// Key CLI arguments
SpawnArgs {
command: 'claude',
args: [
'--print', // Required for structured output
'--input-format', 'stream-json', // Persistent stdin-driven user turns
'--output-format', 'stream-json', // Streaming JSON output
'--replay-user-messages', // Echo stdin user turns back on stdout
'--model', modelId, // Model selection
'--thinking-budget', budgetTokens, // Thinking (when enabled)
'--session', sessionId, // Resume session
'--add-dir', skillDir, // Skill directories
'--system', systemPrompt, // System prompt injection
'--system-mode', systemPromptMode, // prepend | append | replace
'--max-turns', maxTurns,
],
env: { ANTHROPIC_API_KEY: apiKey },
usePty: false,
}

Prompt delivery: Interactive Claude sessions use SpawnArgs.stdin and send newline-delimited stream-json user envelopes ({ type: 'user', message: { role: 'user', content }, parent_tool_use_id: null }) into the live Claude subprocess. Explicit nonInteractive=true falls back to a one-shot --print <prompt> invocation that exits after the first turn.

3.3 Event Parsing

Native format: Newline-delimited JSON (stream-json). Each line is a JSON object with a type field.

Key native event types and their AgentEvent mappings:

Native typeAgentEvent type(s)
message_startmessage_start
content_block_start (text)(consumed internally — text streaming begins)
content_block_delta (text)text_delta
content_block_start (thinking)thinking_start
content_block_delta (thinking)thinking_delta
content_block_stop (thinking)thinking_stop
content_block_start (tool_use)tool_call_start
content_block_delta (tool_use)tool_input_delta (incremental tool input)
content_block_stop (tool_use)tool_call_ready
replayed user event with parent_tool_use_id + tool_use_resulttool_result
message_delta(cost extraction → cost event)
message_stopmessage_stop
system.status=requestingturn_start
resultturn_end (+ fallback message_stop / cost when needed)

Session lifecycle events: When resuming a session (--session), the adapter emits session_resume after session_start. When forking (--fork), it emits session_fork. These events are synthesized by the adapter from the session metadata, not from native Claude output.

3.4 Session Format

  • Location: ~/.claude/projects/<hash>/ where <hash> is a content-hash of the project path.
  • Format: JSONL (one JSON object per line).
  • Capabilities: canResume: true, canFork: true, sessionPersistence: 'file'.

3.5 Thinking Normalization

EffortMappingCLI arg
'low'budget_tokens: 1024--thinking-budget 1024
'medium'budget_tokens: 8192--thinking-budget 8192
'high'budget_tokens: 32768--thinking-budget 32768
'max'budget_tokens: max_budget_tokens--thinking-budget max_budget_tokens

thinkingBudgetTokens is passed through directly. thinkingOverride is merged last.

3.6 Install Methods

PlatformTypeCommand
allnpmnpm install -g @anthropic-ai/claude-code
darwinbrewbrew install claude-code

3.7 Auth Detection

  • Primary: browser_login — inspects session token files in ~/.claude/ (per spec 08 §10.1).
  • Alternative: api_key — checks ANTHROPIC_API_KEY environment variable.

Cross-spec reconciliation: Spec 06 §12.1 lists auth methods as ['api-key','oauth'] while spec 08 §10.1 lists primary method as browser_login. This spec follows spec 08 as the authoritative source for auth detection. The browser_login method describes the detection strategy (checking local session tokens), while api-key and oauth in spec 06 describe the underlying credential types.

3.8 Plugin Support

  • supportsPlugins: true (partial — limited to skill-directory and mcp-server formats).
  • Formats: ['skill-directory', 'mcp-server'].
  • Mechanism: --add-dir flag for skill directories; MCP servers via config.
  • No dedicated plugin install/list/uninstall commands. Plugin operations are mapped to config file manipulation.
  • No marketplace URL. No registry.

4. Codex CLI Adapter

4.1 Identity

PropertyValue
agent'codex'
displayName'Codex CLI'
cliCommand'codex'
minVersion'1.0.0'

4.2 buildSpawnArgs

SpawnArgs {
command: 'codex',
args: [
prompt,
'--model', modelId,
'--reasoning', reasoningLevel, // 'low' | 'medium' | 'high'
'--session', sessionId,
],
env: { OPENAI_API_KEY: apiKey },
usePty: false,
}

4.3 Event Parsing

Native format: JSONL. OpenAI-style structured events.

Key native event types and their AgentEvent mappings:

Native typeAgentEvent type(s)
response.startmessage_start
response.text.deltatext_delta
response.reasoning.startthinking_start
response.reasoning.deltathinking_delta
response.reasoning.completethinking_stop
response.function_calltool_call_start
response.function_call.deltatool_input_delta (when streaming tool input)
response.function_call.completetool_call_ready
response.function_call_outputtool_result
response.costcost
response.completemessage_stop
errorerror

4.4 Session Format

  • Location: ~/.codex/sessions/
  • Format: JSONL.
  • Capabilities: canResume: false, canFork: false, sessionPersistence: 'file'.

Note: Spec 06 §12.2 confirms canResume=false, canFork=false for Codex CLI.

4.5 Thinking Normalization

EffortMappingCLI arg
'low''low'--reasoning low
'medium''medium'--reasoning medium
'high''high'--reasoning high
'max''high'--reasoning high (no separate max tier)

Note: Codex uses discrete reasoning levels, not token budgets. Setting thinkingBudgetTokens when supportsThinkingBudgetTokens: false throws CapabilityError before spawning, per spec 06 §11.

4.6 Install Methods

PlatformTypeCommand
allnpmnpm install -g @openai/codex

4.7 Auth Detection

  • Primary: api_key — checks OPENAI_API_KEY environment variable (validates format: must start with 'sk-').
  • Auth file: ~/.codex/auth.json.

4.8 Plugin Support

  • supportsPlugins: false.
  • All plugin operations throw CapabilityError.

5. Copilot CLI Adapter

5.1 Identity

PropertyValue
agent'copilot'
displayName'GitHub Copilot CLI'
cliCommand'copilot'
minVersion'1.0.0'

5.2 buildSpawnArgs

// Note: cliCommand is 'copilot' but actual command is 'gh'
SpawnArgs {
command: 'gh', // GitHub CLI binary
args: [
'copilot', // gh subcommand
prompt,
],
env: { GITHUB_TOKEN: token },
usePty: false,
}

Important: The cliCommand property is 'copilot' (the logical agent name), but SpawnArgs.command is 'gh' because Copilot CLI is installed as a GitHub CLI extension. The adapter's detectVersion() runs gh copilot --version, not copilot --version.

5.3 Event Parsing

Native format: Plain text streaming with JSON session metadata. Simpler parsing than most agents — primarily produces text_delta events.

Parsing strategy: Lines are checked for JSON structure first (session metadata). Non-JSON lines are treated as text output and emitted as text_delta events. Session metadata JSON objects (identified by having a session_id field) are consumed internally and not emitted.

Native output → AgentEvent mappings:

Native output patternAgentEvent type(s)
First text line receivedmessage_start (synthetic)
Non-JSON text linetext_delta
JSON metadata with session_id(consumed internally, not emitted)
Process exit code 0message_stop (synthetic)
Process exit code non-zerocrash

Auth/error detection: Since Copilot produces plain text, auth failures are detected by pattern-matching stderr and stdout for known error strings (e.g., "not authenticated", "requires authentication"). These are translated to auth_error events.

Key limitations:

  • No tool_call_start / tool_result / tool_input_delta events (supportsNativeTools: false).
  • No thinking_start / thinking_delta / thinking_stop events (supportsThinking: false).
  • No mcp_tool_call_start events (supportsMCP: false).
  • No session_resume / session_fork events (canResume: false, canFork: false).

5.4 Session Format

  • Location: ~/.config/github-copilot/sessions/
  • Format: JSON.
  • Capabilities: canResume: false, canFork: false, sessionPersistence: 'file'.

5.5 Thinking Normalization

Not applicable. supportsThinking: false. Setting thinkingEffort throws CapabilityError.

5.6 Install Methods

PlatformTypeCommandNotes
allgh-extensiongh extension install github/gh-copilotRequires GitHub CLI

Prerequisite: gh --version must succeed. Install GitHub CLI with brew install gh (macOS), apt install gh (Debian/Ubuntu), or winget install GitHub.cli (Windows).

5.7 Auth Detection

  • Primary: oauth_device — checks OAuth token cache in ~/.config/github-copilot/hosts.json.
  • Alternative: github_token — checks GITHUB_TOKEN environment variable.

5.8 Plugin Support

  • supportsPlugins: false.
  • All plugin operations throw CapabilityError.

6. Gemini CLI Adapter

6.1 Identity

PropertyValue
agent'gemini'
displayName'Gemini CLI'
cliCommand'gemini'
minVersion'1.0.0'

6.2 buildSpawnArgs

SpawnArgs {
command: 'gemini',
args: [
prompt,
'--model', modelId,
],
env: { GOOGLE_API_KEY: apiKey },
usePty: false,
}

MCP servers: Configured via the Gemini config file, not CLI args. The adapter writes MCP server definitions to ~/.config/gemini/settings.json before spawn.

6.3 Event Parsing

Native format: JSONL streaming output. Google-specific event shapes translated to AgentEvent.

Key native event types and their AgentEvent mappings:

Native typeAgentEvent type(s)
generateContent.startmessage_start
generateContent.texttext_delta
generateContent.thought.startthinking_start
generateContent.thoughtthinking_delta
generateContent.thought.donethinking_stop
generateContent.functionCalltool_call_start
generateContent.functionCall.deltatool_input_delta (when streaming tool input)
generateContent.functionCall.donetool_call_ready
generateContent.functionResponsetool_result
generateContent.imageimage_output
generateContent.donemessage_stop
usagecost (token usage extraction)

Unique capability: supportsImageOutput: true — Gemini is the only built-in agent that produces image_output events. The adapter parses base64-encoded image data from the native output.

6.4 Session Format

  • Location: ~/.gemini/sessions/
  • Format: JSONL.
  • Capabilities: canResume: false, canFork: false, sessionPersistence: 'file'.

Note: Spec 06 §12.3 confirms canResume=false, canFork=false for Gemini CLI.

6.5 Thinking Normalization

EffortMappingCLI mechanism
'low'thinkingConfig.thinkingBudget: 1024--thinking-budget 1024
'medium'thinkingConfig.thinkingBudget: 8192--thinking-budget 8192
'high'thinkingConfig.thinkingBudget: 32768--thinking-budget 32768
'max'thinkingConfig.thinkingBudget: max--thinking-budget max

Maps to Gemini's thinkingConfig equivalents. The --thinking-budget CLI flag is passed in the args array of SpawnArgs when thinkingEffort is set.

6.6 Install Methods

PlatformTypeCommand
allnpmnpm install -g @google/gemini-cli

6.7 Auth Detection

  • Primary: browser_login and api_key (both equally primary per spec 08 §10.1) — checks GOOGLE_API_KEY and GEMINI_API_KEY environment variables; also checks browser-based login session at ~/.config/gemini/credentials.json.
  • No alternative methods. Spec 06 §12.3 lists methods=['api-key','oauth']; the oauth method is the same credential mechanism as browser_login (browser-based OAuth flow producing a cached credential file).

6.8 Plugin Support

  • supportsPlugins: false.
  • All plugin operations throw CapabilityError.

7. Cursor Adapter

7.1 Identity

PropertyValue
agent'cursor'
displayName'Cursor'
cliCommand'cursor'
minVersion'0.45.0'

7.2 buildSpawnArgs

SpawnArgs {
command: 'cursor',
args: [
prompt,
'--model', modelId,
],
env: {}, // Auth via session token, not env var
usePty: false,
}

Cross-spec reconciliation: 06-capabilities-and-models.md §12.5 lists requiresPty=true for Cursor, which is incorrect. The correct value is false. Evidence: (1) Scope §22 explicitly names only "OpenClaw" as requiring PTY ("PTY support via node-pty for agents that require it (OpenClaw, some interactive modes)"). (2) 11-process-lifecycle-and-platform.md §6.1 lists only OpenClaw in the PTY-required agents table. (3) 03-run-handle-and-interaction.md §7.1 confirms Cursor's usePty=false. The requiresPty values for Cursor and OpenClaw are swapped in spec 06 (see also §11.9).

7.3 Event Parsing

Native format: Partial streaming — text events are streamed, but tool call results may be buffered. The adapter handles both streaming and buffered output.

Key native event types and their AgentEvent mappings:

Native output patternAgentEvent type(s)
Stream start markermessage_start
Text chunktext_delta
Tool invocation (buffered JSON)tool_call_start, tool_call_ready
Tool output (buffered JSON)tool_result
Completion markermessage_stop
Non-zero exit / error JSONcrash or error

Note: Cursor's output format is partially documented. The adapter's parseEvent() handles both streaming text lines and buffered JSON blocks for tool calls. Thinking events are model-dependent: emitted only when ModelCapabilities.supportsThinking is true for the selected model.

7.4 Session Format

  • Location: ~/.cursor/sessions/
  • Format: SQLite.
  • Capabilities: canResume: false, canFork: false, sessionPersistence: 'sqlite'.

7.5 Thinking Normalization

Model-dependent. When the selected model's ModelCapabilities.supportsThinking is true, thinking effort is passed as a provider-level parameter. When false, setting thinkingEffort throws CapabilityError.

7.6 Install Methods

PlatformTypeCommandNotes
darwinmanualopen https://cursor.sh/downloadmacOS .dmg installer
linuxmanualopen https://cursor.sh/downloadAppImage
win32wingetwinget install Cursor.Cursor

Note: No headless-only install. Full app required even for CLI use.

7.7 Auth Detection

  • Primary: browser_login — inspects session token in ~/.cursor/auth.json (per spec 08 §10.1).
  • Alternative: api_key — checks CURSOR_API_KEY environment variable.

Cross-spec reconciliation: Spec 06 §12.5 lists auth methods as ['oauth'] while spec 08 §10.1 lists primary method as browser_login. This spec follows spec 08 as the authoritative source for auth detection strategies. The distinction is behavioral: browser_login describes how the user authenticates (via Cursor's built-in browser flow), while the token format stored in auth.json is an OAuth token.

7.8 Plugin Support

  • supportsPlugins: true.
  • Formats: ['extension-ts', 'mcp-server'].
  • Registry: { name: 'cursor-extensions', url: 'https://cursor.sh/extensions', searchable: true }.
  • Cursor uses its own extension system for TypeScript extensions.

8. OpenCode Adapter

8.1 Identity

PropertyValue
agent'opencode'
displayName'OpenCode'
cliCommand'opencode'
minVersion'1.0.0'

8.2 buildSpawnArgs

SpawnArgs {
command: 'opencode',
args: [
prompt,
'--model', modelId,
'--session', sessionId,
'--fork', forkSessionId,
],
env: { /* provider-specific: ANTHROPIC_API_KEY or OPENAI_API_KEY */ },
usePty: false,
}

8.3 Event Parsing

Native format: Structured JSON streaming. Full tool call streaming. ACP event types also emitted.

Key native event types and their AgentEvent mappings:

Native typeAgentEvent type(s)
message.startmessage_start
message.text.deltatext_delta
message.thinking.startthinking_start (when model supports thinking)
message.thinking.deltathinking_delta (when model supports thinking)
message.thinking.donethinking_stop (when model supports thinking)
tool.calltool_call_start
tool.call.deltatool_input_delta
tool.call.donetool_call_ready
tool.resulttool_result
mcp.tool.callmcp_tool_call_start
mcp.tool.resultmcp_tool_result
message.completemessage_stop

ACP events: OpenCode emits native ACP protocol events (acp.request, acp.response) that are not part of the AgentEvent union (spec 04). These are translated to debug events with { type: 'debug', message: JSON.stringify(nativeEvent) }, preserving ACP data without extending the event union.

Unique capability: supportsStructuredOutput: true — OpenCode is the only built-in agent supporting structured output. When structured output is requested, the agent's final text output (in the last text_delta events before message_stop) contains the JSON-formatted structured response conforming to the user-specified schema. The adapter does not introduce new event types; consumers parse the accumulated text from text_delta events.

Session lifecycle events: When resuming (--session), the adapter emits session_resume. When forking (--fork), it emits session_fork. These are synthesized by the adapter from session metadata.

8.4 Session Format

  • Location: ~/.local/share/opencode/ (XDG data home on Linux; platform-appropriate on macOS/Windows).
  • Format: SQLite.
  • Capabilities: canResume: true, canFork: true, sessionPersistence: 'sqlite'.

8.5 Thinking Normalization

Model-dependent. Passed as provider-level parameter when model supports thinking.

8.6 Install Methods

PlatformTypeCommand
allnpmnpm install -g opencode
darwinbrewbrew install opencode/tap/opencode

8.7 Auth Detection

  • Primary: api_key — checks provider-specific env vars (ANTHROPIC_API_KEY, OPENAI_API_KEY) based on configured provider.
  • Auth file: ~/.config/opencode/auth.json.

8.8 Plugin Support

  • supportsPlugins: true.
  • Formats: ['npm-package', 'skill-file', 'mcp-server'].
  • Registry: { name: 'npm', url: 'https://www.npmjs.com/search?q=opencode-', searchable: true }.
  • Marketplace: https://www.npmjs.com/search?q=opencode-.

8.b OpenCode HTTP Adapter

8.b.1 Identity

PropertyValue
agent'opencode-http'
displayName'OpenCode (HTTP)'
adapterType'remote'
connectionType'http'
minVersion'0.1.0'

Note: This is a remote adapter (not subprocess), implementing the RemoteAdapter interface.

8.b.2 Connection Management

// HTTP connection via RemoteAdapter interface
interface OpenCodeHttpConnection {
connectionType: 'http';
baseUrl: string; // e.g., 'http://localhost:9527'

// Server-Sent Events streaming
stream(path: string, data: unknown): AsyncIterableIterator<AgentEvent>;

// REST API methods
get(path: string, params?: Record<string, unknown>): Promise<unknown>;
post(path: string, data?: unknown): Promise<unknown>;
}

Server management: The adapter automatically starts opencode serve --port 0 when needed and manages the server lifecycle.

8.b.3 Event Parsing

Transport: HTTP POST to /api/chat/stream with Server-Sent Events (SSE).

Event format: SSE events are parsed from data: {...} lines, with JSON payloads matching OpenCode's native event structure.

SSE Event TypeAgentEvent type(s)
message.startmessage_start
message.text.deltatext_delta
tool_start, tool_calltool_call_start
tool_inputtool_input_delta
tool_readytool_call_ready
tool_resulttool_result
message.stopmessage_stop

Enhanced streaming: SSE provides lower latency than subprocess stdout parsing.

8.b.4 Session Format

  • Location: Same as subprocess OpenCode: ~/.local/share/opencode/ (XDG data home on Linux).
  • Format: SQLite (shared with subprocess adapter).
  • Capabilities: canResume: true, canFork: true, sessionPersistence: 'sqlite'.

8.b.5 Server Lifecycle

  • Startup: opencode serve --port 0 --host 127.0.0.1 with dynamic port allocation.
  • Health monitoring: Regular /health endpoint checks.
  • Cleanup: Graceful server shutdown on adapter disposal.
  • Port management: Automatic port discovery to avoid conflicts.

8.b.6 Auth Detection

  • Inherited: Uses same auth detection as subprocess OpenCode adapter.
  • Provider support: ANTHROPIC_API_KEY, OPENAI_API_KEY, GOOGLE_API_KEY.
  • Config file: ~/.config/opencode/config.json.

8.b.7 Plugin Support

  • Identical to subprocess adapter: Supports MCP servers via HTTP API.
  • Formats: ['mcp-server'].
  • Registry: MCP server marketplace at https://modelcontextprotocol.io.

Advantage: HTTP interface enables enhanced MCP plugin management compared to subprocess limitations.


10. Pi Adapter

9.1 Identity

PropertyValue
agent'pi'
displayName'Pi'
cliCommand'pi'
minVersion'1.0.0'

9.2 buildSpawnArgs

SpawnArgs {
command: 'pi',
args: [
prompt,
'--model', modelId,
'--session', sessionId,
'--fork', forkSessionId,
],
env: { /* provider-specific */ },
usePty: false,
}

9.3 Event Parsing

Native format: JSONL streaming. Each line is a JSON object with id, parentId, type, and data fields.

Live event parsing vs. session parsing: During a live run, the adapter processes each JSONL line as it arrives. The id and parentId fields are used for session reconstruction (§9.4) but are not needed for real-time event emission. The type field determines the AgentEvent mapping:

Native type fieldAgentEvent type(s)
message_startmessage_start
texttext_delta
thinking_startthinking_start (when model supports thinking)
thinkingthinking_delta (when model supports thinking)
thinking_endthinking_stop (when model supports thinking)
tool_calltool_call_start
tool_call_inputtool_input_delta (when streaming tool input)
tool_call_readytool_call_ready
tool_resulttool_result
message_endmessage_stop
errorerror

Session lifecycle events: When resuming (--session), the adapter emits session_resume. When forking (--fork), it emits session_fork. These are synthesized by the adapter from session metadata.

9.4 Session Format

  • Location: ~/.pi/agent/sessions/
  • Format: JSONL tree (each entry has id and parentId fields forming a conversation tree).
  • Capabilities: canResume: true, canFork: true, sessionPersistence: 'file'.

Tree reconstruction: The session parser must reconstruct the conversation tree from id/parentId references rather than treating entries as a flat list. A given session file may contain multiple conversation branches.

9.5 Thinking Normalization

Model-dependent. Passed as provider-level parameter when model supports thinking.

9.6 Install Methods

PlatformTypeCommand
allnpmnpm install -g @mariozechner/pi-coding-agent

9.7 Auth Detection

  • Primary: api_key — checks provider-specific env vars based on configured provider.
  • Auth file: ~/.pi/agent/auth.json.

9.8 Plugin Support

  • supportsPlugins: true.
  • Formats: ['npm-package', 'skill-file'].
  • Registry: { name: 'npm', url: 'https://www.npmjs.com/search?q=%40mariozechner%2Fpi-', searchable: true }.

11. omp Adapter

10.1 Identity

PropertyValue
agent'omp'
displayName'omp (oh-my-pi)'
cliCommand'omp'
minVersion'1.0.0'

10.2 buildSpawnArgs

SpawnArgs {
command: 'omp',
args: [
prompt,
'--model', modelId,
'--session', sessionId,
'--fork', forkSessionId,
],
env: { /* provider-specific */ },
usePty: false,
}

10.3 Event Parsing

Native format: JSONL tree (identical format to Pi). Same id/parentId tree structure. Same native event type → AgentEvent mappings as Pi (§9.3), including tool_input_delta and session lifecycle events.

Key difference from Pi: omp unconditionally emits thinking_start, thinking_delta, and thinking_stop events regardless of model, since omp always supports thinking (§10.5).

10.4 Session Format

  • Location: ~/.omp/agent/sessions/
  • Format: JSONL tree (identical to Pi — same id/parentId structure).
  • Capabilities: canResume: true, canFork: true, sessionPersistence: 'file'.

10.5 Thinking Normalization

Always supported (not model-dependent, unlike Pi):

EffortMapping
'low'budget_tokens: 1024
'medium'budget_tokens: 8192
'high'budget_tokens: 32768
'max'budget_tokens: max_budget_tokens

Key difference from Pi: omp unconditionally supports all thinking effort levels. Setting thinkingEffort never throws CapabilityError for omp, regardless of model.

10.6 Install Methods

PlatformTypeCommand
allnpmnpm install -g @oh-my-pi/pi-coding-agent

10.7 Auth Detection

  • Same approach as Pi: provider-specific env var inspection.
  • Auth file: ~/.omp/agent/auth.json.

10.8 Plugin Support

  • supportsPlugins: true.
  • Formats: ['npm-package', 'skill-file'].
  • Registry: { name: 'npm', url: 'https://www.npmjs.com/search?q=%40oh-my-pi%2F', searchable: true }.

10.9 Platform Notes

  • Windows: Partial support. Core run/prompt functionality works. Some shell-dependent tool operations may behave differently under cmd.exe. The adapter emits a debug event with level: 'warn' on Windows.
  • supportedPlatforms: ['darwin', 'linux', 'win32'].
  • See 11-process-lifecycle-and-platform.md §5.2 for full details.

12. OpenClaw Adapter

11.1 Identity

PropertyValue
agent'openclaw'
displayName'OpenClaw'
cliCommand'openclaw'
minVersion'1.0.0'

11.2 buildSpawnArgs

SpawnArgs {
command: 'openclaw',
args: [
prompt,
'--model', modelId,
],
env: { OPENCLAW_API_KEY: apiKey },
usePty: true, // Requires PTY
}

11.3 Event Parsing

Native format: Interactive TUI output via PTY. Requires VT escape sequence stripping (VtStripper, spec 11 §6.3) before line-based parsing. After stripping, output lines are JSON objects.

Parsing pipeline: Raw PTY output → VtStripper.strip() → JSON.parse per line → native type → AgentEvent.

Key native event types and their AgentEvent mappings (after VT stripping):

Native JSON type fieldAgentEvent type(s)
response.startmessage_start
response.texttext_delta
response.thinking.startthinking_start (model-dependent)
response.thinkingthinking_delta (model-dependent)
response.thinking.endthinking_stop (model-dependent)
tool.invoketool_call_start
tool.invoke.deltatool_input_delta
tool.invoke.donetool_call_ready
tool.outputtool_result
channel.eventplugin_invoked (channel-plugin activity)
plugin.loadedplugin_loaded
response.endmessage_stop
errorerror

Session lifecycle: OpenClaw has canResume: false, canFork: false, so session_resume and session_fork events are never emitted.

Channel-plugin events: Native channel-plugin activity (messages from Telegram, Discord, Slack, etc.) is identified by the channel.event type and translated to plugin_invoked AgentEvents. The plugin_loaded event fires when a channel-plugin successfully connects to its messaging platform.

Partial streaming: Text events are streamed in real-time, but tool results may be buffered until the tool completes.

11.4 Session Format

  • Location: ~/.openclaw/sessions/
  • Format: JSON (per channel/session).
  • Capabilities: canResume: false, canFork: false, sessionPersistence: 'file'.

11.5 Thinking Normalization

Model-dependent. Passed as provider-level parameter when model supports thinking.

11.6 Install Methods

PlatformTypeCommandNotes
allnpmnpm install -g openclawRequires Node 22.16+, 16GB RAM minimum

11.7 Auth Detection

  • Primary: api_key — checks provider-specific env vars.
  • Auth file: ~/.openclaw/auth.json.

11.8 Plugin Support

  • supportsPlugins: true.
  • Formats: ['npm-package', 'skill-file', 'channel-plugin'].
  • Registries: [{ name: 'npm', searchable: true }, { name: 'openclaw-registry', url: 'https://openclaw.ai/plugins', searchable: true }].
  • Unique format: channel-plugin for messaging gateways (Telegram, Discord, Slack, WhatsApp, Signal).

11.9 PTY Requirement

OpenClaw is the only built-in agent with requiresPty: true (scope §22). See 11-process-lifecycle-and-platform.md §6 for PTY details.

Cross-spec reconciliation: 06-capabilities-and-models.md §12.9 incorrectly lists requiresPty=false for OpenClaw. The correct value is true, per scope §22 ("PTY support via node-pty for agents that require it (OpenClaw, some interactive modes)"), 03-run-handle-and-interaction.md §7.1, and 11-process-lifecycle-and-platform.md §6.1.

11.10 Platform Notes

  • Windows: Requires ConPTY (Windows 10 1809+). Older Windows versions fall back to winpty with potential output buffering differences.

13. Hermes Adapter

SCOPE EXTENSION: hermes-agent (@NousResearch/hermes-agent) is included as a 10th supported agent.

12.1 Identity

PropertyValue
agent'hermes'
displayName'hermes-agent'
cliCommand'hermes'
minVersion'0.1.0'

12.2 buildSpawnArgs

SpawnArgs {
command: 'hermes',
args: [
prompt,
'--output-format', 'jsonl', // Required for structured output
'--model', modelId, // Model selection (multi-provider)
'--session', sessionId, // Resume session (canResume=true)
],
env: {
// Multi-provider: set whichever key is configured
OPENROUTER_API_KEY: ...,
NOUS_API_KEY: ...,
ANTHROPIC_API_KEY: ...,
OPENAI_API_KEY: ...,
GITHUB_TOKEN: ...,
GOOGLE_API_KEY: ...,
},
usePty: false,
}

Critical: The --output-format jsonl flag must always be passed. Without it, hermes produces human-readable text that cannot be parsed by parseEvent().

12.3 Event Parsing

Native format: JSONL via --output-format jsonl. Python process emits structured events.

Key native event types and their AgentEvent mappings:

Native type fieldAgentEvent type(s)
message_startmessage_start
text_deltatext_delta
tool_calltool_call_start
tool_call_inputtool_input_delta
tool_call_readytool_call_ready
tool_resulttool_result
mcp_tool_callmcp_tool_call_start
mcp_tool_resultmcp_tool_result
skill_loadedskill_loaded (maps to SkillLoadedEvent, not PluginLoadedEvent)
skill_invokedskill_invoked (maps to SkillInvokedEvent, not PluginInvokedEvent)
message_endmessage_stop
usagecost
errorerror

Skill events: hermes skills are mapped to the skill_loaded / skill_invoked AgentEvent types (spec 04), not to plugin_loaded / plugin_invoked, because hermes's skill system matches the skill event semantics (name + source) rather than the plugin event semantics (pluginId + version).

MCP events: MCP tool events (mcp_tool_call_start, mcp_tool_result) are emitted when hermes invokes tools from connected MCP servers.

Session lifecycle: hermes has canResume: true, canFork: false. The adapter synthesizes session_resume when invoked with --session. No session_fork events.

Thinking: hermes has supportsThinking: false, so thinking_start, thinking_delta, and thinking_stop events are never emitted.

12.4 Session Format

  • Location: ~/.hermes/ (SQLite database).
  • Format: SQLite with FTS5 full-text search support.
  • Capabilities: canResume: true, canFork: false, sessionPersistence: 'sqlite'.

SCOPE EXTENSION: hermes session location and SQLite format are not in the original scope's session table (scope §16). This is a spec-level extension derived from hermes-agent's actual behavior.

12.5 Thinking Normalization

Not applicable. supportsThinking: false. Setting thinkingEffort throws CapabilityError.

12.6 Install Methods

PlatformTypeCommandNotes
allpippip install hermes-agentRequires Python >= 3.11
allcurlcurl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bashShell installer; requires Unix shell (bash). On Windows, use WSL2 or Git Bash.
allnixnix run github:NousResearch/hermes-agentNix flake available

SCOPE EXTENSION: hermes install methods are Python-based (pip), unlike all other agents which use npm or platform-specific methods. The 'pip' and 'nix' install types are already incorporated into the InstallMethod.type union in spec 06 §3.3.

12.7 Auth Detection

  • Primary: api_key (per spec 08 §10.1) — checks environment variables in priority order: OPENROUTER_API_KEY, NOUS_API_KEY, ANTHROPIC_API_KEY, OPENAI_API_KEY, GITHUB_TOKEN, GOOGLE_API_KEY.
  • Alternative: oauth — checks OAuth token cache from hermes login (Nous Portal or OpenAI Codex).
  • Alternative: github_token — checks GITHUB_TOKEN for GitHub-backed model access.
  • Alternative: config_file — inspects ~/.hermes/cli-config.yaml for embedded API keys (YAML safe-load only).
  • Returns 'authenticated' if any valid credential is found for any provider.
  • AuthState.details lists all detected providers with their auth method.

SCOPE EXTENSION: hermes-agent supports the broadest set of auth methods (6+ env vars, YAML config, OAuth) reflecting its multi-provider architecture.

12.8 Plugin Support

  • supportsPlugins: true.
  • Formats: ['skill-file', 'skill-directory', 'mcp-server'].
  • Registry: { name: 'agentskills-hub', url: 'https://agentskills.io', searchable: true }.
  • MCP: Supports both MCP client (connecting to external MCP servers) and MCP server (exposing hermes capabilities via mcp_serve.py).
  • Note: hermes MCP server plugins have no registry discovery path — they are configured directly via ~/.hermes/cli-config.yaml. See 09-plugin-manager.md for details.

12.9 Platform Notes

  • macOS / Linux: Fully supported.
  • Windows: WSL2 only. Native Windows is not supported. See 11-process-lifecycle-and-platform.md §5.3.
  • supportedPlatforms: ['darwin', 'linux'] — does not include 'win32'.
  • Python dependency: hermes is the only Python-based agent. It requires Python >= 3.11 on PATH. Virtual environment installations must ensure hermes is accessible on PATH.

14. Per-Adapter Thinking Effort Summary

Agent'low''medium''high''max'Budget tokensNotes
claude1024819232768max_budget_tokensPassed through--thinking-budget flag
codex'low''medium''high''high'Ignored--reasoning flag; max→high
gemini1024819232768maxVia thinkingConfigthinkingConfig equivalents
copilotsupportsThinking: false
cursormodel-depmodel-depmodel-depmodel-depmodel-depProvider-level param
opencodemodel-depmodel-depmodel-depmodel-depmodel-depProvider-level param
pimodel-depmodel-depmodel-depmodel-depmodel-depProvider-level param
omp1024819232768max_budget_tokensPassed throughAlways supported
openclawmodel-depmodel-depmodel-depmodel-depmodel-depProvider-level param
hermessupportsThinking: false

Cross-reference: Full thinking normalization tables are in 06-capabilities-and-models.md §8.


15. Per-Adapter Auth Summary

AgentPrimary methodEnv var(s)Auth file
claudebrowser_loginANTHROPIC_API_KEY~/.claude/ (session tokens)
codexapi_keyOPENAI_API_KEY~/.codex/auth.json
geminibrowser_login / api_keyGOOGLE_API_KEY, GEMINI_API_KEY~/.config/gemini/credentials.json
copilotoauth_deviceGITHUB_TOKEN~/.config/github-copilot/hosts.json
cursorbrowser_loginCURSOR_API_KEY (fallback)~/.cursor/auth.json
opencodeapi_keyProvider-specific~/.config/opencode/auth.json
piapi_keyProvider-specific~/.pi/agent/auth.json
ompapi_keyProvider-specific~/.omp/agent/auth.json
openclawapi_keyProvider-specific~/.openclaw/auth.json
hermesMulti (6+ methods)6+ env vars~/.hermes/.env, ~/.hermes/cli-config.yaml

Cross-reference: Full auth detection strategies are in 08-config-and-auth.md §10.1.

Invariant: All auth detection is read-only, local-only, no network calls, completes under 100ms.


16. Per-Adapter Plugin Support Summary

AgentsupportsPluginsFormatsRegistryMarketplace
claudetrue (partial)skill-directory, mcp-server
codexfalse
geminifalse
copilotfalse
cursortrueextension-ts, mcp-servercursor-extensionshttps://cursor.sh/extensions
opencodetruenpm-package, skill-file, mcp-servernpmhttps://www.npmjs.com/search?q=opencode-
pitruenpm-package, skill-filenpmhttps://www.npmjs.com/search?q=%40mariozechner%2Fpi-
omptruenpm-package, skill-filenpmhttps://www.npmjs.com/search?q=%40oh-my-pi%2F
openclawtruenpm-package, skill-file, channel-pluginnpm + openclaw-registryhttps://openclaw.ai/plugins
hermestrueskill-file, skill-directory, mcp-serveragentskills-hubhttps://agentskills.io

Cross-reference: Full plugin support matrix in 06-capabilities-and-models.md §9 and 09-plugin-manager.md.


17. Error Format Translation

All adapters translate native agent errors into typed AgentEvent objects. The BaseAgentAdapter class (spec 05 §4) provides hook methods for common error scenarios:

16.1 Error Event Mappings

Native error typeAgentEvent typeFields
Auth failure (invalid/missing key)auth_erroragent, message, guidance
Rate limit / quota exceededrate_limit_errormessage, retryAfterMs
Context window exceededcontext_exceededusedTokens, maxTokens
Process crash (non-zero exit)crashexitCode, stderr
Generic / unknown errorerrorcode: ErrorCode, message, recoverable

16.2 parseEvent() Contract

  • parseEvent() must never throw. Unrecognized lines return null.
  • In debug mode (ClientOptions.debug: true, spec 01 §5.1.1), unrecognized lines are emitted as { type: 'log', source: 'stdout', line: rawLine } (conforming to the LogEvent type defined in spec 04).
  • Empty lines and whitespace-only lines are silently dropped.

16.3 BaseAgentAdapter Error Hooks

Per spec 05 §4 (canonical signatures):

HookSignatureTriggerDefault behavior
onSpawnError(error)(error: Error) → AgentEventSubprocess fails to startReturns { type: 'crash', exitCode: -1, stderr: error.message }
onTimeout()() → AgentEventRun or inactivity timeoutReturns { type: 'error', code: 'TIMEOUT', recoverable: false }
onProcessExit(code, signal)(exitCode: number, signal: string | null) → AgentEvent[]Subprocess exitsReturns terminal events based on exit code/signal
shouldRetry(event, attempt, policy)(event: AgentEvent, attempt: number, policy: RetryPolicy) → booleanAfter error, before retryReturns false (no retry by default)

18. Version Detection

All adapters detect the installed agent version via detectVersionFromCli() (a BaseAgentAdapter utility):

// Default: runs `<cliCommand> --version` and parses semver
const version = await detectVersionFromCli(adapter.cliCommand);

Exceptions:

  • Copilot: Runs gh copilot --version (not copilot --version).
  • hermes: Runs hermes --version; output is Python-formatted (e.g., hermes-agent 0.1.0).

The detected version is compared against minVersion. If the installed version is below minVersion, AdapterRegistry.detect() returns an InstalledAgentInfo with meetsMinVersion: false and mux.run() emits a debug warning.


19. Adapter Registration

All 10 built-in adapters are registered with the AdapterRegistry during createClient():

// Simplified registration sequence
const registry = new AdapterRegistry();
registry.register(new ClaudeCodeAdapter());
registry.register(new CodexAdapter());
registry.register(new GeminiAdapter());
registry.register(new CopilotAdapter());
registry.register(new CursorAdapter());
registry.register(new OpenCodeAdapter());
registry.register(new PiAdapter());
registry.register(new OmpAdapter());
registry.register(new OpenClawAdapter());
registry.register(new HermesAdapter());

Plugin adapters registered via mux.adapters.register() are added after built-in adapters and extend the AgentName union at runtime.


20. Spec-Level Additions

The following items are spec-level additions not explicitly stated in the scope:

AdditionSectionRationale
minVersion per adapter§3–12Required for version compatibility checking
hermes --output-format jsonl requirement§12.2Not stated in scope; discovered through research
hermes FTS5 session search§12.4SQLite FTS5 support is hermes-specific
Claude session hash-based paths§3.4Implementation detail not in scope
Codex 'max''high' mapping§4.5Scope says 'max'→'high' but only in comment
parseEvent() never-throw contract§16.2Implied by spec 05 but not explicit in scope
Debug-mode logging of unrecognized lines§16.2Extension for adapter debugging
Copilot gh vs copilot command split§5.2Scope lists copilot as CLI but actual binary is gh
OpenClaw PTY reconciliation note§11.9Corrects spec 06 cross-spec error
Cursor PTY reconciliation note§7.2Corrects spec 06 cross-spec error (swapped with OpenClaw)
Auth method reconciliation notes§3.7, §7.7Resolves spec 06 vs spec 08 auth method naming discrepancies
Per-adapter event mapping tables§3–12Scope describes formats, not specific native event types
Session lifecycle event synthesis§3–12Adapters synthesize session_resume/session_fork from metadata
hermes nix install method§12.6From spec 06 §7.10; extends scope's install union
Prompt delivery via stdin§3.2Implementation detail for long/array prompts
OpenCode ACP events as debug§8.3ACP events not in AgentEvent union; translated to debug

Implementation Status (2026-04-12)

Per-adapter session directories

Verified from each adapter's sessionDir():

AgentSession directory
claude~/.claude/projects
codex~/.codex/sessions
gemini~/.gemini/sessions
copilot~/.config/github-copilot/sessions
cursor~/.cursor/sessions
opencode~/.local/share/opencode
pi~/.pi/agent/sessions
omp~/.omp/agent/sessions
openclaw~/.openclaw/sessions
hermes~/.hermes/sessions
agent-mux-remote(none — transport-delegated)

All adapters use listJsonlFiles() from packages/adapters/src/session-fs.ts to enumerate session files; writes route through the tmp + fs.rename atomic helper in the same module.

13. agent-mux-remote (11th built-in adapter)

AgentMuxRemoteAdapter (packages/adapters/src/agent-mux-remote-adapter.ts) is a pass-through adapter that emits plain amux run … spawn args. Transport is out of scope for the adapter: the caller wraps the returned SpawnArgs with a RunOptions.invocation of 'local', 'docker', 'ssh', or 'k8s' via buildInvocationCommand(). This lets agent-mux nest: a local amux can dispatch to a second amux executing in a Docker container, on a remote SSH host, or in a Kubernetes pod.

Key fields:

FieldValue
agent'agent-mux-remote'
displayNameagent-mux (remote via invocation mode)
cliCommandamux
hostEnvSignals[]
sessionDir()throws (delegated; the remote amux owns sessions)
Auth{ type: 'api_key', name: 'Transport' } — handled by the chosen invocation mode.

Runtime configuration is supplied via RunOptions.env:

  • AMUX_REMOTE_AGENT — the harness to invoke on the remote side (default claude).

Structured JSONL events produced by the nested amux run are passed through unchanged.