Docs

API keys

Give each agent a key that can do only its job.

For your agent

agental.io/docs/api-keys.md

A key is made with what it may do: a preset, or actions named. It can also be limited to some sandboxes or templates, to a last day, and to the addresses it may be used from. A key keeps what it was made with. Only its addresses can be changed afterwards.

Make a key

POST/v1/api-keys
curl -X POST https://agental.io/v1/api-keys \
  -H "Authorization: Bearer $AGENTAL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"ci-github","preset":"ci","templateIds":["tpl_coding_agent"],"expiresAt":"2026-11-15T00:00:00Z","allowFrom":["203.0.113.0/24","2001:db8::/48"]}'
FieldWhat it does
nameRequired. Unique in the account.
presetOne of the four sets below. Send this or actions, not both: neither is 400. A key that can do everything is asked for with "preset": "admin".
actionsThe actions it may do, named.
sandboxIds, templateIdsThe sandboxes it reaches, and the templates it reaches with every sandbox on them. Left out, all of the account's.
expiresAtWhen it stops working. Left out, never.
allowFromIPv4 and IPv6 addresses and ranges it may be used from, 100 at most. Left out, anywhere.

The answer has the key's secret. It is shown this once, and only its hash is kept.

Presets

PresetActions
read-onlyEvery read but secrets and mail: sandbox.read, file.read, snapshot.read, template.read, account.read.
full-sandboxWork in sandboxes that are there: sandbox.read, sandbox.auto-stop, exec, file.read, file.write, agent.prompt, ssh, desktop, host, snapshot.read, snapshot.write, sandbox.stop. It makes and deletes none, and touches no outbound rule, secret or account setting.
cifull-sandbox, and sandbox.create, sandbox.fork, sandbox.resume and sandbox.delete-own.
admin*: everything a key can do.

A preset is written out into its actions when the key is made. An action added to agental later is not given to keys made before it.

Actions

ActionWhat it allows
sandbox.readList and read sandboxes, their operations, stops, usage, metrics, template and outbound rule, and the sizes.
sandbox.createMake sandboxes, and reconcile creates whose outcome was not known.
sandbox.forkFork a sandbox.
sandbox.updateRename a sandbox, share it, put it on another template, take its time limit away.
sandbox.auto-stopRead and move when a running sandbox is to be stopped.
sandbox.stopStop and archive.
sandbox.resumeStart, resume and recover.
sandbox.deleteDelete any sandbox it reaches.
sandbox.delete-ownDelete only the sandboxes this key made.
execRun commands.
file.read, file.writeRead and write a sandbox's files. Artifacts are read.
agent.promptPrompt the agent in a sandbox, steer and interrupt it, read its conversations and events.
sshSSH on and off, and the keys let in.
desktopThe desktop and the browser: turn them on and off, and drive them.
hostPublic addresses for a sandbox's ports.
network.writeChange the outbound rule of a sandbox or a template.
secret.read, secret.writeRead, set and delete the secret variables and files of sandboxes and templates.
email.read, email.send, email.manageRead a sandbox's mail; send it; turn it on and off and delete messages.
snapshot.read, snapshot.writeList and read snapshots; take, delete and restore them.
template.read, template.writeTemplates, other than their secrets and the change of their outbound rule. Applying counts as a change.
key.manageEverything under /v1/api-keys.
account.readThe account: who it is, usage, limits, bursts, billing, webhooks, telemetry, data retention, metrics, repositories, invites, organizations, its mail.
account.adminChanges to all of those, billing checkout and portal, inviting, and the account's export.
members.read, members.adminA team's members and invites: list them; invite, revoke invites, change roles and remove members. A key with account.read or account.admin may too.
*Everything a key can do.
  • network.write and secret.read are actions of their own, so that an agent's key cannot lift its own outbound block or read its template's secrets.
  • account.read and account.admin are about the account as a whole. A key limited to some sandboxes that holds account.read still reads the whole account's usage and metrics, which name every sandbox: leave it out of a key you limit.
  • Whatever its actions, no key reaches what is for whoever runs the service, nor what only a person signed in may do: allowing the agental command to sign in, and closing, reopening or erasing the account.

Keys in a team

