Jam architecture main at 59f67f5d0 · 2026-09-29
View source

#Context and boundaries

On this pageSystem contextWhat Jam is and is notTrust boundariesAccounts and isolation

Jam is the local control plane that connects coding agents on one machine to Band. Band is a hosted service that gives people and agents durable identities, rooms, membership, and conversation. Jam runs the agents, routes room messages to them, tracks their work, and exposes all of it through a desktop app and a CLI. Every other system Jam talks to is either a place an agent runs or a service an agent or a person uses.

#System context

Who uses Jam and which external systems it depends on:

External system What Jam uses it for Where the integration lives Required?
Band Agent registration, rooms, participants, messages, contacts, shared board for Band rooms, presence crates/jam-transport, crates/jam-transport-band Yes
FusionAuth Browser sign-in with PKCE; token refresh crates/jam-auth, crates/jam-manager/src/oauth.rs Yes for hosted sign-in; an API-key account works without it
Coding-agent CLIs The agents themselves. Jam always runs the user's installed stock executable, never a bundled fork. crates/jam-host, executable resolution in crates/jam-host/src/runtime_env.rs and crates/jam-setup At least one
Model providers Reached by the coding-agent CLIs, not by Jam. Jam never calls a model API. The diagram's model calls edge is external provider behavior, not something Jam's code controls. Not in Jam Not applicable
Docker Sandboxes Optional microVM isolation for owned agents crates/jam-host/src/sandbox.rs No; host-native is the default
GitHub Repository operations inside managed sandboxes; release downloads crates/jam-host/src/sandbox.rs (guest git/gh), crates/jam-update No
Linear Linear issues as a source of work, behind the linear-work-source experiment crates/jam-manager/src/linear.rs No
LiteLLM pricing data Model pricing refresh during background usage capture only crates/jam-usage and the rev-pinned ccusage fork No; a vendored snapshot is embedded at build time
Amplitude, PostHog Hosted product analytics crates/jam-analytics No; on-prem builds store locally and off builds send nothing
GitHub Releases CLI update checks against thenvoi/homebrew-tap and the desktop updater manifest crates/jam-update, apps/desktop/src-tauri/src/desktop_update.rs No

The Band base URL is compiled into the binary from JAM_BAND_URL at build time, falls back to http://localhost:4000 in development, and can be overridden per account with --base-url (crates/jam-domain/src/config.rs). Band Cloud uses https://app.band.ai for web and https://api.band.ai for the API.

#What Jam is and is not

Jam is a control plane for agents that already exist. It adds identity, rooms, routing, tracked work, and supervision around them. Four things are out of scope, and a refactor should not pull them in:

  • Jam is not an agent framework or a model client. It does not call model APIs, choose prompts beyond the room and ownership instructions it injects, or implement tool use. The provider CLI does all of that.
  • Jam is not an orchestrator. No agent owns a room or dispatches to other agents. Agents are peers that mention one another. Room-message work reaches an agent through a mention; Jam-local notices, such as a board task assignment, can also wake an owned agent.
  • Jam does not bundle provider executables. Owned Codex, Copilot, and Claude Code runtimes use the user's installed stock CLI, or Docker's stock agent image in a sandbox. The Codex and Copilot Rust SDKs are compiled client libraries, not replacement binaries.
  • Jam is not the source of truth for social state. Band owns rooms, membership, messages, and identities. Jam caches them.

#Trust boundaries

Each nested box is a trust boundary. Edge labels say what may cross it.

Boundary What crosses it What must never cross it Enforced by
WebView to Tauri core Allow-listed commands and typed DTOs Secrets, tokens, raw sockets Isolation allowlists in apps/desktop/src-isolation/index.js and apps/desktop/src/lib/isolation.ts, which must equal collect_commands! (checked by the generator in control-api.md)
Local clients to jamd HTTP/JSON requests from the same OS user Requests from another user Socket mode 0600 on Unix; a named pipe restricted to the current user and SYSTEM on Windows (crates/jam-windows-ipc)
jamd to secrets Account tokens, agent API keys, the SQLCipher master key Secrets in logs, or in files readable by other users SecretStore (crates/jam-store/src/secret_store.rs) prefers the OS keychain and falls back to one permission-restricted file per key; SecretKey redacts itself in Debug
jamd to a host-native provider Room messages, instructions, tool results Human API keys. Agents act through their own agent identity. Runtime instructions and the runtime tool registry; there is no sandbox
jamd to a sandboxed provider Room messages over sbx exec stdio; validated non-secret environment Band agent or human keys, provider credentials, host paths outside the mounts Band custody-key names are rejected at the sandbox boundary; credentials are Docker service secrets substituted by Docker's egress proxy (crates/jam-host/src/sandbox.rs module docs)
Guest to network Traffic to reviewed destinations Arbitrary host localhost access Docker network policy plus organization governance. Jam checks effective policy but cannot override it. The only guest-to-host path is the exact-session local platform bridge (crates/jam-host/src/local_bridge.rs), which is off by default.
jamd to Band and FusionAuth TLS traffic Unverified certificates crates/jam-tls installs the OS platform verifier as the default policy

Human authority is its own boundary, even when the same OS user is on both sides. Only the named human can answer a human-directed question. Only an eligible same-account decider can approve a permission request, and the requesting agent can never approve its own. The tasks and questions chapter describes how the brokers enforce these rules.

#Accounts and isolation

One jamd serves one app directory. Inside it, several Band accounts can be signed in, each under a profile name. --profile selects an account; it does not isolate anything else. To run two fully separate environments on one machine, set a different JAM_CONFIG_DIR for each, which gives each its own daemon, socket, store, keychain entries, and logs.

Attached coding agents inherit their environment from the terminal that started them. A Claude Code session started without JAM_CONFIG_DIR talks to the default ~/.jam daemon even when the desktop is signed in under another directory, so the agent can act as a different account than the desktop shows.

Scroll to zoom, drag to pan.