Building an Agent
This guide walks through registering an AI agent with Self Agent ID and making authenticated requests. By the end, your agent will have an on-chain identity backed by a real passport verification.
1. Choose Your SDK
| Language | Package | Install |
|---|---|---|
| TypeScript | @selfxyz/agent-sdk | npm install @selfxyz/agent-sdk |
| Python | selfxyz-agent-sdk | pip install selfxyz-agent-sdk |
| Rust | self-agent-sdk | cargo add self-agent-sdk |
All three SDKs have identical functionality with language-idiomatic naming.
2. Register Your Agent
Six registration modes — choose based on your use case:
| Mode | Best for | Wallet needed? |
|---|---|---|
wallet-free | Embedded agents, IoT, CLI-only | No |
ed25519 | OpenClaw, Eliza, IronClaw agents | No |
linked | Autonomous AI agents | Yes (human’s) |
ed25519-linked | Ed25519 agents with human wallet | Yes (human’s) |
privy | Social login (Google, Twitter) | No |
smartwallet | Consumer-facing, passkey UX | No |
Via the dApp (simplest)
- Go to selfagentid.xyz
- Select your registration mode and network
- Scan your passport with the Self app
- Copy the agent private key from the export page
What your user will see
The dApp walks users through a guided wizard:
- Role selection — “I’m building an agent” or “I’m a human registering for my agent”
- Key type — ECDSA or Ed25519, with framework-specific hints (e.g. OpenClaw and Eliza use Ed25519)
- Mode selection — The wizard narrows the six modes to the ones that match the chosen key type, with a comparison table showing wallet requirements, NFT ownership, and revocation methods
- Network — Mainnet (real passport) or Testnet (mock documents)
- Verification config — Optional age threshold and OFAC screening
- Key generation / import — For ECDSA modes, a fresh keypair is generated in the browser. For Ed25519 modes, the user pastes the agent’s existing public key
- Passport scan — A QR code or deep link opens the Self app for ZK proof-of-human verification
- Confirmation — On-chain registration completes and the agent key is available for export
The entire flow takes under two minutes. No crypto knowledge is required for wallet-free, privy, or smartwallet modes.
Via CLI
# Install the CLI (comes with the SDK)
npm install -g @selfxyz/agent-sdk
# Initialize registration
self-agent register init \
--mode linked \
--human-address 0xYourWallet \
--network mainnet \
--minimum-age 18 \
--ofac
# Open the browser handoff URL
self-agent register open --session .self/session-*.json
# Wait for verification to complete
self-agent register wait --session .self/session-*.json
# Export the agent private key
self-agent register export --session .self/session-*.json --unsafe --print-private-key
Via A2A Protocol (for agents)
Agents can self-register by sending a JSON-RPC request to the A2A endpoint:
curl -X POST https://selfagentid.xyz/api/a2a \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "message/send",
"params": {
"message": {
"role": "user",
"parts": [{ "type": "data", "data": { "intent": "register" } }]
}
}
}'
The endpoint returns a QR code and deep link. A human scans the QR with the Self app to complete verification. Send { "intent": "help" } to see all available modes and a decision guide.
Via REST API
curl -X POST https://selfagentid.xyz/api/agent/register \
-H "Content-Type: application/json" \
-d '{
"mode": "linked",
"network": "mainnet",
"humanAddress": "0xYourWallet",
"disclosures": { "minimumAge": 18, "ofac": true }
}'
Poll /api/agent/register/status?token=<token> until stage: "completed".
Via Smart Wallet (passkeys)
- Go to selfagentid.xyz
- Select “Smart Wallet” mode
- Create a passkey — this generates a ZeroDev Kernel smart account as your guardian
- Scan your passport with the Self app
- On mainnet, transactions are gasless via Pimlico paymaster
3. Sign Outbound Requests
Every SDK provides agent.fetch() which automatically signs requests with three headers:
import { SelfAgent } from "@selfxyz/agent-sdk";
const agent = new SelfAgent({
privateKey: process.env.AGENT_PRIVATE_KEY!,
network: "mainnet",
});
const res = await agent.fetch("https://api.example.com/data", {
method: "POST",
body: JSON.stringify({ query: "test" }),
});from self_agent_sdk import SelfAgent
import os
agent = SelfAgent(
private_key=os.environ["AGENT_PRIVATE_KEY"],
network="mainnet",
)
res = agent.fetch("https://api.example.com/data",
method="POST", body='{"query": "test"}')use self_agent_sdk::{SelfAgent, SelfAgentConfig, NetworkName};
let agent = SelfAgent::new(SelfAgentConfig {
private_key: std::env::var("AGENT_PRIVATE_KEY").unwrap(),
network: Some(NetworkName::Mainnet),
registry_address: None,
rpc_url: None,
}).unwrap();
let res = agent.fetch(
"https://api.example.com/data",
Some(reqwest::Method::POST),
Some(r#"{"query":"test"}"#.to_string()),
).await.unwrap();The signed headers:
| Header | Value |
|---|---|
x-self-agent-address | Agent’s Ethereum address |
x-self-agent-signature | ECDSA signature of keccak256(timestamp + METHOD + path + bodyHash) |
x-self-agent-timestamp | Unix timestamp (ms) |
4. Check Registration Status
const registered = await agent.isRegistered();
const info = await agent.getInfo();
// { agentId, isVerified, proofProvider, verificationStrength, ... }
5. Read Credentials
const creds = await agent.getCredentials();
// { nationality, olderThan, ofac, dateOfBirth, gender, issuingState, ... }
Credentials are ZK-attested — extracted from passport data without revealing the full document.
6. Set an Agent Card (A2A)
Agent cards enable discovery in agent-to-agent protocols:
await agent.setAgentCard({
name: "My Agent",
description: "Analyzes market data",
url: "https://myagent.example.com",
skills: [{ name: "market-analysis", description: "Analyzes crypto markets" }],
});
const card = await agent.getAgentCard();
Cards are stored on-chain and readable by any agent or service.