interagentic
The CLI for agents: an identity of its own, the services that accept it, and every other API through a proxy that holds the credentials so the agent never does.
npx interagentic <command> [options]
npm install -g interagentic
There is nothing to log into. The first command that needs an identity creates one: an Ed25519 keypair in ~/.interagentic/, a namespace registered at the broker, and tokens signed per call.
Three things it does
Call a compatible service. Any domain that publishes /.well-known/interagentic/services.json is a command tree.
npx interagentic popcorn.club
npx interagentic popcorn.club orders
npx interagentic popcorn.club orders create --qty 2
npx interagentic mongo databases create --slug my-db
Call anything else, without holding its credential.
npx interagentic curl https://api.github.com/user/repos \
-H "Authorization: Bearer {{OAUTH2_ACCESS_TOKEN}}"
The placeholder is filled in by the proxy, after a human connected the provider. The value never travels back toward the agent.
Hand work to a human when it needs one. A missing credential, an unlinked agent or a price all exit 3 with the URL to give a person.
Commands
Identity
interagentic init [namespace]
interagentic whoami
interagentic token --audience api.example.com
interagentic link --permissions orders:read,orders:write
interagentic keys list | rotate | revoke <keyId> --yes | invalidate <keyId> --yes
interagentic info [namespace]
interagentic reset
interagentic destroy --yes
$ interagentic whoami
identity interagentic://id.interagentic.dev/acme-worker
key key_V1StGXR8 · EdDSA · rotated 2h ago
human linked
Tokens last five minutes and are minted per call, with aud set to the host being called. interagentic token prints one for your own HTTP client:
curl https://api.example.com/v1/orders \
-H "Authorization: Bearer $(npx interagentic token --audience api.example.com)"
Keys rotate themselves before they go stale. keys rotate is safe to run concurrently: rotations take a lock, collapse into one, write the new key ahead of the broker call, and back off on 429. Never retry with a rotated-out key — that is exactly what makes a broker lock the namespace.
Services
interagentic <domain> [command…] [options]
interagentic services [domain]
Stopping at a group prints its children and exits 0; an unknown command prints the nearest matches and exits 2 before anything is sent. Required parameters can be positional, in the order the action declares:
interagentic popcorn.club orders refunds create ord_8fJ2 --reason damaged --amount 4.5 --notify
interagentic popcorn.club orders create 2
interagentic popcorn.club orders list --json | jq '.[].id'
interagentic deploy projects deploy --name my-site --files ./dist/
By default the CLI asks for a human-readable answer and renders markdown in the terminal; --json asks for raw JSON. --help on any action prints its parameters, types and example without calling it.
curl
interagentic curl <url> [curl options]
The flags are curl's — -X, -H, -d, --data-raw, --data-binary, --data-urlencode, --json, -F, -G, -T, -i, -I, -v, -s/-S, -o/-O, -D, -w, -f, --fail-with-body, -L, --max-redirs, --location-trusted, -m, --connect-timeout, --retry (with --retry-delay, --retry-max-time, --retry-all-errors), -A, -e, -b, -u, -r, --compressed, and the TLS and protocol flags curl accepts.
--scopes <list> | State the scopes instead of letting the proxy infer them |
--account <label> | Choose between several connected accounts |
--wait | Block until a human approves, then retry once (--wait-timeout <s>) |
Where the request goes is decided for you:
- a target that publishes
services.json with "auth": "interagentic" is called directly, with a token minted for its host;
- everything else goes through the credential proxy, which substitutes
{{PLACEHOLDER}}s as the request leaves;
- a server on this machine that speaks neither is called as it is, with no token — a hosted proxy could not reach it anyway.
Placeholders work in headers, the query string and the body. {{$name}} is different: it is an input variable, filled in from JSON piped into the command.
echo '{"id":42}' | interagentic curl https://api.example.com/items/{{$id}}
interagentic curl history
interagentic wait <approval-url>
Account
interagentic credits [ledger]
interagentic connections list | delete <name> --yes
interagentic orgs list | create | switch <org_id|me> | invite | members | role | delete
interagentic api-keys list | create | revoke <keyId> | save <iak_…>
interagentic invites create | list
interagentic dependents list | revoke <tokenId> --yes
Stable keys expire: api-keys create issues one good for 90 days, --days <n>
(up to 365) moves that. Nothing renews a key — api-keys list shows how long
each one has left.
Global options
--json | Machine-readable output; errors become { "error": { "code", "message" } } on stderr |
--broker <url> | Use a different identity broker (alias --server) |
--state-dir <path> | Use a different state directory |
--proxy-url <url> | Use a different credential proxy |
--debug | Print the requests being made, and which token went where |
--help | Help for the current command or group |
Command output goes to stdout; progress, warnings and approval notices go to stderr, so $(interagentic token) and | jq work.
Exit codes
0 | Success, including printing help for a command group |
1 | The request was made and failed |
2 | Unknown command or bad arguments — nothing was sent |
3 | A human is required; an approval URL was printed |
State on disk
~/.interagentic/ (0700)
├── identity.json broker, namespace, key id, algorithm, rotation time (0600)
├── private.pem the private key (0600)
├── private.pem.pending write-ahead log of an in-flight rotation (0600)
├── rotation.lock held while rotating
├── credentials.json a stable API key, when one is saved
├── service-auth-cache.json which hosts speak the identity protocol
└── history.json what `interagentic curl` called
Treat private.pem the way you would an SSH key. Anyone holding it can act as your agent until the key is rotated — and using a rotated-out key locks the namespace, which is the point.
Environment
INTERAGENTIC_BROKER | https://id.interagentic.dev | Identity broker (INTERAGENTIC_SERVER_URL still works) |
INTERAGENTIC_STATE_DIR | ~/.interagentic | State directory |
INTERAGENTIC_PROXY_URL | https://keychains.dev | Credential proxy for curl |
INTERAGENTIC_STABLE_API_KEY | — | A stable API key (iak_…) instead of a keypair |
INTERAGENTIC_ACT_AS | — | Act for an organization |
INTERAGENTIC_INVITE_TOKEN | — | Join via an invite on first registration |
In CI, point INTERAGENTIC_STATE_DIR inside the job's workspace so each run gets its own identity instead of sharing one key across concurrent jobs.
Development
npm --prefix ../client-sdk run build
npm run build
npm test
npm run test:e2e
The self-contained tests spawn the built CLI behind a network guard that fails any request to a host other than the local mocks.
License
MIT