Architecture
Overview
Section titled “Overview”AgentPane is a Turborepo monorepo with three packages:
apps/server— Hono HTTP server with Effect.ts service layers (port 3456)apps/web— Next.js 16 App Router with React 19 (port 6767)apps/docs— Astro + Starlight documentation site
npx agentpane starts two processes: the Hono API server on port 3456 and a Next.js standalone server on port 6767. In development, the Next.js dev server rewrites /api/* to the API server. No auth or CORS — everything is same-origin.
Two-Process Server
Section titled “Two-Process Server”┌──────────────────────┐ ┌──────────────────────┐│ Next.js (port 6767) │ │ Hono (port 3456) ││ │ │ ││ App Router UI │──▶│ /api/* routes ││ (rewrites /api/*) │ │ │└──────────────────────┘ │ Effect.ts Services │ │ ┌──────────────────┐ │ │ │ ConnectionManager │ │ │ │ PromptEngine │ │ │ │ EventHub │ │ │ │ WriteQueue │ │ │ │ SessionRepo │ │ │ └────────┬─────────┘ │ │ │ │ │ ┌────────┴────┐ │ │ │ SQLite │ │ │ │ (WAL) │ │ │ └─────────────┘ │ │ │ │ ┌────────────────┐ │ │ │ Agent (stdio) │ │ │ │ ACP/JSON-RPC │ │ │ └────────────────┘ │ └──────────────────────┘Backend Services
Section titled “Backend Services”The backend uses Effect.ts for dependency injection and error handling. Services are composed into a ManagedRuntime:
| Service | Responsibility |
|---|---|
| AcpClient | Facade composing ConnectionManager, EventHub, PromptEngine, and WriteQueue |
| ConnectionManager | Agent subprocess lifecycle, ACP connection setup, session load/resume |
| PromptEngine | Prompt execution orchestration, turn persistence, token tracking |
| EventHub | Session-level event broadcaster management with idle cleanup |
| WriteQueue | Batched DB writes (50ms debounce per session, crash recovery) |
| SessionRepo | CRUD for sessions, turns, and message blocks in SQLite |
| SqliteLive | Database connection, migrations, WAL mode, foreign keys |
Error Handling
Section titled “Error Handling”Domain errors use Schema.TaggedError with httpStatus and httpMessage getters. The runEffect bridge function maps Effect exits to HTTP responses automatically.
Frontend
Section titled “Frontend”The frontend is a Next.js 16 App Router application — pure UI with no backend dependencies. It communicates with the API via plain fetch using relative URLs (same-origin, no auth tokens).
Key patterns:
- React Query — All server state with SSR prefetch and dehydration, query invalidation on SSE events
- Always-on EventSource — SSE connection stays open regardless of agent connection state
- React Compiler — Automatic memoization, no manual
useMemo/useCallback - Streaming markdown — Via Streamdown with Shiki syntax highlighting
Agent Communication
Section titled “Agent Communication”AgentPane talks to agents over the Agent Client Protocol (ACP) — JSON-RPC 2.0 over stdio:
- The server spawns the agent binary as a child process
- Communication uses newline-delimited JSON over stdin/stdout
- Events are broadcast to the frontend via SSE (Server-Sent Events)
Session-level broadcasters survive agent disconnects, delivering connection status events to keep the UI in sync.
Database
Section titled “Database”SQLite with WAL mode, stored at ~/.agentpane/agentpane.db (configurable via AGENTPANE_DATA_DIR). Three tables:
- sessions — id, name, working directory, agent type, timestamps
- turns — id, session reference, role (user/assistant), stop reason
- message_blocks — id, turn reference, kind, content