Vault
Store credentials as encrypted connections that B3OS injects into outbound requests at the egress proxy, so agents use them without ever seeing them.
The vault holds your credentials as connections (conn_). A connection's secret is written once and never returned. When an action, a routine step or a sandbox's action call needs it, the node's egress proxy adds it to the outgoing request, and only for the hosts the connection is bound to. Used that way, your agent, the model, pack code and logs never see the value. The one exception is a value you choose to hand over: a sandbox's secrets can place a connection's field in an environment variable, where code in that sandbox can read it (see use a connection).
Secrets are encrypted at rest with AES-256-GCM, under a key per organization that is itself wrapped by the node's master key.
Store a connection
bashcurl -s https://beta-api.b3os.org/v1/vault/connections \ -H "Authorization: Bearer $B3OS_API_KEY" \ -H "Content-Type: application/json" \ -d '{"pack": "io.b3os/github", "key": "api", "label": "CI bot token", "secret": {"token": "<github token>"}}'
tsimport { B3OS } from "@b3os/sdk";const b3os = new B3OS();const connection = await b3os.vault.createConnection({ pack: "io.b3os/github", key: "api", label: "CI bot token", secret: { token: process.env.GITHUB_TOKEN! },});console.log(connection.id, connection.hosts, connection.secret_fields);
pythonimport osfrom b3os import B3OSb3os = B3OS()connection = b3os.vault.create_connection({ "pack": "io.b3os/github", "key": "api", "label": "CI bot token", "secret": {"token": os.environ["GITHUB_TOKEN"]},})print(connection["id"], connection["hosts"], connection["secret_fields"])
Store credentials from your own code or the dashboard, not through an agent: a secret typed into a chat ends up in the model's context. Agents then use connections by ID without seeing them.
The response shows the connection's type, bound hosts and the names of its stored secret fields, never the values. Creating connections needs vault:write, which the default key does not have; create a key with it in the dashboard.
Three kinds of connection
| Kind | Give | Injected into |
|---|---|---|
| For a pack | pack and key, the connection key in the pack's manifest | Requests to the hosts the pack declares for that key |
| Custom | type and hosts (exact names or *. wildcards, up to 8) | Requests to those hosts |
| Verification only | type and no hosts | Nothing, ever. B3OS reads it itself, for example to check a routine webhook's signature. |
subject stores one credential per end user of yours, so you can keep a connection for each of your customers and filter by it.
Secret fields by type
type | secret fields | Injected as |
|---|---|---|
api_key | api_key | Wherever the pack's inject says |
bearer | token | Authorization: Bearer <token> |
basic | username, password | Authorization: Basic ... |
oauth2 | access_token, and optionally refresh_token, expires_at, client_id, client_secret | Authorization: Bearer <access_token> |
none | none | Nothing |
In v0.1 you bring OAuth tokens you obtained yourself; hosted consent links for OAuth providers are planned. An OAuth connection whose access token expired and could not be refreshed has status: expired.
Use a connection
- Action calls name it in
connections, keyed by the action's connection key; see calling actions. - Routine steps bind it under the step's
connections. - Sandboxes list it in
api.connections, so their action calls may use it, or place one of its fields in an environment variable withsecrets. The environment variable puts the value inside the sandbox, where its code can read it; prefer action calls, which keep it at the proxy. See agents in sandboxes.
Naming a connection takes vault:run on top of the operation's own scope.
Rotate and delete
PATCH /v1/vault/connections/{connection_id} with a new secret replaces all its fields at once: calls in flight finish with the old value and new calls use the new one. It can also change the label, subject, params and, for custom connections, the hosts. DELETE removes the connection and its secret; routine steps that bind it then fail with connection_required, and sandboxes granted it lose access.
Scopes
| Scope | For |
|---|---|
vault:write | Create, update and delete connections |
vault:read | List and read connection metadata; values are never returned |
vault:run | Use connections in action calls and routine steps |
A sandbox's grant gets vault scopes only when it names them exactly. Limits and FAQ has the caps.