Agentic AI Atlasby a5c.ai
OverviewWikiGraphFor AgentsEdgesSearchWorkspace
/
GitHubDocsDiscord
iiRecord
Agentic AI Atlas · Multi-Adapter Architecture Design
page:docs-agent-mux-archive-design-18-multi-adapter-architecturea5c.ai
Search record views/
Record · tabs

Available views

II.Record viewspp. 1 - 1
overviewarticlejsongraph
II.
Page JSON

page:docs-agent-mux-archive-design-18-multi-adapter-architecture

Structured · live

Multi-Adapter Architecture Design json

Inspect the normalized record payload exactly as the atlas UI reads it.

File · wiki/docs/agent-mux/archive/design/18-multi-adapter-architecture.mdCluster · wiki
Record JSON
{
  "id": "page:docs-agent-mux-archive-design-18-multi-adapter-architecture",
  "_kind": "Page",
  "_file": "wiki/docs/agent-mux/archive/design/18-multi-adapter-architecture.md",
  "_cluster": "wiki",
  "attributes": {
    "nodeKind": "Page",
    "sourcePath": "docs/agent-mux/archive/design/18-multi-adapter-architecture.md",
    "sourceKind": "repo-docs",
    "title": "Multi-Adapter Architecture Design",
    "displayName": "Multi-Adapter Architecture Design",
    "slug": "docs/agent-mux/archive/design/18-multi-adapter-architecture",
    "articlePath": "wiki/docs/agent-mux/archive/design/18-multi-adapter-architecture.md",
    "article": "\n# Multi-Adapter Architecture Design\n\n> Archived design document. Preserved for historical context; not part of the current normative `reference/` contract.\n\n## Overview\n\nExtend agent-mux to support multiple adapter types beyond subprocess-based execution. This enables integration with sophisticated tools that provide HTTP APIs, WebSocket interfaces, or direct SDK access.\n\n## Current Architecture (Subprocess-Only)\n\n```typescript\ninterface AgentAdapter {\n  buildSpawnArgs(options: RunOptions): SpawnArgs;\n  parseEvent(line: string, context: ParseContext): AgentEvent | AgentEvent[] | null;\n  // ... session, auth, config methods\n}\n```\n\n**Limitations:**\n- Forces all tools into subprocess model\n- Cannot leverage HTTP APIs, WebSocket streaming, or native SDKs\n- Suboptimal for TUI-first tools (OpenCode), server-based tools (Codex app-server)\n\n## Proposed Architecture\n\n### 1. Adapter Type Hierarchy\n\n```typescript\n// Base interface (shared across all adapter types)\ninterface BaseAgentAdapter {\n  // Identity\n  readonly agent: AgentName;\n  readonly displayName: string;\n  readonly adapterType: 'subprocess' | 'remote' | 'programmatic';\n  \n  // Capabilities (unchanged)\n  readonly capabilities: AgentCapabilities;\n  readonly models: ModelCapabilities[];\n  \n  // Common functionality\n  detectAuth(): Promise<AuthState>;\n  getAuthGuidance(): AuthSetupGuidance;\n  sessionDir(cwd?: string): string;\n  parseSessionFile(filePath: string): Promise<Session>;\n  // ... other common methods\n}\n\n// Subprocess adapters (current model)\ninterface SubprocessAdapter extends BaseAgentAdapter {\n  readonly adapterType: 'subprocess';\n  readonly cliCommand: string;\n  buildSpawnArgs(options: RunOptions): SpawnArgs;\n  parseEvent(line: string, context: ParseContext): AgentEvent | AgentEvent[] | null;\n}\n\n// Remote adapters (HTTP, WebSocket, Unix sockets)\ninterface RemoteAdapter extends BaseAgentAdapter {\n  readonly adapterType: 'remote';\n  readonly connectionType: 'http' | 'websocket' | 'unix';\n  \n  connect(options: RunOptions): Promise<RemoteConnection>;\n  disconnect(connection: RemoteConnection): Promise<void>;\n  \n  // Optional: start/stop server if adapter manages it\n  startServer?(): Promise<ServerInfo>;\n  stopServer?(serverInfo: ServerInfo): Promise<void>;\n}\n\n// Programmatic adapters (direct SDK integration)\ninterface ProgrammaticAdapter extends BaseAgentAdapter {\n  readonly adapterType: 'programmatic';\n  \n  execute(options: RunOptions): AsyncIterableIterator<AgentEvent>;\n}\n```\n\n### 2. Connection Abstractions\n\n```typescript\n// Remote connection interface\ninterface RemoteConnection {\n  readonly connectionId: string;\n  readonly connectionType: 'http' | 'websocket' | 'unix';\n  \n  send(data: unknown): Promise<void>;\n  receive(): AsyncIterableIterator<AgentEvent>;\n  close(): Promise<void>;\n}\n\n// HTTP-specific connection\ninterface HttpConnection extends RemoteConnection {\n  readonly connectionType: 'http';\n  readonly baseUrl: string;\n  \n  get(path: string, params?: Record<string, unknown>): Promise<unknown>;\n  post(path: string, data?: unknown): Promise<unknown>;\n  stream(path: string, data?: unknown): AsyncIterableIterator<AgentEvent>;\n}\n\n// WebSocket-specific connection  \ninterface WebSocketConnection extends RemoteConnection {\n  readonly connectionType: 'websocket';\n  readonly websocketUrl: string;\n  \n  subscribe(channel: string): AsyncIterableIterator<AgentEvent>;\n  unsubscribe(channel: string): Promise<void>;\n}\n```\n\n### 3. Server Management\n\n```typescript\ninterface ServerInfo {\n  readonly serverId: string;\n  readonly serverType: string;\n  readonly endpoint: string;\n  readonly pid?: number;\n  readonly health?: 'starting' | 'healthy' | 'unhealthy';\n}\n\ninterface ServerManager {\n  start(adapter: RemoteAdapter, options?: ServerOptions): Promise<ServerInfo>;\n  stop(serverId: string): Promise<void>;\n  health(serverId: string): Promise<ServerInfo>;\n  list(): Promise<ServerInfo[]>;\n}\n```\n\n## Implementation Plan\n\n### Phase 1: Core Architecture\n\n1. **Create new interface hierarchy** in `packages/core/src/adapter-types.ts`\n2. **Extend AgentAdapter** to be union type: `SubprocessAdapter | RemoteAdapter | ProgrammaticAdapter`\n3. **Update BaseAgentAdapter** in adapters package to implement `SubprocessAdapter`\n4. **Maintain backward compatibility** - all existing adapters continue working\n\n### Phase 2: Execution Engine Updates\n\n1. **Update RunHandleImpl** to route based on `adapter.adapterType`\n2. **Create RemoteRunner** for HTTP/WebSocket execution\n3. **Create ProgrammaticRunner** for direct SDK execution  \n4. **Add ServerManager** for lifecycle management\n5. **Update event streaming** to handle different execution models\n\n### Phase 3: New Adapter Implementations\n\n1. **opencode-http**: HTTP server + REST API + SSE streaming\n2. **codex-sdk**: Direct SDK integration\n3. **codex-websocket**: WebSocket app-server integration\n4. **claude-agent-sdk**: Programmatic Claude interface\n5. **pi-sdk**: Enhanced programmatic Pi interface\n\n### Phase 4: Mock Infrastructure\n\n1. **MockHttpServer**: Simulate HTTP endpoints + SSE\n2. **MockWebSocketServer**: Simulate real-time connections\n3. **MockSDK**: Simulate direct SDK calls\n4. **Enhanced scenarios**: Support all adapter types\n\n## Adapter Naming Convention\n\n**Pattern**: `{tool}-{type}` where type indicates the integration method:\n\n- `opencode` (subprocess, default)\n- `opencode-http` (HTTP server)\n- `codex` (subprocess, current)\n- `codex-sdk` (programmatic SDK)\n- `codex-websocket` (WebSocket app-server)\n- `claude-agent-sdk` (programmatic)\n\n## Example Adapter Implementations\n\n### HTTP Adapter (OpenCode)\n\n```typescript\nclass OpenCodeHttpAdapter implements RemoteAdapter {\n  readonly adapterType = 'remote';\n  readonly connectionType = 'http';\n  readonly agent = 'opencode-http';\n  \n  async connect(options: RunOptions): Promise<HttpConnection> {\n    // Start 'opencode serve' if needed\n    const serverInfo = await this.ensureServer();\n    \n    // Create HTTP connection\n    return new OpenCodeHttpConnection({\n      baseUrl: serverInfo.endpoint,\n      sessionId: options.sessionId,\n      model: options.model,\n    });\n  }\n  \n  private async ensureServer(): Promise<ServerInfo> {\n    // Check if server already running\n    // If not, start via 'opencode serve --port 0'\n    // Return connection details\n  }\n}\n\nclass OpenCodeHttpConnection implements HttpConnection {\n  async *stream(path: string, data: unknown): AsyncIterableIterator<AgentEvent> {\n    // POST to /api/chat/stream with SSE\n    const response = await fetch(`${this.baseUrl}${path}`, {\n      method: 'POST',\n      body: JSON.stringify(data),\n      headers: { 'Accept': 'text/event-stream' }\n    });\n    \n    for await (const chunk of response.body) {\n      yield this.parseServerSentEvent(chunk);\n    }\n  }\n}\n```\n\n### SDK Adapter (Codex)\n\n```typescript\nclass CodexSdkAdapter implements ProgrammaticAdapter {\n  readonly adapterType = 'programmatic';\n  readonly agent = 'codex-sdk';\n  \n  async *execute(options: RunOptions): AsyncIterableIterator<AgentEvent> {\n    const sdk = new CodexSDK({\n      apiKey: process.env.OPENAI_API_KEY,\n      model: options.model || this.defaultModelId,\n    });\n    \n    const stream = await sdk.chat.completions.create({\n      messages: [{ role: 'user', content: options.prompt }],\n      stream: true,\n    });\n    \n    for await (const chunk of stream) {\n      yield this.parseCodexChunk(chunk);\n    }\n  }\n}\n```\n\n## Migration Strategy\n\n1. **Backward Compatible**: All existing adapters continue working unchanged\n2. **Gradual Adoption**: Add new adapter types without breaking existing functionality  \n3. **Clear Documentation**: Document when to use each adapter type\n4. **Mock Support**: Ensure all adapter types have full mock coverage\n\n## Benefits\n\n1. **Native Performance**: Direct SDK integration eliminates subprocess overhead\n2. **Real-time Streaming**: WebSocket connections enable bidirectional communication\n3. **Full Capabilities**: HTTP APIs provide access to complete tool feature sets\n4. **Flexible Integration**: Choose the best integration method per tool\n5. **Future-Proof**: Support emerging tools with non-CLI interfaces\n\n## Claude-Specific Transport Note\n\nClaude now spans multiple distinct integration surfaces that should not be collapsed into a single \"server mode\" mental model:\n\n- `claude` CLI can provide a **persistent structured subprocess transport** through `--print --input-format stream-json --output-format stream-json`, with stdin carrying later user turns and stdout carrying structured events.\n- `claude-agent-sdk` is a **programmatic persistent transport** with direct callback integration.\n- `claude-remote-control` is the **server-managed Claude surface for Claude.ai / Claude app clients**. Agent-mux can launch and observe the bridge honestly, but it does not advertise local stdin-driven chat semantics for it.\n- Claude channels are **MCP-mediated push/reply integrations into a running Claude host session**, not a standalone replacement for the CLI or SDK transports.\n\nAgent-mux should model these surfaces honestly and only advertise the transport semantics each one actually supports.\n\n## Trade-offs\n\n1. **Complexity**: Multiple execution paths increase code complexity\n2. **Resource Management**: HTTP servers and connections need lifecycle management\n3. **Testing**: More sophisticated mocking required\n4. **Dependencies**: Programmatic adapters may require additional npm dependencies\n\n## Files to Create/Modify\n\n### New Files\n- `packages/core/src/adapter-types.ts` - New interface hierarchy\n- `packages/core/src/remote-runner.ts` - HTTP/WebSocket execution\n- `packages/core/src/programmatic-runner.ts` - SDK execution  \n- `packages/core/src/server-manager.ts` - Server lifecycle management\n- `packages/adapters/src/remote-adapter-base.ts` - Base class for remote adapters\n- `packages/adapters/src/programmatic-adapter-base.ts` - Base class for SDK adapters\n\n### Modified Files\n- `packages/core/src/adapter.ts` - Update AgentAdapter union type\n- `packages/core/src/run-handle-impl.ts` - Route by adapter type\n- `packages/adapters/src/base-adapter.ts` - Implement SubprocessAdapter\n- `packages/harness-mock/src/index.ts` - Add mock infrastructure\n\nThis architecture enables agent-mux to evolve beyond subprocess-only integration while maintaining full backward compatibility and providing a clear path for supporting sophisticated AI tools with diverse integration requirements.\n",
    "documents": []
  },
  "outgoingEdges": [],
  "incomingEdges": [
    {
      "from": "page:docs-agent-mux-archive-design",
      "to": "page:docs-agent-mux-archive-design-18-multi-adapter-architecture",
      "kind": "contains_page"
    }
  ]
}

Shortcuts

Back to overview
Open graph tab