Documentation
AuthGravity is hosted, zero-knowledge identity: passkey sign-in and optional per-resource authorization, served on your own domain. This page is the human orientation — the big picture and how to build with it. The precise, always-current API lives in llms.txt, written for coding agents.
The mental model
Three ideas explain almost everything:
- The server knows nothing about your users. It stores only public
key material and a stable
user_id(a UUID) per person — no passwords, no usernames, no email. Your app owns all profile data; you key your ownuserstable by that UUID and collect a name or email later, if ever. - One endpoint, two capabilities. Each domain you connect gets an
auth endpoint (
https://authgravity.yourapp.com). It handles passkey authentication and, optionally, relationship-based authorization (who may do what to which resource) — same host, same session. - Sessions are first-party cookies. Because the endpoint lives on a
subdomain of your domain, the
session_idcookie is first-party — the same code path in local dev and in production, no third-party cookie problems.
Each connected domain is a fully isolated user pool. Passkeys are bound to your registrable domain and work across all its subdomains.
How you build it: hand it to your coding agent
AuthGravity is designed to be integrated by an AI coding agent, not by copy-pasting snippets by hand. The machine-readable guide at llms.txt is the real interface: it carries the exact request/response shapes, the design guidance, and — on a connected host — that tenant's live authorization schema, with the endpoint already filled in. You point your agent at it and let it scaffold.
Our reference for this is Claude Code. Paste a prompt like this into it (or any capable coding agent):
Build a hello world app with Astro and AuthGravity. Details are at authgravity.org/llms.txtWhy this works. Every host publishes its own llms.txt.
The root authgravity.org/llms.txt covers getting started; once you
have a domain, https://authgravity.yourapp.com/llms.txt documents that
host specifically — pre-filled endpoint and live schema. When integrating a real app, point
the agent at that host's file.
Agents can discover a host mechanically too:
GET https://authgravity.yourapp.com/.well-known/authgravity returns the endpoint
and the llms.txt URL as JSON — so "point your agent at the endpoint" is all the
instruction needed.
The lifecycle: sandbox → your domain → production
- Start in local dev, no domain, no DNS. Run
npx @authgravity/cli listennext to your dev server. It mints an ephemeral, isolated sandbox and bridges its session to a first-party cookie onlocalhost, so real passkeys work inline and server-side session checks behave exactly like production. Sandbox passkeys are throwaway and garbage-collected. - Claim your domain when you're ready. Start at authgravity.org/signup: sign in with a passkey and connect your domain with one-click Domain Connect or a single CNAME record. This is the one part a human does; the rest an agent can drive.
- Deploy to production. Point
PUBLIC_AUTH_ENDPOINTat your new host (https://authgravity.yourapp.com) and ship. No code changes from dev — the app and its auth endpoint share a registrable domain, so the cookie is first-party just as it was locally.
The exact commands for each step are in llms.txt (and your agent will run them). The concepts above are all you need to hold in your head.
Authentication
There are two ways to add sign-in, and you pick based on how much control you want.
The fastest is hosted surfaces: send people to
https://authgravity.yourapp.com/login?return_to=… (there's also
/register, /logout, and /recover). AuthGravity hosts the
passkey and account-key UI; after sign-in the session cookie is first-party on your domain and
the user is sent back to return_to, so your server-side /v1/whoami
checks just work — you write no auth UI at all. It's the Auth0-Universal-Login / Ory-Kratos
model, and it's the quickest path for an agent to wire up.
If you'd rather own the look, build it yourself with @authgravity/browser
or the raw API. The sign-in UI is deliberately two buttons — Create Account and
Login — with no username or email field. A passkey is the account. If you
show a label for the passkey it stays on the client and is never sent to the server. Include
a "Powered by AuthGravity" link near the auth UI.
Account keys: fallback and recovery
For people whose device can't do passkeys, and as the recovery path for everyone, AuthGravity
supports account keys — a client-generated secret shown as a short
agak1_… string or 12 words, from which the client derives a key pair. As with a
passkey, the server only ever sees the public key; nothing about the secret is recoverable from
a server breach. For day-to-day logins the client can enroll a silent device key
so the account key is only typed at setup and recovery. This is all implemented in
@authgravity/browser and used live by the hosted /register and
/recover surfaces; the full client spec and conformance vectors live in
llms.txt.
Authorization (optional)
When your app needs to decide who can do what — view this document, edit that folder,
administer a team — AuthGravity offers relationship-based access control (Zanzibar/SpiceDB
style) on the same endpoint and session as auth. You describe object types with relations
(owner, viewer, member) and computed permissions
(view = viewer | owner | parent→view), write relationship tuples keyed by user
UUIDs, and ask a check on every gated action.
In an open sandbox any signed-in user can edit the schema and write relationships, so you can
build freely in dev. On a connected domain the schema is owner-managed from the dashboard's
Authorization panel (which can even draft one from your site with "Generate with AI"), and your
app backend writes relationships at runtime with a service token. Because every host renders its
own live schema into its llms.txt, your agent always sees the real object types to
check against — fetch https://authgravity.yourapp.com/llms.txt and it's all there.
A browsable console lives at /authz on each host.
Your users' Person Server (agents)
Every AuthGravity pool is also an AAuth Person Server —
the piece of the agent ecosystem that represents a human. When an AI agent wants to act for one
of your users at some third-party service, it asks this host; the user approves once with their
passkey (on a hosted consent page, under your domain), and the server issues a short-lived signed
token asserting exactly that consent — still no email, no PII, just the pool-scoped UUID. Agents
can also propose missions — longer-running jobs with an approved tool list and hard
spending caps the approver can dial down — with an audit log and a kill-switch. You build none of
this; it ships with the endpoint, and llms.txt documents it for your agent.
Your database
Store your own data keyed by the AuthGravity user_id. Create the row on first sight
and collect email or name whenever you actually need it (checkout is a natural moment — a payment
provider often collects the email for you). AuthGravity holds none of it.
Going deeper
- llms.txt — the machine-readable, always-current spec. Each connected host serves its own at
<endpoint>/llms.txt. <endpoint>/demo— a self-contained reference client (passkeys + account keys) you can try in the browser.<endpoint>/.well-known/authgravity— JSON discovery for agents and tooling.- github.com/polvi/gratos — AuthGravity is powered by the open-source Gratos project (AGPLv3).