security
Your keys, your machines, your rules.
Brio runs agents that write code, spend money and touch your repositories, so every part of it is built to fail closed: nothing runs outside a sandbox, nothing is spent past a budget, nothing irreversible happens without a person, and everything is on the record.
01 · Official routes only
No scraping, no borrowed sign-ins.
Brio reaches AI vendors only through the channels they publish for programmatic use. This is a hard rule in the code, not a setting: adapters for the routes on the right must not exist.
| allowed | never |
|---|---|
| Official APIs with your own keys | Driving consumer chat apps: chatgpt.com, claude.ai, gemini.google.com, grok.com |
| Official CLIs, run with their documented headless flags | Reading or reusing the sign-in tokens any CLI or app stored |
| Official SDKs and hosted agent APIs | Unofficial or reverse-engineered APIs |
| A2A agents and MCP servers you add | Bypassing CAPTCHAs or bot detection in browser agents |
Using a subscription (rather than an API key) is possible only on your own machine, through the local runner, where the vendor's own CLI runs under your own sign-in, and only for vendors whose terms allow it: Antigravity, and Claude Code for your own work. Each vendor's terms are recorded in the registry.
02 · Where things run
No Brio cloud. No account with us.
Brio is self-hosted. Your data stays in your Postgres; the only calls that leave your machines go to the vendors you connected, with your keys, billed to you directly.
You
- the web app
- brio CLI
- Claude Code, Cursor (MCP)
- any A2A agent
Your Brio
- API and orchestrator
- Postgres
- the key vault
- the audit ledger
Your runners
- a Docker sandbox per attempt
- or your laptop, under your sign-ins
Vendors you chose
- called with your keys
- billed to you directly
03 · The vault
Keys are sealed, used once, and never shown again.
Bring your own keys. Each one is envelope-encrypted and decrypted only inside the runner, for the attempt that needs it.
- 01
you
paste a vendor key once
- 02
vault
a fresh data key encrypts it (XChaCha20-Poly1305)
- 03
KEK
the data key is wrapped by a master key (KMS or a key file)
- 04
database
only ciphertext is stored; the key is never shown again
- 05
runner
unwrapped in memory for one attempt, sent as a header
- 06
after
zeroed; logs and events are redacted
- every logger and event writer runs a redactor: known secret values plus patterns (sk-, xai-, bearer tokens, cloud keys)
- secrets never go into prompts, handoff packets, memory or artifacts
- an output that contains a secret is quarantined
- the master key comes from a KMS or a key file, and can be rotated
- connectors show whether a key works, never the key
- a contract test asserts that no secret leaks into logs or events
04 · Sandboxes
One container per attempt, deny by default.
Agents that run code never run on the API's host. Each attempt gets its own container, its own worktree, its own limits and an allowlist of hosts it may reach.
runner host · Docker
container · one per attempt
- non-root user, no capabilities
- read-only base image
- writable: the worktree and /tmp only
- no Docker socket, no host mounts
- CPU, memory, disk and PID limits
- a wall-clock limit, then killed
.brio/brief.md · .brio/contract.json · .brio/handoff.json
egress: default deny, through a proxy
Outbound requests to addresses people type in (a model endpoint, an A2A agent) are checked inside the connection's own DNS lookup, so a name cannot be re-pointed at a private address between the check and the call. Private addresses are refused unless an operator allows them.
05 · Local runners
Your laptop connects out; nothing connects in.
A local runner opens one connection to your Brio with a token that is shown once, stored hashed and revocable. It holds no database credentials and never receives a vault key.
Docker by default
Host mode is opt-in
Only your own work
06 · Data policies
Confidential work goes only where you allow.
Every task carries a sensitivity: public, internal or confidential. Policies map each to the connectors it may reach.
- with no policy, confidential work goes only to local models
- connector allow and deny lists apply to everything; deny wins
- network policies widen or narrow a sandbox's allowlist
- policy changes are entries in the ledger
Checked twice
The planner, the router and the choice of reviewer all filter by the same policy engine, and dispatch checks again. A pinned or hand-picked agent cannot slip past: violations are impossible, not merely warned about.
07 · Budgets
Checked before you spend, not after the bill.
Monthly limits per workspace and per agent, and each mission's and task's own budget. Spend is the live cost of running attempts, so work in flight counts.
before
every scope that applies must have room; the attempt's cap becomes what is left
80%
a budget.warn event, once per period, and a notification
100%
budget.stop: the attempt is cancelled within seconds
after
the task waits, blocked, until a person raises the budget
Already using Mandate to govern agents' spending? Connect it, and every paid attempt also asks Mandate for a hold after Brio's own budgets pass. A decline, or an unreachable Mandate, blocks the task.
08 · Approvals
Irreversible actions wait for a person.
Pushes, deploys, sends and purchases need a yes, by policy. You decide in the app, by email, by push, in Slack, or from your editor over MCP.
| action | default |
|---|---|
| approve a plan | required if it costs more than $5 or has more than 10 tasks |
| push a branch / open a pull request | required; a person decides, never an API token |
| deploy, publish, send email or a message, purchase | required, per action |
| a browser agent visiting a new domain | required |
| spend over the mission's budget | required |
| delete files outside the task's footprint | always denied |
A Slack button counts only with a valid signature less than five minutes old, from an account whose email is a member of the workspace. MCP clients decide only with a scope a person grants on the consent page.
09 · Roles
Spending power apart from day-to-day work.
Owners and admins administer; members act; viewers read. A workspace always keeps an owner, and every role change is in the ledger.
| owner | admin | member | viewer | |
|---|---|---|---|---|
| read missions, boards, scores, memory | ✓ | ✓ | ✓ | ✓ |
| start missions, edit plans, run agents, approve | ✓ | ✓ | ✓ | |
| connectors, budgets, policies, ledger, Slack | ✓ | ✓ | ||
| make owners and admins; delete the workspace | ✓ |
10 · Prompt injection
Other agents' words are data, never instructions.
Handoffs, attachments, issue text, other agents' messages, project memory, check output and results under review all reach a prompt only inside a labelled, fenced block that the text cannot close from inside.
Every result is scanned for
- attempts to override instructions
- chat role markers and jailbreak personas
- requests to send secrets
- notes addressed to the AI reading this
- hidden Unicode
- piping a download into a shell
# a result that tries it
research-agent → t2 · report written
brio → injection_scan · held for a person
“ignore your previous instructions and…” at line 41
you → reviewed · passed on, quoted
A finding holds the result for you instead of failing it, so legitimate security work is not lost.
11 · The ledger
An audit trail that proves it was not edited.
Dispatches, spend, approvals, external side effects, policy changes, key changes, memory edits and role changes are entries in an append-only, hash-chained ledger.
seq 41
dispatch
codex → t3
prev 3a8e…c4
hash 9f2c…a1
seq 42
spend
$0.31 · t3
prev 9f2c…a1
hash 4be0…7d
seq 43
approval
PR #42 · approved
prev 4be0…7d
hash c71a…02
seq 44
side effect
pushed brio/health
prev c71a…02
hash e5d9…3f
Written with the action
An entry is written in the same transaction as what it records.
Verifiable
Owners and admins verify the chain; the first broken entry is named.
Exportable
As JSONL or CSV, to keep chain heads somewhere else.
12 · Accounts
Only the people you choose get in.
Sign in with an emailed link, Google or a passkey. On a server anyone can reach, one setting decides who may create an account.
A sign-up allowlist
Single-use links
API tokens with limits
13 · The review
Reviewed, with the findings published.
Before release, Brio had a security review with a written threat model. Every finding, what was fixed and what remains, is in the repository.
Found a vulnerability? Please tell the maintainer privately before opening a public issue: the owner of the repository is listed on GitHub.
Safe by default, on your own machines.
Run Brio where you control the data, with the keys you already have.