Skip to content

Reference

alter agents

Manage managed-agent identities and their API keys.

A managed agent is a first-class identity for an AI workload, with its own keys and its own audit attribution. These commands manage agents and their key lifecycle.

alter agents list [--status ...] [--type ...] [--provider ...] [--search ...]
alter agents create --name <name> --scopes <json> [--display-name ...] [--type ...] [--input ...]
alter agents show --agent <agent-id>
alter agents audit --agent <agent-id> [--limit ...] [--offset ...]
alter agents registry-list [--limit ...] [--offset ...]
alter agents registry-show --agent <actor-id>
alter agents update --agent <agent-id> [--display-name ...] [--metadata ...] [--scopes <json> --expected-version <n>] [--grace-seconds <n>]
alter agents suspend --agent <agent-id> [--yes]
alter agents resume --agent <agent-id> [--yes]
alter agents revoke --agent <agent-id> [--yes]
alter agents mint-key --agent <agent-id>
alter agents list-keys --agent <agent-id>
alter agents revoke-key --agent <agent-id> --key <key-id> [--force] [--yes]
alter agents deprecate-key --agent <agent-id> --key <key-id>
alter agents undeprecate-key --agent <agent-id> --key <key-id>

All commands are app-scoped — pass --app <id> (or the app’s name), or link a workspace / set ALTER_APP_ID. Reads (list / show / list-keys) need dashboard_agents:read; create, metadata-only update, mint-key, deprecate-key, and undeprecate-key need dashboard_agents:write; scope updates, suspend, resume, revoke, and revoke-key need dashboard_agents:admin. audit needs dashboard_audit:read (it reads the audit log, not the agent registry).

FlagDefaultDescription
--status <list>allComma-separated filter: active, inactive, revoked.
--type <type>allagent or service.
--provider <provider>allAgents whose scopes include this provider.
--search <query>—Substring match on name / display name.
--limit <n>10Page size (1–10).
--offset <n>0Pagination offset.
Terminal window
alter agents list --status active --type service

Every output format emits the agent rows themselves — --output json is the rows array, matching every other list command. When more agents remain, the command prints the next --offset to run on stderr, so a | jq pipeline keeps clean data on stdout.

Paginated audit feed for one agent — the portal actions taken against it (create / update / revoke and key lifecycle), newest first. Needs dashboard_audit:read.

These are management-plane rows, so they follow the same rule as alter audit: an organization admin sees every lifecycle event, while a non-admin member sees only the ones they performed and gets a stderr notice saying so. The agent’s current configuration stays fully visible to everyone via agents show.

FlagDefaultDescription
--limit <n>50Page size (1–500).
--offset <n>0Pagination offset.
--output <format>tablejson, jsonl, or table.
Terminal window
alter agents audit --agent <agent-id> --output table

The read-only agent registry — agents seen in audit data, with activity stats (last activity, 30-day count). This is distinct from agents list / show, which manage the configured agent identities; the registry is the observability view. Both need dashboard_agents:read.

registry-list uses --limit 50 by default (range 1–200) and --offset 0. As with list and audit, every format emits the registry rows themselves (json is the array) and the next --offset prints to stderr when more remain.

Terminal window
alter agents registry-list
alter agents registry-show --agent <actor-id>

Create a managed agent. --name and a --scopes object are required unless you supply --input; input bodies must contain the same scope map. An empty object (--scopes '{}') provisions a deny-all agent that cannot reach any provider until scopes are added.

The response carries the agent’s first API key in the api_key field, shown once (mint-key returns later keys the same way). Capture it in the same pipeline so it never lands in the terminal: --output json | jq -r '.api_key'. Note the difference from app keys, where alter keys mint returns the secret as plain_key.

FlagRequiredDescription
--name <name>yesStable identifier: starts with a lowercase letter or digit, then lowercase letters, digits, -, or _ (maximum 255 characters).
--display-name <name>noHuman-readable name.
--type <type>noagent (default) or service.
--scopes <json>yesJSON object mapping provider ids to non-empty scope arrays (maximum 12 KiB compact JSON). {} is allowed and means no provider access. List managed secrets by slug under managed_secret_slugs; entries under the legacy managed_secrets key are refused.
--input <path>noJSON body from a file (@path) or stdin (-); replaces the per-field flags.

The capability allowlist is a ceiling, not a grant, and it is matched by exact string comparison. Nothing about it blocks a save: naming a provider before it is configured is legitimate, so an entry that cannot match is reported rather than rejected. When one is found, the command still exits 0 and prints a warning on stderr, leaving stdout a clean JSON object:

alter: scope warning — managed secret 'stripe-prd' does not match any active secret in this app; the allowlist entry stays inert (did you mean 'stripe-prod'?) (save was allowed)

For managed secrets, list each secret’s slug from alter managed-secrets list --app <app-id> under managed_secret_slugs, for example {"managed_secret_slugs":["stripe-production"]}. The slug is stable and unique within the app. Display names and template IDs are not capability identifiers: two secrets called “Stripe” can have different permissions, and changing a display name does not change access.

