Skip to content

Agents · work in progress

AgentPass for services

Let an AI agent act for one of your users, with the user’s explicit approval, without sharing their password or session. Identvia is an AgentPass v0.1 federated Authority; your site is the Service.

AgentPass v0.1 is a draft specification and may change. Identvia implements the version pinned at clerk/agentpass@937efe3. Don’t put irreversible or high-value actions behind it yet.

How it works

  1. The agent’s harness asks Identvia for a pass: which site, which user, what task, which kind (bearer_token or browser_session), and the harness’s public key.
  2. Identvia finds your site through DNS, asks your site which permissions exist, and puts the request in the user’s inbox. The user picks the permissions and approves with a passkey or authenticator app. Agents can never approve their own requests.
  3. The harness gets a pass that works once, for your site only, within 2 minutes, and only together with a proof signed by the harness key.
  4. Your site redeems the pass: it checks it with Identvia, verifies the proof, and issues its own API token or a one-time sign-in link.
  5. While the agent works, your site re-checks the delegation at least every 60 seconds. When the user revokes it in Identvia, the agent is stopped.

PHP: identvia/agentpass-php

An MIT-licensed library for any PHP 8.1+ site (no framework, works on shared hosting). It serves the AgentPass endpoints, does DNS discovery and authority resolution, validates passes with the Authority, verifies the holder proof, mints bearer tokens or browser sessions, and runs the continuous checks (fail-closed).

PHP
$service = new AgentPass\Service\Service(new AgentPass\Service\ServiceConfig(
    origin: 'https://todo.example.com',
    signingKeyPem: file_get_contents(__DIR__ . '/agentpass-key.pem'),   // bin/agentpass-keygen
    trustedAuthorities: [AgentPass\Service\ServiceConfig::authority('https://id.identvia.com')],
    scopes: [['name' => 'todos:read', 'description' => 'See your todos'], ['name' => 'todos:write', 'description' => 'Add todos']],
    store: AgentPass\Service\Store\PdoStore::sqlite(__DIR__ . '/data/agentpass.sqlite'),
));
if ($service->handleGlobals()) { exit; }            // the /agentpass-service/* endpoints

// In your API:
$d = $service->authenticateBearer($_SERVER['HTTP_AUTHORIZATION'] ?? '');
if (!$d->can('todos:write')) { /* 403 */ }

The download includes a complete demo todo service (examples/todo) that accepts both bearer tokens and browser sessions.

DNS record

Publish one TXT record so Authorities can find your configuration:

DNS
_agentpass-service.todo.example.com.  TXT  "https://todo.example.com/agentpass-service/config.json"

Enterprise domains can publish _agentpass.<domain> with their own Authority URL, or none to disable delegation. Identvia and the SDK honour that precedence.

Identvia’s Authority endpoints

  • Configuration: https://id.identvia.com/agentpass/ap
  • Issuance: POST /agentpass/requests → 202 with a status link; poll no faster than poll_after_ms.
  • Validate and authorization-check: called by Services with a short-lived ES256 assertion signed by the key in the Service’s JWKS.

Your responsibilities

  • Treat the agent as acting for the user, but label it: show “via agent” in your UI and logs.
  • Offer narrow permissions. Never offer *; Identvia won’t either.
  • Keep checkCacheSeconds at 60 or less, and fail closed when the Authority can’t be reached.
  • Treat the task description as untrusted text from the agent.