Skip to main content

Architecture Design

patb-cli is a thin client and protocol gateway in front of a remote agent service. It does not run any agent logic locally — all reasoning happens on the remote service at d33ib4uu7f4xpi.cloudfront.net; the CLI's job is to create threads, trigger runs, and translate the resulting event stream into either terminal output or ACP JSON-RPC messages.

Two front ends, one remote client

Both operational modes are built on the same three remote operations exposed by src/remote.ts:

  1. createAWSThread(apiKey)POST /threads, returns a thread_id.
  2. triggerAWSRun(apiKey, threadId, prompt)POST /threads/:threadId/runs, returns a run_id. Runs are triggered with { agentName: "the-brain", prompt, wait: false }.
  3. connectAWSStream(apiKey, threadId, runId, callbacks)GET /threads/:threadId/runs/:runId/stream (Accept: text/event-stream), parsing Server-Sent Events and invoking onProgress, onComplete, or onError.
  • src/cli.ts (Interactive REPL, the default mode) renders onProgress to stderr and the final onComplete text to stdout, then loops back to prompt for the next message on the same thread.
  • src/bridge.ts (Zed ACP Bridge, --bridge/-b) maps each Zed session/new to a fresh remote thread, and turns onProgress/onComplete into ACP session/update JSON-RPC notifications, finishing each session/prompt with a stopReason: "end_turn" result. See ACP Protocol for the full method/notification reference.

Response selection

The remote service returns each reply in instructorState.explanation, and connectAWSStream reads it from there, falling back to the run's messages and finally to a generic completion notice — see CLI Usage for the exact order.

That field name is a leftover worth knowing about. The service once routed a supervisor node to several specialists, each contributing its own slice of state, and this client chose between a writer's draft, an instructor's explanation and a developer's test results. The service has since been rebuilt as a single agent, and it keeps instructorState.explanation precisely so that clients like this one did not have to change. The branches for the other two shapes have been removed: they could no longer be sent, and testing for them only disguised how simple the contract now is.

Configuration boundary

src/config.ts is the single source of truth for credentials: it loads .env (without overriding real environment variables) and fails fast — before either front end starts — if PATBA_API_KEY is missing. Both cli.ts and bridge.ts receive an already-validated key from index.ts; neither module re-implements credential loading.