Skip to main content
OneCLI runs an agent per person. Each agent lives in its own sandbox, and the only way out is the gateway, which checks every request against your policy and injects the credentials granted to that agent. The control plane, the runner, and the gateway are separate services, so agents can run on a laptop, a homelab, or a VPC behind NAT with no ingress and no tunnel.

Architecture overview

OneCLI architecture
  • Web Dashboard: Next.js app. Create agents, chat with them, edit their memory and skills, manage connections, secrets, and grants.
  • API Server: the control plane. Owns the database, the conversation plane, and the work queue the runner polls.
  • Rust Gateway: intercepts outbound requests (HTTPS included, via MITM) and injects credentials. Agents authenticate with access tokens via Proxy-Authorization headers.
  • Runner: starts, parks, and reaps agent sandboxes. Outbound-only, and never touches the database.
  • Sandbox Supervisor: runs inside each sandbox, speaking a vendor-neutral harness interface so the agent runtime is swappable.
  • Channel Adapter: the Slack daemon, posting answers, mirrors, and approval cards.
  • Secret Store: AES-256-GCM at rest, decrypted only at request time, matched by host and path pattern, injected as headers or query parameters.

The agent lifecycle

  1. You create an agent and grant it a model key plus the connections it needs.
  2. A message (from the dashboard, Slack, or a schedule) queues a turn on the API server’s work queue.
  3. The runner, polling outbound-only, picks up the turn and boots or wakes the agent’s sandbox. The sandbox has a durable workspace volume that survives park and wake.
  4. The agent works: shell, filesystem, and HTTP, with every outbound request forced through the gateway.
  5. Actions matching an approval rule pause and render an Approve/Deny card in the chat (dashboard or Slack). The decision is deterministic: nothing executes until a human decides, and expiry denies.
  6. The answer lands back in the conversation. What the agent learned persists in its platform-kept memory, and idle sandboxes are parked to free resources.

The gateway

Every outbound request from a sandbox (and from any connected external agent) passes through the Rust gateway:
  1. The agent makes a normal HTTP request (e.g., GET https://www.googleapis.com/calendar/v3/events)
  2. The gateway evaluates policy: organization rules plus the agent’s own grants. Blocked or rate-limited requests get a 403 or 429 immediately
  3. Approval-gated requests pause for a human decision
  4. If allowed, the gateway matches the target host and path against the credentials granted to that agent, decrypts the match, and injects it as a header (e.g. Authorization: Bearer ...) or query parameter. A credential the agent has no grant for is never considered
  5. The request is forwarded with credentials attached, and the response passes back unchanged
Policy is evaluated before credential injection, so a blocked request never decrypts or touches your secrets.

Policy engine

Rules are evaluated top-down, first match wins. Each rule pairs identities (which agents or people) with targets (an app and its tools, a connection, a secret, or a network pattern) and applies an action:
  • Block: deny the request entirely (403)
  • Allow: permit it, optionally requiring human approval, or rate-limited to N requests per window (429 beyond the cap)
Two layers feed the engine: organization rules (guardrails no workspace can loosen) and agent grants (per-agent access, compiled into rules automatically when you grant a connection). A request is allowed only when both layers permit it.

Channels

Slack is the first provider of the channels layer. An agent can join via the shared OneCLI app (one Slack app for the whole deployment, instant attach, each agent answering as its own persona) or as a dedicated app per agent (its own bot user and DM entry). A user’s DM with an agent is their web thread: one conversation, two doors. Gateway approvals show up as Slack cards with Approve/Deny buttons.

Connecting your own agents

The same gateway serves agents you already run:

Stack

Project structure