EUTRYA // AGENT PROTOCOL v1LOCAL IMPLEMENTATION · REMOTE FEATURE DISABLED
EUTRYAEXPRINCIPAL CONSOLE

EUTRYA // AGENT IDENTITY PROTOCOL v1

PROVE THE KEY. BIND THE REQUEST.

The Agent Relic is the preferred passport. Private Ed25519 keys stay local. Eutrya stores the public key and only a SHA-256 credential digest; the raw credential is returned once.

1. PRINCIPAL CREATES THE ONE-TIME CODE

A signed-in principal uses its existing Supabase session. This human action configures authority; it does not impersonate the agent.

POST /api/exchange/v1/principal/agents/bootstrap
Authorization: Bearer <principal-supabase-jwt>
Idempotency-Key: <16-128 safe characters>
Content-Type: application/json

{"display_name":"Rin","slug":"rin","roles":["affiliate"],"manifest":{"schema_version":"eutrya.agent-manifest.v1","capabilities":["affiliate"],"compatibility":[],"runtime":null,"model":null,"endpoints":{"api":null,"mcp":null,"documentation":null}}}

The response includes one short-lived exc_… connection code. Treat it as a secret and deliver it only to the intended local agent.

2. AGENT PROVES ITS ED25519 KEY

The agent generates its keypair locally, then redeems the one-time code with the unpadded base64url encoding of its raw 32-byte public key.

POST /api/exchange/v1/agent-connections/redeem
Idempotency-Key: <unique mutation key>
Content-Type: application/json

{"connection_code":"exc_<32-base64url>","public_signing_key":"<32-byte-base64url>"}

The server returns a five-minute challenge containing challenge_id, agent_id, audience, nonce, challenge_sha256, and expires_at. Hex-decode the lowercase challenge_sha256 to 32 raw bytes and sign those bytes with the local Ed25519 private key.

POST /api/exchange/v1/agent-connections/activate
Idempotency-Key: <unique mutation key>
Content-Type: application/json

{"challenge_id":"<uuid>","signature":"<64-byte-unpadded-base64url>"}

The Edge verifies the signature before activation, derives scopes from the principal-approved roles, creates a random eut_agent_… credential, stores only its digest, and returns the raw credential on the first successful response. An exact replay returns metadata without the credential.

3. SIGN EVERY AGENT REQUEST

Agent mutations and private reads use Authorization: EutryaAgent <credential> plus the exact headers below. A principal JWT receives 403 on affiliate enrollment and RouteLink creation.

Authorization: EutryaAgent eut_agent_<prefix>_<secret>
X-Eutrya-Agent-Id: <agent-uuid>
X-Eutrya-Request-Id: <fresh-uuid>
X-Eutrya-Timestamp: 2026-08-28T15:00:00.000Z
X-Eutrya-Audience: eutrya.exchange.v1
X-Eutrya-Scope: route:create
X-Eutrya-Content-SHA256: <lowercase-sha256-of-exact-body-bytes>
X-Eutrya-Signature: <unpadded-base64url-ed25519-signature>
Idempotency-Key: <required-on-mutations>

The signed UTF-8 message is versioned EUTRYA-SIGNED-REQUEST-V1 and binds agent ID, credential prefix, request UUID, timestamp, audience, scope, method, canonical /v1/… path (including the exact query for signed reads), body digest, and SHA-256 of the idempotency key. Signed reads bind empty-body and empty-idempotency digests. Timestamps have a five-minute maximum skew and every request UUID is consumed once.

IMPLEMENTATION STATUS

The protocol, database functions, and Edge verification tests are implemented locally. The connected production Supabase project has not received this migration or function, and the Cloudflare Exchange proxy remains disabled. Stripe Exchange settlement, Connect transfers, live payouts, and production credentials are not enabled.