An agent created before slugs may still hold entries under the legacy managed_secrets key. Those entries match by display name, so each covers every active secret with that name. They may be kept or removed in an update, but new entries are refused with legacy_managed_secret_name_rejected. On create, any legacy entry is new, so the CLI exits with a usage error before calling the backend. On update, the CLI first reads the agent and keeps only the names its stored_legacy_managed_secret_names field lists; if that read fails (for example, the token lacks read access), the CLI sends the update and the backend’s 422 decides.

Warnings cover a provider absent from the catalog or not configured on this app, a scope the provider has not published, a * token (matched literally, so it permits nothing), a managed-secret slug no active secret carries, any entry under the legacy managed_secrets key (it matches by display name), a legacy name that several active secrets share (it permits every one of them), an allowlist that does not cover the scopes a configured provider requests (the one warning about too NARROW an allowlist — a grant carrying those scopes is denied once it takes effect), and the reserved internal sentinel __deny_all__, which is not authorable (send an empty allowlist {} to deny everything). A token without dashboard_secrets:read or dashboard_providers:read cannot run the corresponding check and is told so, rather than seeing an empty result that reads as “nothing wrong”. A very large allowlist has its advisories capped, with a trailing count of those not shown.

Terminal window
alter agents create --name nightly-sync --type service \
--display-name "Nightly Sync" \
--scopes '{"google":["openid","email"]}'
Terminal window
alter agents show --agent <agent-id>

Update labels, metadata, or the full capability allowlist. Scope changes require dashboard_agents:admin and the current version from alter agents show; this prevents a stale full-allowlist replacement from restoring access another operator removed. Broadening applies immediately; narrowing uses --grace-seconds or the 24-hour deployment default.

FlagDescription
--display-name <name>New display name.
--metadata <json>Replacement metadata object.
--scopes <json>Full provider-to-scope allowlist (maximum 12 KiB compact JSON). {} narrows to no provider access. List managed secrets by slug under managed_secret_slugs; a legacy managed_secrets entry may be kept or removed, never added (see create).
--expected-version <n>Positive version from the latest agents show response; required with --scopes.
--grace-seconds <n>Narrowing grace 0–604800; requires --scopes. Use 0 for immediate application.
Terminal window
alter agents update --agent <agent-id> --display-name "Nightly Sync (EU)"
alter agents update --agent <agent-id> \
--scopes '{"google":["openid"]}' \
--expected-version <version-from-agents-show> \
--grace-seconds 3600

A --scopes update rewrites the whole allowlist, so it reports the same allowlist warnings create does, on stderr and without blocking the save.

If the agent changes before the update commits, the command exits with a conflict. Run agents show again, reconcile the complete desired allowlist against the fresh record, and retry with its new version.

Revoke an agent. This cascade-revokes all of its keys. Revocation is recoverable — you can re-create an agent with the same scopes — so the prompt is a simple y/N (skip with --yes).

Terminal window
alter agents revoke --agent <agent-id>

Pause an agent without revoking it, then restore it later.

Terminal window
alter agents suspend --agent <agent-id>
alter agents resume --agent <agent-id>
  • suspend flips the agent to inactive. Existing keys and grants stay attached, but every call made with that agent’s key starts failing with agent_inactive — credential calls, grant listing, delegation, Connect session minting, key derivation and catalog reads alike. agent.me() keeps working for self-diagnostics, and telemetry ingestion (span emission and automatic provider-call audit reporting) keeps flowing so a suspension never blinds the audit trail.
  • resume flips the agent back to active. Any overdue pending scope narrowing applies on the next auth check or sweeper pass after resume.

Both commands prompt with y/N; pass --yes to skip the prompt.

An agent can hold several keys, which lets you rotate without downtime: mint the new key, deploy it, then revoke the old one.

Terminal window
# Mint a fresh key (plaintext shown once, in the api_key field)
alter agents mint-key --agent <agent-id>
# List every key (active / deprecated / revoked) with last-used timestamps
alter agents list-keys --agent <agent-id>
# Revoke one key
alter agents revoke-key --agent <agent-id> --key <key-id>

revoke-key accepts --force to override the last-active-key guard (leaving the agent with no active key) and --yes to skip the prompt.

Before revoking, you can deprecate a key to signal it should be retired. A deprecated key still authenticates — the backend returns an advisory deprecation header on every authenticated response, and the SDKs warn once per client on the first one, so callers can migrate first. It is fully reversible, so there is no prompt.

Terminal window
# Mark a key deprecated (still works; advisory only)
alter agents deprecate-key --agent <agent-id> --key <key-id>
# Undo it
alter agents undeprecate-key --agent <agent-id> --key <key-id>

Rotate an agent’s key without downtime

Terminal window
# 1. Mint a fresh key (printed once) and deploy it to the agent.
alter agents mint-key --agent <agent-id>
# 2. Confirm the agent is calling with the new key — check the LAST USED column.
alter agents list-keys --agent <agent-id>
# 3. Revoke the superseded key.
alter agents revoke-key --agent <agent-id> --key <old-key-id>

Report an issue with this page

Necessary

Required for sign-in, security, authorization, and remembering your choices.

Always active

Analytics

Helps us understand which product and documentation features are useful.

Performance diagnostics

Uses performance tracing and privacy-masked session replay to diagnose problems.

You can change these choices at any time from Cookie settings.