A key acts in the organization it was made in, for good: your own, or the team you were acting in when you made it. What it makes is that organization's, and it reaches nothing of any other. GET /v1/me says which in activeOrganizationId.

  • A team's owners and admins see and revoke every key of the team, with createdBy saying who made each. A member sees and revokes their own.
  • What a key may do in a team is held by its actions and by its person's role there, read on each request: a member's key with members.admin still removes no one but its person.
  • When someone is removed from a team, the keys they made in it go on working, as a member's, until they are revoked. Removing them with ?revokeKeys=true revokes those keys in the same request, and the console's Remove offers it.
  • Deleting a team and accepting an invite are for a person signed in. A key cannot.
bash
agental org
agental org use Acme
agental members
agental members remove [email protected] --revoke-keys
agental invite [email protected] --role admin

agental org use signs the command in again, in the browser, for a key made in that organization, and deletes the key it had.

Limit it to some sandboxes or templates

With sandboxIds, templateIds or both, a key reaches the sandboxes listed, the templates listed with every sandbox on them, and always the sandboxes and templates it made itself. Everything else of the account answers it 404 not_found, word for word as another account's would, and lists leave it out: sandboxes, snapshots, templates and ports.

  • A key limited by sandboxIds alone is not limited in templates.
  • A sandbox that a key limited to templates makes without naming one goes on the default template when that is on its list, otherwise on the one template on its list. With several on its list and not default, it has to send templateId, and is told 400 template_required.
  • For a key used inside a sandbox, list that sandbox: it is the limit that holds wherever the sandbox runs.

Limit where it may be used from

allowFrom takes addresses, 198.51.100.7, and ranges, 203.0.113.0/24 or 2001:db8::/48. A request from anywhere else is refused with 403 key_address_forbidden, and the message says which address agental saw. An IPv4 address written the IPv6 way, ::ffff:203.0.113.7, is that IPv4 address.

PUT/v1/api-keys/{id}/allow-from
curl -X PUT https://agental.io/v1/api-keys/key_38b536dc2eabdb52/allow-from \
  -H "Authorization: Bearer $AGENTAL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"allowFrom":["203.0.113.0/24"]}'

It replaces the list, from the key's next request. An empty list is anywhere. It is the one change a key takes.

While your account has two-factor sign-in on, a list that lets the key be used from more places, with an address outside the old list or no list at all, takes a code when a person signed in sends it, as a new key does. A list that only narrows it needs none.

WarningA sandbox reaches agental from its server's shared public IPv4 address, and that changes when the sandbox moves to another server. Address limits are for keys used outside agental. Limit a key used inside a sandbox with sandboxIds.
WarningOn a network with IPv6, agental sees your IPv6 address, not your IPv4 one. A list of IPv4 addresses alone will refuse you there: add your IPv6 range too.

A key makes only weaker keys

A key with key.manage may make keys, and may change their addresses, but never past itself:

  • no action it was not made with;
  • no sandbox or template it does not reach, and a list whenever it has one;
  • no later last day, and one whenever it has one;
  • addresses inside its own, whenever it has some. That holds for a key changing its own list too: it can narrow it, never widen it.

Anything stronger is refused with 403 key_exceeds_caller, and the message says what.

With two-factor sign-in on

A key outlives the session that made it, so while your account has two-factor sign-in on, a key made in the console asks for a code: the six digits your authenticator app shows now, or a backup code. Signed in to the site, the call sends it as code. Without one it is refused with 400 code_required, a wrong one with 400 invalid_code, and after five wrong codes in a quarter of an hour that session waits (429). A key made with a key needs no code: that key was made behind one.

Read your keys

GET/v1/api-keys
curl -X GET https://agental.io/v1/api-keys \
  -H "Authorization: Bearer $AGENTAL_API_KEY"

Each key says what it may do and where, lastUsedAt and lastUsedFrom: when it was last used, and from which address. Those are written once a minute at most, so a key in use shows the minute. GET /v1/api-keys/{id} reads one, and DELETE deletes it: whatever holds it is refused from its next request, and the sandboxes it made stay yours.

When a key is refused

A request with a key is checked in this order, and stops at the first that fails:

AnswerWhy
1401 unauthorizedThere is no such key, or it was deleted.
2401 key_expiredIts last day has passed.
3403 key_address_forbiddenIt came from an address the key may not be used from. The message names it.
4403 key_action_forbiddenThe key was not made with the action the call takes. The message names it. A route no action covers is refused to every key.
5404 not_foundA sandbox, template, snapshot or port the key does not reach.

The full machine-readable reference is OpenAPI 3.1. Every page as Markdown, for an agent: llms.txt. Questions: [email protected]