Guest Post

Giving Agents Their Own Turso Accounts with AgentID

AgentID gives AI agents their own OIDC identity, so an agent can create and access its own Turso account with no borrowed credentials or human in the loop.

Haakam Aujla
Haakam AujlaCEO of AgentMail
Cover image for Giving Agents Their Own Turso Accounts with AgentID

Agents need accounts. Their own accounts, created and accessed under their own identity. No borrowed credentials, no shared service tokens, no OAuth flows requiring a human at a browser.

That's the gap AgentID fills for Turso.

#What AgentID Is

AgentID is an OpenID Connect provider built specifically for AI agents. It's the same protocol your app already uses for Google or GitHub sign-in. If your stack validates OIDC tokens today, AgentID is a configuration change, not a code change.

The difference from a standard OIDC provider is what sits behind the authorization flow. Instead of a human completing a browser session, an agent approves sign-in requests by signing a compact JWS assertion with a P-256 private key it holds. No human password, no borrowed account, and no human required in the loop.

AgentID is built on AgentMail, an email inbox API for AI agents. An agent's identity is tied to a live AgentMail inbox, and that inbox address becomes the email on any account the agent creates. This matters more than it might seem at first. More on that below.

#The Three Identities Problem

Agents operating in production tend to conflate things that should stay separate:

  • The agent itself
  • The human who owns or is responsible for the agent
  • The application or infrastructure the agent runs inside

When an agent authenticates using a human's credentials or an application-managed service token, you lose the ability to distinguish between these. Permissions blur. Audit trails blur. When something goes wrong, accountability blurs.

AgentID separates them cleanly. Each agent gets a stable subject identifier (sub) tied to its own AgentMail inbox. With the appropriate scopes, a relying party like Turso can also obtain the identity of the human who owns the agent, separately as metadata, not conflated with the agent's own identity.

Turso's agent-database architecture already supports database-per-agent patterns for exactly this reason: isolation between agents matters, both for security and for operational clarity. AgentID extends that isolation up to the account layer.

#Establishing an Agent Identity

Before an agent can sign in anywhere, it needs an AgentMail inbox and a signing credential.

The setup is straightforward:

  1. Create an AgentMail account and inbox. AgentMail supports programmatic agent signup using a human owner's email for verification. The agent doesn't need a human to click through anything.
  2. Generate a P-256 keypair for the agent.
  3. Store the private key in the agent's keystore, secret manager, or HSM. It never leaves the agent's control. It's not sent to AgentMail, and it's not sent to Turso.
  4. Register the public key through the AgentMail API.
  5. AgentMail returns an api_key_id. That identifier is used in the JWS header when the agent signs AgentID approval requests.

The signing credential can be scoped to an individual inbox, a pod, or an AgentMail organization. It doesn't grant REST API access to AgentMail. It's specifically for approving AgentID sign-ins within its scope. The full setup is in the AgentID public-key authentication guide.

#The Sign-In Flow

Turso is a registered OIDC relying party. It requests all currently supported AgentID identity scopes:

openid email profile owner_profile owner_email

The authorization flow uses the standard OIDC Authorization Code flow with PKCE. Here's what happens:

  1. Turso redirects the user to AgentID's authorization endpoint.
  2. AgentID creates a short-lived, single-use authorization transaction and displays its request ID on the AgentID authorization page.
  3. An agent controlling the browser can read the request ID directly, or a human can provide it to the agent.
  4. The agent constructs and signs a compact JWS containing the request ID and inbox ID:
{
  "jti": "<request-id>",
  "inbox_id": "<agent-inbox>"
}

The protected header identifies the registered public key:

{
  "alg": "ES256",
  "typ": "agentid-approval+jwt",
  "kid": "<api_key_id>"
}
  1. The signed assertion is submitted to AgentID's approval endpoint. The signature is the authentication. No bearer token, no password, no session cookie required.
  2. AgentID verifies the signature and checks the live state of the transaction, signing credential, inbox, and scope permissions.
  3. AgentID redirects back to Turso with a short-lived authorization code.
  4. Turso exchanges the code for an ID token and access token, then validates the ID token against AgentID's published issuer and JWKS.
  5. Turso uses the resulting identity to create a new account or sign the agent into its existing one. The verified AgentMail address becomes the account's email address.

Node, Python, and raw HTTP examples for the agent-side approval contract are in the AgentID agent-side documentation.

#What Turso Receives

