Agent access tokens for external harnesses
An agent that runs on its own harness, such as an in-house agent loop on a schedule, often needs to call an API or MCP server that requires a named principal. Runtype issues that agent a short-lived OAuth access token. The token names the agent as its subject and is valid only for one resource that you allow. No person takes part in the request, and the agent never borrows a user’s API key.
This guide shows how to allow a resource, give the agent a credential, request a token with curl, and verify the token in your API.
Agent access tokens are enabled per organization. If the token endpoint returns
unauthorized_client with the description “Agent tokens are not available for this
organization”, contact Runtype support to enable them.
Before you begin
Complete the following before the agent requests a token:
- Register the harness as an external agent. See Bring your own agent.
- Only an organization admin can create or revoke the agent’s credentials and change its policy. With an API key, the key needs the
AGENTS:WRITEpermission and must belong to an organization admin. Reading them needsAGENTS:READ. - Find the canonical resource URI of each API the agent calls. The canonical form uses
https, a lowercase host, no default port, no query, no fragment, and no trailing slash, for examplehttps://mcp.example.com/mcp.
How agent tokens work
The agent authenticates to the token endpoint as an OAuth client and names the resource it wants to call:
- You list the resource in the agent’s audience policy, with the scopes a token may carry.
- You give the agent a credential: a registered public key (recommended) or a client secret.
- The agent sends a
client_credentialsrequest tohttps://api.runtype.com/v1/identity/tokenwith theresourceparameter. - Runtype checks the credential and the policy, records the issuance in your organization’s audit log, and returns an access token that lives at most 300 seconds.
- The agent sends the token to your API as a bearer token. Your API verifies it with Runtype’s public keys.
The agent’s client ID is its agent ID. A credential revocation or a policy change applies to the next token request.
Allow a resource in the audience policy
The audience policy lists every resource the agent may get tokens for. Replace the whole policy with one request:
Replace the following:
YOUR_AGENT_ID: the ID of the external agent, which starts withagent_.YOUR_API_KEY: a Runtype API key, owned by an organization admin, with theAGENTS:WRITEpermission.
The fields of each entry are:
Each change increases the policy’s policyRevision and is recorded with you as the actor. To avoid overwriting a teammate’s change, send expectedPolicyRevision; the request fails with 409 if the policy changed after you read it.
Get a token with a client secret
A client secret is the shortest path for curl, low-code tools, and scripts. The secret starts with rt_agent_sk_ so secret scanners can flag a leak.
-
Create a secret:
Create a client secretThe response contains
clientIdandclientSecret. Store the secret in the harness’s secret manager. Runtype shows it only once and stores only its hash. A secret expires after at most 365 days. -
Request a token with HTTP Basic authentication:
Request a token with a client secretReplace
YOUR_CLIENT_SECRETwith thert_agent_sk_secret. To send the credentials in the body instead, passclient_idandclient_secretas form fields.
The response is a standard OAuth token response:
An agent can hold two active secrets. To rotate without downtime, create a second secret, switch the harness to it, and then revoke the first one.
Get a token with private_key_jwt
With private_key_jwt, the private key stays with the harness and no reusable secret crosses the network. Runtype accepts EC (ES256, ES384), RSA (RS256 to RS512, PS256 to PS512, 2048 bits or more), and Ed25519 (EdDSA) keys.
-
Register the public key. Send only the public JWK; Runtype refuses symmetric keys and any JWK with private members:
Register a public keyReplace
YOUR_KEY_XandYOUR_KEY_Ywith the public coordinates of your key. If you leave outkid, Runtype uses the key’s RFC 7638 thumbprint. -
Sign a client assertion for each token request. The following Node.js example uses the
joselibrary:Sign a client assertionReplace
YOUR_ORGANIZATION_IDwith the ID of the Runtype organization that owns the agent. -
Request a token with the assertion:
Request a token with private_key_jwt
Runtype refuses an assertion unless all of the following are true:
issandsubboth equal the agent ID.audis a single string equal to the organization’s agents issuer,https://api.runtype.com/orgs/YOUR_ORGANIZATION_ID/agents, or its organization issuer,https://api.runtype.com/orgs/YOUR_ORGANIZATION_ID. An array is refused.- The header
algmatches the registered key, andkid, when present, names it. jtiis present and has not been used before. Each assertion works once.expminusiatis at most 300 seconds, and the assertion has not expired.- The
typheader, when present, isclient-authentication+jwtorJWT.
An organization admin can turn on the requireAgentPrivateKeyJwt organization setting. The token endpoint then refuses client secrets for every agent in the organization with invalid_client.
Manage credentials
Use the following endpoints to see and retire an agent’s credentials:
GET /v1/agents/YOUR_AGENT_ID/credentialslists every key and secret with itsstatus:active,expired, orrevoked. Secrets appear only as their last four characters.POST /v1/agents/YOUR_AGENT_ID/credentials/CREDENTIAL_ID/revokerevokes one credential. The next token request with it fails. Tokens issued before the revocation stay valid until they expire, at most 300 seconds later.
Registering and revoking credentials and changing the policy are recorded in your organization’s audit log. Each issued token also writes an audit record with the agent, credential, resource, scopes, lifetime, token ID, and policy revision. The record never contains the token.
Verify an agent token in your API
Agent tokens are RFC 9068 access tokens signed with the same keys as Runtype identity assertions, published at https://api.runtype.com/.well-known/jwks.json. They use a separate issuer, so an API that trusts only https://api.runtype.com/orgs/YOUR_ORGANIZATION_ID rejects them without any change.
To accept agent tokens, check the following on every request:
- The signature verifies with the JWKS key whose
kidmatches the token header, andalgisES256. - The
typheader isat+jwt. issis exactlyhttps://api.runtype.com/orgs/YOUR_ORGANIZATION_ID/agents. Reject every other issuer.audis your API’s canonical resource URI.exphas not passed, allowing a small clock tolerance.scopecontains the scope the operation needs, if your API uses scopes.
The following Node.js example uses the jose library:
The token’s sub is agent: followed by the agent ID, and client_id is the agent ID. The runtype claim holds the organization ID, principal, trigger (always external for this grant), grant (always agent), and the policyRevision the token was issued under. The policy decides which resources a token can reach; your API still decides which operations the agent may perform.
OAuth libraries and MCP clients can discover the issuer from its metadata at https://api.runtype.com/.well-known/oauth-authorization-server/orgs/YOUR_ORGANIZATION_ID/agents.
Token endpoint errors
The token endpoint returns OAuth errors as JSON with error and error_description. The following table lists the codes:
Next steps
Use the following pages to continue:
- Bring your own agent: register the harness as an external agent.
- End-user identity and credentials: send a verified end user’s identity to your API.
- Authentication: create the API key that manages agent credentials.