For Coding Agents
Authentication
AGNT uses certificate-based JWT authentication with RSA RS256 signing. You generate certificates through the API, sign JWTs with your private key, and include the token in every request.
There are no API keys. No OAuth flows. No session cookies. Just signed JWTs.
Two API Types
Management APIs operate at the organization level. Creating certificates, configuring providers, managing prompts — anything that doesn't need a user context.
Delegated APIs act on behalf of a specific user. Chats, tasks, memories — anything tied to an end user. These require an email claim in the JWT payload.
The distinction matters because it determines what goes in your JWT.
JWT Structure
Every JWT must include these header fields:
{
"alg": "RS256",
"kid": "your-certificate-key-id"
}alg is always RS256. kid is the key ID returned when you create a certificate. AGNT uses the kid to look up the public key and verify your signature.
Management API Payload
{
"iat": 1700000000,
"exp": 1700003600
}That's it. No user context needed.
Delegated API Payload
{
"email": "user@example.com",
"firstName": "Jane",
"lastName": "Doe",
"iat": 1700000000,
"exp": 1700003600
}| Field | Required | Description |
|---|---|---|
email | Yes | End user's email address |
firstName | No | End user's first name |
lastName | No | End user's last name |
iat | Yes | Issued-at timestamp (epoch seconds) |
exp | Yes | Expiration timestamp (epoch seconds) |
Keep token lifetimes short. An hour is plenty. Generate a new token per request if you want — the signing is local and fast.
Signing JWTs
Use the jose library (or any RS256-capable JWT library). Here's JavaScript:
import { SignJWT, importPKCS8 } from "jose";
import fs from "fs";
const privateKeyPem = fs.readFileSync("./private-key.pem", "utf-8");
const privateKey = await importPKCS8(privateKeyPem, "RS256");
// Management API token (no user context)
const managementToken = await new SignJWT({})
.setProtectedHeader({ alg: "RS256", kid: "your-certificate-key-id" })
.setIssuedAt()
.setExpirationTime("1h")
.sign(privateKey);
// Delegated API token (with user context)
const delegatedToken = await new SignJWT({
email: "user@example.com",
firstName: "Jane",
lastName: "Doe",
})
.setProtectedHeader({ alg: "RS256", kid: "your-certificate-key-id" })
.setIssuedAt()
.setExpirationTime("1h")
.sign(privateKey);Include the token in the Authorization header:
Authorization: Bearer <token>
Auto-Provisioning
When you make a Delegated API call with an email that AGNT hasn't seen before, the user is automatically created. The firstName and lastName claims are used to populate the user record.
No separate user creation step. No signup flow to build. Include the email, and the user exists.
Subsequent calls with the same email update firstName and lastName if the claims are present and different.
Certificate Management
Certificates are how AGNT verifies your JWTs. You create a certificate, AGNT stores the public key, and you keep the private key. Standard RSA key pair stuff.
Create a Certificate
POST https://api.agnt.ai/certificates
Returns an RSA key pair. Save the private key immediately — AGNT does not store it and cannot recover it.
Response includes id, kid, publicKey, and privateKey.
List Certificates
GET https://api.agnt.ai/certificates
Returns all certificates for your organization.
Get Active Certificate
GET https://api.agnt.ai/certificates/active
Returns the currently active certificate.
Get Public Key (No Auth Required)
GET https://api.agnt.ai/certificates/public/:kid
This endpoint is public. No authentication needed. Useful for external services that need to verify tokens you've issued.
Revoke a Certificate
POST https://api.agnt.ai/certificates/:id/revoke
Revoked certificates can no longer be used to verify JWTs. Existing tokens signed with a revoked certificate will be rejected.
Delete a Certificate
DELETE https://api.agnt.ai/certificates/:id
Permanently removes the certificate. This is irreversible.
Super Admin Access
Users with an @agnt.ai email domain are automatically granted super admin access across the platform. This is hardcoded and not configurable — it's an internal operational concern, not a feature.