#Context and boundaries
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.