Guides
Agents and tokens
Give a coding agent a key of its own, narrow it with scopes or an agent class, connect a hosted client through OAuth, and read the audit of what the agent did.
A coding agent works on Rytiv with an API key like any other client. What sets its key apart is that you hand it over without watching every request, so the platform, not the agent, has to know what the key is meant for. Rytiv gives you three tools for that: scopes, agent tokens with a class, and an audit of every judged request.
One key per agent
Section titled “One key per agent”Create a key for each agent and name it after the agent. A key is shown once; store it where the agent reads it (RYTIV_TOKEN, a .mcp.json with ${RYTIV_TOKEN}, your CI’s secret store).
ry tokens create claude-code --agent sandbox --app web --app web-trycurl -X POST "https://api.rytiv.app/v1/tokens" \ -H "Authorization: Bearer $RYTIV_TOKEN" \ -H "Content-Type: application/json" \ -d '{"name": "claude-code", "agent": {"class": "sandbox", "apps": ["web", "web-try"]}}'const res = await fetch("https://api.rytiv.app/v1/tokens", { method: "POST", headers: { Authorization: `Bearer ${process.env.RYTIV_TOKEN}`, "Content-Type": "application/json" }, body: JSON.stringify({ name: "claude-code", agent: { class: "sandbox", apps: ["web", "web-try"] } }),});const { token } = await res.json(); // shown in this answer onlyimport os, requests
res = requests.post( "https://api.rytiv.app/v1/tokens", headers={"Authorization": f"Bearer {os.environ['RYTIV_TOKEN']}"}, json={"name": "claude-code", "agent": {"class": "sandbox", "apps": ["web", "web-try"]}},)token = res.json()["token"] # shown in this answer onlyCreating a key needs a key with full access; your first one comes from the console or from ry login.
Agent tokens: a class and a list of apps
Section titled “Agent tokens: a class and a list of apps”An agent block makes the key an agent token. The platform enforces two facts about it on every request:
| Class | What the agent may do |
|---|---|
sandbox |
Everything an API key may do, inside the apps on its list. For trying things out. |
twin |
The same, for a per-task copy of production: a preview app, a database branch, a computer. |
production |
Read only. Status, releases and logs are open; what production holds (files, a shell, query results) needs prodDataRead: true on the token. Any change is refused with agent-token-production-readonly. |
apps names the apps the token may touch; a request about another app, or about something that is not an app (a bucket, a volume), is refused with agent-token-app-scope. Without the list, the token reaches the whole organization.
Whatever the class, an agent token can never mint, reveal or revoke a credential, administer the organization, or act for another organization (agent-token-credential, agent-token-delegation). An agent that is told “this is production, only read” by its prompt is one injected sentence away from forgetting it; the token does not forget.
With ry tokens create: --agent <class>, --app <name> (repeatable) and --read-prod-data.
Scopes: less than full access
Section titled “Scopes: less than full access”Scopes narrow a key the way a CI job or a partner needs it. A key without scopes is the whole organization; a key with scopes can only do less.
| Scope | Allows |
|---|---|
read |
Every read of the product API that is a status: apps, machines, deploys, databases, buckets, domains, schedules, webhooks. Not credentials, not billing, not the files of a machine. |
deploy |
The deploy routes of every app: build, deploy, releases, rollback, logs, machines, secrets. Never creating or deleting an app, never a key. |
deploy:<app> |
The same for exactly that app. The app list shows only the apps the key may deploy. |
mail:send |
Sending mail from any proven domain of the organization. |
mail:send:<domain> |
Sending from exactly that domain. |
ry tokens create ci-web --deploy web --expires-in 30dry tokens create status-page --scope readA scoped key cannot open a shell, a tunnel or the console of a machine; those need full access. A route the scope does not cover answers 403 with token-scope and names the scope needed. Scopes and an agent class combine; the narrower rule wins.
Expiry
Section titled “Expiry”A key may stop working at a moment (expiresAt) or after a duration (ttlSeconds, in the CLI --expires-in 12h or --expires-at 2027-01-31T00:00:00Z): at least 60 seconds and at most 365 days ahead. A key with an expiry cannot create a key that outlives it; without an explicit expiry, the new key inherits the creator’s.
ry tokens listry tokens revoke tok-1a2b3c4dRevoking a key rejects requests already using it right away.
Connect a hosted client with OAuth
Section titled “Connect a hosted client with OAuth”A client that has no place for a pasted key (a hosted connector) connects to the MCP server through OAuth 2.1:
POST https://api.rytiv.app/v1/mcpwithout a key answers401with aWWW-Authenticateheader that names the discovery document/.well-known/oauth-protected-resource/v1/mcp.- The client reads
/.well-known/oauth-authorization-server, registers itself atPOST /v1/oauth/register(no client secret; every client is a public client bound to PKCE), and sends you toGET /v1/oauth/authorize. - You land on
https://console.rytiv.com/connect, signed in, and approve the client for the active team. - The client exchanges its code at
POST /v1/oauth/tokenand receives an access token (valid 1 hour) and a refresh token (30 days, renewed on use).
The access token is an ordinary key of the organization, named after the client, and appears under Team, Tokens & keys in the console, where you revoke it. Scopes of the OAuth server: mcp and offline_access.
In Claude Code, Codex and Cursor you do not need OAuth: add the server with your key as a bearer header, see the quickstart.
Read what the agent did
Section titled “Read what the agent did”Every request judged for an agent token is recorded: the route, the verdict, the token.
curl "https://api.rytiv.app/v1/agent-actions?limit=100" \ -H "Authorization: Bearer $RYTIV_TOKEN"?token=<id> narrows the list to one key. Reading the audit needs a key with full access.
Confirmations
Section titled “Confirmations”A change in production by an agent waits for a person. The console carries the page for it (/confirm/<id>), and the platform refuses the change until the confirmation exists; in this release the refusal stands, and the person makes the change with their own key or in the console. See Confirmations.