Architecture
The AnyHarness, worker, gateway, and client ownership split.
This page is for developers who want to understand where the boundaries sit: what the client renders, what the runtime executes, what the control plane owns, and how credentials move (or, deliberately, don't move) between them. For a gentler introduction, start with Overview and Core components.
Four pieces, one hard rule
The hard rule that never bends: third-party tool credentials never leave the control plane. Your Linear token, your Notion OAuth grant, your Slack access token, none of it is ever written to a workspace or handed to an agent. Every call to a connected tool goes through the integrations gateway instead, described below.
Model provider credentials are different, and deliberately so: see the next section.
The client
The desktop app (and the lighter-weight web client) is a rendering and control surface. It shows you workspaces, streams the transcript as an agent works, and lets you drive terminals, browse files, and review git diffs. It authenticates to the server as a user, and it talks directly to whichever AnyHarness runtime backs the workspace you have open, local or remote.
The client does not implement agent behavior and does not hold provider or integration credentials itself. When you connect an integration or sign in to an agent, that credential material is either kept server-side (cloud credits, connected integrations) or written straight into the runtime's own credential storage (a native CLI login), never into the client's state.
AnyHarness: the runtime
AnyHarness is the process that actually runs a session. Two things about it matter architecturally:
- One runtime per workspace target. A local checkout or worktree gets a runtime process on your machine, launched by the desktop app. A cloud workspace gets a runtime running inside its sandbox instead. The client talks to whichever one is live over the same API, which is why a workspace behaves identically regardless of where it runs.
- Durable state vs. live execution. AnyHarness keeps two kinds of state: durable records (sessions, events, workspace metadata) that survive a restart, and live execution (the actual agent subprocess, its streams, and pending permission prompts) that exists only while that process is running. This split is what lets a session resume cleanly after a restart, and it's also why a session belongs to one runtime at a time rather than floating between machines mid-task.
AnyHarness attaches the integrations gateway to every eligible session, and attaches the model gateway when that agent is authenticated through it. It never talks to a third-party tool API directly; that path always goes through the integrations gateway described below.
Moving work between local and cloud is a git operation, not a live handoff. Push the branch from one workspace and open or continue it on another; there is no way to migrate a running session between targets mid-task. See Local & cloud.
The runtime worker
Some capabilities need a machine to have its own identity with the control plane, separate from the user sitting in front of the client. That's the runtime worker: a small sidecar process that enrolls with the server, sends a periodic heartbeat, and writes a token to disk that AnyHarness reads at session launch.
The worker runs in two places: inside a cloud sandbox (started automatically alongside AnyHarness) and, optionally, on your desktop machine (for integration access from local workspaces). AnyHarness itself never sees the worker's own credential, only the narrower gateway token, and only that one token, is ever exposed to the runtime.
Two ways an agent authenticates
Not every agent talks to its model provider through a gateway, and that's intentional. Per agent, per workspace, Proliferate uses one of two materialization modes:
- Native auth. The agent signs in the same way it would on your own machine: your Claude subscription, your Codex login, your own Anthropic or OpenAI API key. That credential is written into the runtime's native credential storage, local or in the sandbox, and the agent calls the provider directly. This is the default and the common case for individual use.
- Gateway auth. The credential is Proliferate-managed: shared managed credits, a centrally stored BYOK key, or an org policy that routes everyone through one place. The next section covers how that routing actually works.
You (or your org admin) choose which applies per agent. See Models & authentication for how that choice is made.
The two gateways
Both gateways are hosted on the server. What they guarantee is different: the integrations gateway is always in the path with no bypass; the model gateway is one of the two modes above.
Model gateway. When an agent is in gateway auth mode, its LLM calls route through a gateway built on LiteLLM. The server holds the actual provider keys; AnyHarness gets a short-lived, budget-scoped virtual key instead. In Proliferate Cloud this is managed centrally with per-user and per-organization budgets; self-hosted installs can point it at their own LiteLLM proxy and provider keys.
Integrations gateway. Third-party tool calls (Linear, Notion, Slack, and others) always route through a single Cloud-hosted MCP endpoint, regardless of how the agent authenticates for models. AnyHarness advertises it to the agent as one tool source; the gateway resolves which provider is meant, attaches the right stored credential, and proxies the call. The agent, and AnyHarness, only ever see the Proliferate gateway and the worker's gateway token, never the underlying Linear API key or Notion OAuth grant.
Ownership at a glance
| Component | Owns | Never holds |
|---|---|---|
| Client (Desktop/web) | Rendering, user input, session control | Provider keys, integration credentials |
| AnyHarness (runtime) | Running the agent, sessions, terminals, files, git | Third-party integration credentials, ever; provider keys only when that agent is in gateway auth mode (native auth mode holds your own credential, same as running locally) |
| Runtime worker | Enrollment, heartbeat, handing AnyHarness its gateway token | Any product logic; it does not execute commands or materialize workspaces |
| Server (control plane) | Accounts, orgs, workspaces, billing, both gateways, all managed credentials | Nothing it doesn't already own; this is the source of truth |
Why it's split this way
Keeping the integrations gateway mandatory means a compromised or misbehaving agent session can never walk off with your Slack token or your Notion OAuth grant, no matter how that agent authenticates for models. Making the model gateway optional keeps the default path simple: bring your own subscription and it works exactly like it does outside Proliferate, with no extra credential to manage. Turn on gateway auth when you want centralized keys and budgets instead.
This split also makes self-hosting a real option: you can run the control plane and the gateways yourself and point your own client and runtimes at them, without changing how a workspace behaves day to day. See Self-hosting if that's the direction you're headed.