Agent registration (auth.md)
PerSQL implements auth.md, the open protocol that lets an agent register for a service and receive a scoped, short-lived access token — discoverable from a Markdown file at the service root. An agent that has never heard of PerSQL can find the manifest at https://api.persql.com/.well-known/auth.md, learn which flows exist, and bootstrap a token on its own.
There are two flows. Both end in a psql_live_… token you use against the /v1 API.
Discovery
Section titled “Discovery”Two hops, both unauthenticated:
GET /.well-known/oauth-protected-resource— RFC 9728 metadata pointing at the authorization server.GET /.well-known/oauth-authorization-server— itsagent_authblock lists theidentity_endpoint,token_endpoint, the supported flows, and askilllink toauth.md.
Agent Verified flow
Section titled “Agent Verified flow”Your provider attests your identity with a signed token — any RS256/ES256 OIDC ID token (or ID-JAG assertion) from a trusted issuer, minted with audience persql. Wired today: GitHub Actions, Google Cloud service accounts / workload identity, and GitLab CI. Adding another issuer is a one-line registry entry, so an ID-JAG provider slots in the moment it ships a public JWKS.
import { registerAgent } from "@persql/sdk";
// `providerAssertion` is e.g. a GitHub Actions OIDC token (audience "persql").const grant = await registerAgent(providerAssertion);
import { PerSQL } from "@persql/sdk";const db = new PerSQL({ token: grant.accessToken }).database(grant.database);Under the hood: POST /agent/identity with { "type": "identity_assertion", "assertion": "<jwt>" } returns a service-signed identity_assertion; the SDK exchanges it at /oauth/token (grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer) for the access token. The access token is short-lived — re-exchange the durable assertion to refresh, there is no refresh token:
import { exchangeAgentAssertion } from "@persql/sdk";const fresh = await exchangeAgentAssertion(grant.identityAssertion!);The raw GitHub Actions on-ramp (one curl, no SDK) is documented under self-signup — it’s the same verified flow.
Enterprise identity
Section titled “Enterprise identity”When the trusted issuer is an enterprise IdP (WorkOS, Okta, Microsoft Entra, Google Workspace) that asserts a verified human email, the verified flow binds the workspace to that person, not a machine: an agent running as [email protected] registers a workspace for Madison — one she already owns if she has a PerSQL account, or one she can claim later by signing in with that email. Onboarding a customer’s IdP is a single config entry (its issuer URL + audience); PerSQL OIDC-discovers the rest. The trust boundary is the IdP’s email verification, so this binding is enabled per-issuer only for IdPs trusted for identity.
User Claimed flow
Section titled “User Claimed flow”No provider attestation: a human confirms a short code in the browser, which provisions a workspace in their own account.
import { beginAgentClaim } from "@persql/sdk";
const claim = await beginAgentClaim({ clientName: "My Agent" });console.log(`Visit ${claim.verificationUri} and confirm code ${claim.userCode}`);
// Resolves once the user approves it in the console (or rejects on expiry).const grant = await claim.poll();Under the hood: POST /agent/identity with { "type": "service_auth" } returns a claim_token plus a user_code and verification_uri. The agent shows the user the code; they sign in at the console, pick which workspace the agent should get, and confirm. The agent polls /oauth/token (grant_type=urn:workos:agent-auth:grant-type:claim) until it resolves into an admin token for that workspace.
Always show the user the user_code and have them check it matches before approving — that’s the defense against a forwarded link binding the agent to the wrong account.
- Verified vs claimed token lifetime. The verified flow’s access token is short-lived; its
identityAssertionis the durable (30-day), re-exchangeable credential — keep it secret. The claimed flow returns a normal no-expiry token instead, revocable any time under API tokens (a single human confirmation shouldn’t hand out a long-lived minting credential). - Tokens are admin-scoped to one workspace. A verified agent gets its own self-owned workspace; a claimed agent gets an admin token for the workspace the user picked. Neither can reach the user’s other workspaces.
- Billing is usage-only against the workspace’s prepaid balance — top up before heavy use.