Skip to content
Skip the search — install the Self skill Let your AI agent integrate Self for you.

Start typing to search the documentation.

Verification Patterns

Self Agent ID supports four verification patterns, each suited to different integration scenarios.

Pattern 1: Agent-to-Service

The most common pattern. An agent signs HTTP requests; a service verifies the signature and checks the on-chain registry.

Agent                          Service
  │                               │
  │── POST /api (signed) ────────▶│
  │   headers:                    │
  │     x-self-agent-address      │── ecrecover signer
  │     x-self-agent-signature    │── derive agentKey
  │     x-self-agent-timestamp    │── isVerifiedAgent(key)
  │                               │── check credentials
  │◀── 200 OK ────────────────────│

SDK support: SelfAgent.fetch() on agent side, SelfAgentVerifier.auth() middleware on service side.

Pattern 2: Agent-to-Agent (Peer Verification)

Two agents verify each other’s identity. Both sign their requests, and both verify the other’s signature against the registry.

Agent A                        Agent B
  │                               │
  │── POST (signed by A) ────────▶│
  │                               │── verify A's signature
  │                               │── sameHuman(A, B) check
  │◀── Response (signed by B) ────│
  │── verify B's signature        │

Key feature: sameHuman(agentIdA, agentIdB) detects whether two agents share the same human backer without revealing who that human is.

Pattern 3: Agent-to-Chain (Direct)

The agent calls a smart contract directly using msg.sender. The contract checks the registry.

import { AgentGate } from "./AgentGate.sol";

contract MyProtocol is AgentGate {
    constructor(address registry) AgentGate(registry) {}

    function protectedAction() external onlyVerifiedAgent {
        // Only registered, human-backed agents can call this
    }
}

Best for: Verified Wallet mode where the agent’s wallet address IS the msg.sender.

Pattern 4: Agent-to-Chain (Meta-Transaction)

The agent signs an EIP-712 typed data message; a relayer submits the transaction on-chain. The contract verifies the EIP-712 signature matches a registered agent.

Agent                    Relayer                  Contract
  │                         │                        │
  │── sign EIP-712 ──────── │                        │
  │   (agentKey, nonce,     │── metaVerify(sig) ────▶│
  │    deadline)            │                        │── ecrecover signer
  │                         │                        │── isVerifiedAgent()
  │                         │◀── tx confirmed ───────│
  │◀── receipt ─────────────│                        │

Best for: Gasless verification where agents don’t hold native tokens. The AgentDemoVerifier contract implements this pattern.

Sybil Resistance

Services can enforce their own sybil policies using three approaches:

Strict (max 1 agent per human)

const verifier = SelfAgentVerifier.create()
  .sybilLimit(1)
  .build();

Moderate (allow N agents)

const verifier = SelfAgentVerifier.create()
  .sybilLimit(5)
  .build();

Detection Only

// Allow unlimited, but check relationships
const verifier = SelfAgentVerifier.create()
  .sybilLimit(0) // unlimited
  .build();

// Then use sameHuman() for analytics
const areSame = await registry.sameHuman(agentId1, agentId2);

Credential-Based Verification

Verifiers can require specific ZK-attested credentials:

const verifier = SelfAgentVerifier.create()
  .requireAge(18)           // Agent's human must be 18+
  .requireOFAC()            // Agent's human must be OFAC-cleared
  .requireNationality("US") // Specific nationality
  .build();

All credential checks are verified against on-chain ZK-attested data — no additional identity check needed.

Was this page helpful?