Because Turso requests all AgentID scopes, a successful authorization provides a complete agent identity. The identity is split across two OIDC surfaces.

The ID token carries the stable agent identity:

{
  "iss": "https://auth.agentid.com",
  "aud": "<turso-client-id>",
  "sub": "a91f2c8e...43",
  "scope": "openid email profile owner_profile owner_email",
  "email": "support@acme.agentmail.to",
  "email_verified": true,
  "name": "Acme Support",
  "iat": 1767225000,
  "exp": 1767225600,
  "jti": "9f1c2a44-3e77-4c19-9a2e-6b0d5f8e1c33"
}

Owner information isn't in the ID token. By design, it's served from /v0/userinfo using the access token from the same authorization:

{
  "sub": "a91f2c8e...43",
  "email": "support@acme.agentmail.to",
  "email_verified": true,
  "name": "Acme Support",
  "owner_name": "Maya Chen",
  "owner_email": "maya@acme.com"
}

The claims you can expect, assuming all scopes are granted:

ClaimSourceDescription
subID tokenStable identifier for the agent. Same agent, same sub, every time.
emailID tokenThe agent's live AgentMail inbox address.
email_verifiedID tokenAlways true when present.
nameID tokenThe agent inbox's display name, when configured.
scopeID tokenThe scopes actually granted during this authorization.
owner_name/v0/userinfoThe name of the human who owns the agent.
owner_email/v0/userinfoThe owner's email address.

#The AgentMail Inbox as a Working Communication Channel

This is worth spending a moment on, because it's easy to treat the inbox address as just an identity claim and move on.

It isn't. The AgentMail inbox is a live email address. All email Turso sends to the account, account messages, onboarding, security notifications, service updates, goes directly to that inbox. The agent can receive and process those messages through the AgentMail API, SDKs, webhooks, WebSockets, or IMAP.

That means the agent isn't just authenticated once and then left to operate blind. It has a working communication channel with Turso for the lifetime of the account. Billing alerts, usage warnings, security notices: the agent can receive and act on all of it programmatically, without routing through a human inbox or building a separate notification pipeline.

The human owner's email is separate. It can be disclosed to Turso as accountability metadata via the owner_email claim, but it's not the address associated with the agent's account. That's the AgentMail inbox.

#Token Verification

AgentID publishes a standard OIDC discovery document:

https://auth.agentid.com/.well-known/openid-configuration

Tokens are signed with ES256. Turso validates:

  • The signature against the published JWKS
  • The exact issuer (https://auth.agentid.com)
  • Its own client_id as the audience
  • Token expiration
  • The authorization nonce where applicable

Signing keys rotate with stable key IDs and an overlap window, so caching JWKS by kid is safe. Derive endpoints from the discovery document rather than hard-coding them. The full integration reference is at www.agentid.com/docs.

#Lifecycle and Revocation

AgentID performs live checks during authorization and token exchange. A sign-in fails if any of the following are true at the time of the request:

  • The signing credential has been revoked
  • The inbox has been deleted
  • The organization has been suspended
  • The authorization transaction has expired
  • The inbox is outside the credential's scope

Signing credentials can be revoked individually. AgentMail also provides an organization-wide operation for invalidating all current AgentID sign-in keys, useful if a credential is compromised or an agent is decommissioned.

#What AgentID Doesn't Do

AgentID authenticates the identity that approved the sign-in. It doesn't evaluate the agent's model, instructions, capabilities, or behavior. It has no opinion on what the agent will do after it's authenticated.

Turso remains responsible for the account permissions and resources it grants after authentication. AgentID supplies the authenticated subject, verified inbox identity, and owner information. What Turso does with that is Turso's call.

#How the Layers Fit Together

Turso's agent-database architecture and AgentID operate at different layers, and it's worth being explicit about what each one handles:

  • Turso manages the agent's data and database resources: embedded databases, synced state, memory, context, embeddings, files.
  • AgentMail provides the agent's inbox and handles ongoing account communication.
  • AgentID authenticates the agent when it creates or accesses its Turso account.

The integration connects Turso's database layer with a stable agent identity, a working communication channel, and a clear line of human accountability. What makes an agent a first-class participant in a service relationship is having all of those things, rather than being a process borrowing someone else's credentials.

For developers building agents on Turso, the practical upshot is that you can provision an agent with its own Turso account and its own database resources, without touching a human credential anywhere in the stack. The agent signs in as itself, the human owner is on record, and the full integration reference is at www.agentid.com/docs.