Docs

Security model

What API keys grant, what a connected agent can do on your machine, and how to limit blast radius.

Convoy's pitch — "the web UI runs an AI agent on your machine" — deserves a clear trust model. This page describes what each credential and process can actually do, and the practical ways to contain it.

API keys

  • Keys are user-scoped: they act on behalf of the user who created them and inherit exactly that user's organization and project permissions. There is no separate key permission model and no way for a key to grant more than its owner has.
  • Permission checks are enforced by the backend on every query and mutation, not by the client.
  • Rotate keys when a machine is lost or a secret leaks; create separate keys per machine so revocation is targeted.

Keys live in ~/.config/convoy/config.toml (directory created with mode 0700) and inside generated MCP config files. Generated MCP config embeds your API key — before committing project-scoped config such as .mcp.json or .codex/config.toml, verify the file is ignored by version control.

Model provider keys

Bedrock and Mantle credentials managed by convoy keys are a separate credential type. They are stored only in the local config.toml, assigned to profiles, and injected into Claude Code processes. They are never registered with or synchronized to the Convoy backend.

See Model provider keys for setup, assignment, and removal.

What a connected CLI session can do

convoy connect registers one session for one profile. That session:

  • claims and executes threads only for the profile's project
  • runs the agent runtime (Claude Code, Codex, or OpenCode) in the profile's local working directory
  • streams the agent's output back to Convex

The agent subprocess runs as your local user. By default it has the same filesystem and network access as running claude in that directory yourself — the runtime's own permission settings are the enforcement layer for what it may touch locally (Claude Code's permission modes; Codex's OS sandbox flags; OpenCode's session permission rulesets, where Agent mode auto-allows all tools and "Ask to approve" routes each request to the thread for approval). Opting into --isolated adds an OS-level sandbox generated from the profile's paths, so agents cannot write outside the granted folders (Claude Code and Codex).

The trust boundary is project membership

Anyone who can send a thread message in the project can drive the agent on the connected machine. Before connecting a profile, the question to ask is: do I trust everyone with access to this project to type into a terminal on this machine, mediated by an AI agent?

Practical consequences:

  • only connect profiles for projects whose membership you trust
  • prefer a dedicated checkout or worktree as the profile path, rather than a directory with unrelated secrets
  • enable --isolated (or isolated = true on the profile) so agents are OS-sandboxed to the profile's folders
  • for stronger isolation, run the bridge inside the dev container — container-local dependencies, and a strict network mode that blocks outbound traffic except an allowlist — or pick another boundary from isolation options

What leaves your machine

While a thread runs, the CLI streams the agent's events — assistant text, reasoning, tool calls, and tool output — to the Convex backend, where they are stored durably and rendered for everyone with access to the project. If the agent reads a sensitive file and prints it, that content is now in the thread.

Thread file attachments are cached locally under ~/.cache/convoy/thread-attachments (cleaned up after 7 days).

MCP exposure

The MCP server exposes task and project data scoped by the API key's user. It does not execute code on anyone's machine — MCP risk is the standard "this client can read and write my tasks" surface, plus the embedded key in config files described above.

On this page