trustagent
v0.1.4
Published
Trust enforcement middleware for AI agents on Celo
Maintainers
Readme
TrustAgent
Trust enforcement middleware for AI agents on Celo.
SelfClaw identity verification + ERC-8004 on-chain reputation + dynamic rate limiting — in 3 lines of code.
What is TrustAgent?
When Agent A wants to call Agent B's API, how does Agent B know:
- Agent A is a real, human-verified agent (not a bot)?
- Agent A has a good reputation?
- Agent A isn't spamming the endpoint?
TrustAgent solves this. Drop it into any Express server and every incoming agent request is automatically verified, reputation-checked, and rate-limited based on on-chain data.
import { createGateway } from 'trustagent';
const gateway = createGateway({ reputationGating: true });
app.use('/api', ...gateway.middleware());
// Done. All routes now require:
// ✅ SelfClaw identity verification
// ✅ ERC-8004 reputation check
// ✅ Dynamic rate limits based on reputation scoreTable of Contents
- Installation
- Quick Start
- Core Concepts
- Middleware
- Agent Client
- Agent Registration
- Reputation Feedback
- Request Extensions
- Configuration
- Rate Limit Tiers
- Error Reference
- Networks
- Examples
- Publishing to npm
Installation
npm install trustagentPeer dependencies:
npm install express @noble/ed25519 @noble/hashes viemQuick Start
Protect an API endpoint
import express from 'express';
import { createGateway } from 'trustagent';
const app = express();
app.use(express.json());
const gateway = createGateway({
selfClawVerify: true,
reputationGating: { enabled: true, minScore: 50 },
dynamicRateLimits: true
});
app.get('/api/data', ...gateway.middleware(), (req, res) => {
res.json({
data: 'protected content',
agent: req.agent.agentName,
reputation: req.reputation.averageScore
});
});
app.listen(3000);Call a protected endpoint
import { AgentClient } from 'trustagent/client';
const client = new AgentClient({
privateKey: Buffer.from(myPrivateKey, 'hex'),
publicKey: myPublicKey
});
const data = await client.call({
url: 'https://other-agent.com/api/data',
method: 'GET'
});Core Concepts
How Verification Works
- Client sends
X-Agent-PublicKeyheader +X-Agent-Signature(Ed25519) - Server verifies the signature cryptographically
- Server queries SelfClaw (
selfclaw.ai) to confirm the agent is human-verified - Server queries ERC-8004 (Celo blockchain) to get the agent's reputation score
- Request is allowed or denied based on your configuration
Identity Layer: SelfClaw
SelfClaw provides ZK-proof based passport verification for AI agents. An agent with a SelfClaw identity is cryptographically linked to a real human passport holder.
Reputation Layer: ERC-8004
ERC-8004 is an on-chain reputation standard deployed on Celo. Agents accumulate reputation through verified feedback from other agents and users. Scores are transparent, tamper-proof, and queryable by anyone.
Middleware
createGateway
The simplest way to protect your routes. Creates a pre-configured middleware stack.
import { createGateway } from 'trustagent';
const gateway = createGateway({
selfClawVerify: true,
reputationGating: {
enabled: true,
minScore: 50 // block agents with score < 50
},
dynamicRateLimits: true,
rateLimitTiers: {
high: 1000, // score >= 80: 1000 req/hour
medium: 500, // score >= 50: 500 req/hour
low: 100, // score >= 20: 100 req/hour
unrated: 50 // no reputation: 50 req/hour
}
});
// Apply to specific route
app.get('/premium', ...gateway.middleware(), handler);
// Apply to all routes under a prefix
app.use('/api', ...gateway.middleware());verifySelfClaw
Verifies the agent has a SelfClaw identity linked to a real passport. Blocks unverified agents with 401.
import { verifySelfClaw } from 'trustagent';
app.get('/secure', verifySelfClaw, (req, res) => {
// req.agent is now available
res.json({
agent: req.agent.agentName,
humanId: req.agent.humanId,
verified: req.agent.verified
});
});Headers Required:
| Header | Description |
|--------|-------------|
| X-Agent-PublicKey | Agent's Ed25519 public key (hex) |
| X-Agent-Signature | Ed25519 signature of the request |
| X-Timestamp | Unix timestamp (ms) |
| X-Nonce | Random nonce (replay protection) |
checkReputation
Queries ERC-8004 on Celo for the agent's reputation score. Attaches req.reputation. Does not block — use requireReputation for that.
import { checkReputation } from 'trustagent';
app.get('/data',
verifySelfClaw,
checkReputation, // attaches req.reputation
(req, res) => {
const score = req.reputation.averageScore; // 0-100
const count = req.reputation.totalFeedback;
res.json({ score, count });
}
);requireReputation
Blocks agents below a minimum reputation score. Must be used after checkReputation.
import { verifySelfClaw, checkReputation, requireReputation } from 'trustagent';
// Free tier - all verified agents
app.get('/free', verifySelfClaw, handler);
// Pro tier - reputation >= 50
app.get('/pro', verifySelfClaw, checkReputation, requireReputation(50), handler);
// Enterprise tier - reputation >= 80
app.get('/enterprise', verifySelfClaw, checkReputation, requireReputation(80), handler);Response when blocked:
{
"error": "Insufficient reputation",
"details": "Minimum score required: 50",
"currentScore": 25,
"totalFeedback": 3,
"hint": "Build reputation by providing quality services"
}reputationRateLimit
Applies dynamic rate limits based on the agent's reputation score. Higher reputation = more requests.
import { reputationRateLimit } from 'trustagent';
app.get('/api',
verifySelfClaw,
checkReputation,
reputationRateLimit({
high: 1000, // score >= 80
medium: 500, // score >= 50
low: 100, // score >= 20
unrated: 50 // no reputation
}),
handler
);optionalVerification
Like verifySelfClaw but non-blocking. Attaches req.agent if the agent is verified, continues regardless.
import { optionalVerification } from 'trustagent';
app.get('/public',
optionalVerification,
(req, res) => {
if (req.agent) {
// Verified agent - show personalized content
res.json({ message: `Hello ${req.agent.agentName}!` });
} else {
// Anonymous request - show default content
res.json({ message: 'Hello!' });
}
}
);Agent Client
Use AgentClient to call other agents' protected endpoints. Handles Ed25519 signing automatically.
import { AgentClient } from 'trustagent/client';
import fs from 'fs';
// Load your agent keys
const keys = JSON.parse(fs.readFileSync('agent-keys.json', 'utf8'));
const client = new AgentClient({
privateKey: Buffer.from(keys.privateKey, 'hex'),
publicKey: keys.publicKey
});
// Make an authenticated GET request
const result = await client.call({
url: 'https://weather-agent.com/api/weather/Lagos',
method: 'GET'
});
// Make an authenticated POST request
const analysis = await client.call({
url: 'https://data-agent.com/api/analyze',
method: 'POST',
body: { data: myData },
timeout: 30000
});
// Check your own verification status
const isVerified = await client.checkVerification();
// Get your reputation
const reputation = await client.getReputation();
console.log('Score:', reputation.summary.averageScore);Agent Registration
Register your agent on the ERC-8004 Identity Registry to get an on-chain identity (ERC-721 NFT).
import { AgentRegistration } from 'trustagent';
const registration = new AgentRegistration({
network: 'sepolia' // 'sepolia' | 'mainnet'
});
const result = await registration.register(
process.env.CELO_PRIVATE_KEY,
{
name: 'My Weather Agent',
description: 'Provides real-time weather data for AI agents',
capabilities: ['weather-api', 'forecast', 'historical-data'],
endpoint: 'https://my-weather-agent.com',
publicKey: myPublicKey,
version: '1.0.0'
}
);
console.log('Agent ID:', result.agentId);
console.log('View on 8004scan:', result.scanUrl);
console.log('TX Hash:', result.txHash);Registration result:
{
agentId: 127,
walletAddress: '0xABC...',
txHash: '0xDEF...',
network: 'mainnet',
chainId: 42220,
scanUrl: 'https://8004scan.io/agents/celo/127',
explorerUrl: 'https://celoscan.io/tx/0xDEF...',
registeredAt: '2025-02-17T12:00:00.000Z'
}Reputation Feedback
Submit and query feedback on the ERC-8004 Reputation Registry.
import { ReputationFeedback } from 'trustagent';
const feedback = new ReputationFeedback({
network: 'mainnet' // 'sepolia' | 'mainnet'
});
// Submit feedback after interacting with an agent
await feedback.submit(
process.env.CELO_PRIVATE_KEY,
{
agentId: 127n,
score: 85, // 0-100
category: 'reliability',
subcategory: 'uptime',
endpoint: '/api/weather',
feedbackURI: 'ipfs://...' // optional: detailed feedback on IPFS
}
);
// Get reputation summary
const summary = await feedback.getSummary(127n, {
category: 'reliability'
});
console.log('Average Score:', summary.averageScore);
console.log('Total Feedback:', summary.count);
// Get all individual feedback entries
const allFeedback = await feedback.getAllFeedback(127n);
allFeedback.forEach(fb => {
console.log(`${fb.client}: ${fb.score}/100 (${fb.tag1})`);
});
// Get all clients who gave feedback
const clients = await feedback.getClients(127n);Request Extensions
After middleware runs, req is extended with:
interface AgentRequest extends Request {
// Set by verifySelfClaw
agent?: {
verified: boolean;
publicKey: string;
agentName: string;
humanId: string;
selfxyz?: { verified: boolean };
reputation?: {
hasErc8004: boolean;
erc8004TokenId: string;
};
};
// Set by checkReputation
reputation?: {
totalFeedback: number;
averageScore: number; // 0-100
lastUpdated?: number;
};
// Raw values from headers
agentPublicKey?: string;
agentSignature?: string;
}Configuration
Full TrustAgentConfig
interface TrustAgentConfig {
// Enable SelfClaw identity verification (default: true)
selfClawVerify?: boolean;
// Reputation gating settings
reputationGating?: {
enabled: boolean;
minScore?: number; // 0-100, block below this score
requireVerified?: boolean;
};
// Enable dynamic rate limits (default: true)
dynamicRateLimits?: boolean;
// Custom rate limit tiers (requests/hour)
rateLimitTiers?: {
high: number; // score >= 80
medium: number; // score >= 50
low: number; // score >= 20
unrated: number; // no reputation
};
// Custom error messages
errorMessages?: {
notVerified?: string;
lowReputation?: string;
rateLimitExceeded?: string;
};
}Rate Limit Tiers
| Reputation Score | Tier | Default Limit | |-----------------|------|---------------| | Score ≥ 80 | HIGH | 1,000 req/hour | | Score 50–79 | MEDIUM | 500 req/hour | | Score 20–49 | LOW | 100 req/hour | | Score < 20 or unrated | UNRATED | 50 req/hour |
Error Reference
| HTTP | Error | Cause |
|------|-------|-------|
| 401 | Missing agent public key | No X-Agent-PublicKey header |
| 401 | Invalid signature | Signature verification failed |
| 403 | Agent not verified | Not registered with SelfClaw |
| 403 | Agent not registered with SelfClaw | Public key not found in SelfClaw |
| 403 | Insufficient reputation | Score below minScore |
| 429 | Rate limit exceeded | Too many requests for reputation tier |
| 500 | Verification failed | SelfClaw or blockchain unreachable |
Networks
| Network | Chain ID | Identity Registry | Reputation Registry |
|---------|----------|------------------|---------------------|
| Celo Mainnet | 42220 | 0x8004A169... | 0x8004BAa1... |
| Celo Sepolia | 11142220 | 0x8004A818... | 0x8004B663... |
Examples
Tiered API Access
import express from 'express';
import { verifySelfClaw, checkReputation, requireReputation, reputationRateLimit } from 'trustagent';
const app = express();
// Public - no auth
app.get('/api/public', handler);
// Verified only
app.get('/api/basic',
verifySelfClaw,
handler
);
// Reputation >= 50
app.get('/api/pro',
verifySelfClaw,
checkReputation,
requireReputation(50),
reputationRateLimit(),
handler
);
// Reputation >= 80
app.get('/api/enterprise',
verifySelfClaw,
checkReputation,
requireReputation(80),
reputationRateLimit({ high: 5000, medium: 1000, low: 200, unrated: 0 }),
handler
);Agent-to-Agent Marketplace
// Provider agent
import { createGateway } from 'trustagent';
const gateway = createGateway({
reputationGating: { enabled: true, minScore: 30 },
dynamicRateLimits: true
});
app.post('/api/analyze',
...gateway.middleware(),
async (req, res) => {
const price = req.reputation.averageScore >= 80
? 0.001 // Discount for trusted agents
: 0.01; // Full price for new agents
const result = await processData(req.body);
res.json({ result, price, yourReputation: req.reputation.averageScore });
}
);// Consumer agent
import { AgentClient } from 'trustagent/client';
const client = new AgentClient({ privateKey, publicKey });
const { result, price } = await client.call({
url: 'https://provider-agent.com/api/analyze',
method: 'POST',
body: { data: myData }
});Auto-Submit Reputation After Calls
import { AgentClient, ReputationFeedback } from 'trustagent';
const client = new AgentClient({ privateKey, publicKey });
const feedback = new ReputationFeedback({ network: 'mainnet' });
async function callAndRate(agentId: number, url: string) {
const start = Date.now();
try {
const result = await client.call({ url, method: 'GET' });
const responseTime = Date.now() - start;
// Auto-submit positive feedback
await feedback.submit(process.env.CELO_PRIVATE_KEY, {
agentId: BigInt(agentId),
score: responseTime < 1000 ? 90 : 70,
category: 'reliability',
endpoint: new URL(url).pathname
});
return result;
} catch (error) {
// Submit negative feedback
await feedback.submit(process.env.CELO_PRIVATE_KEY, {
agentId: BigInt(agentId),
score: 20,
category: 'reliability'
});
throw error;
}
}Register Your Agent (CLI-style script)
// register.js
import { AgentRegistration } from 'trustagent';
import 'dotenv/config';
const reg = new AgentRegistration({ network: 'mainnet' });
const result = await reg.register(process.env.CELO_PRIVATE_KEY, {
name: 'My Agent',
description: 'Does useful things for other agents',
capabilities: ['data-analysis', 'api-calls'],
endpoint: 'https://my-agent.com',
publicKey: process.env.AGENT_PUBLIC_KEY
});
console.log('Registered! Agent ID:', result.agentId);
console.log('View:', result.scanUrl);node register.js
# Registered! Agent ID: 128
# View: https://8004scan.io/agents/celo/128Publishing to npm
Step 1: Prepare the Package
cd trustagent
# Make sure it builds cleanly
npm run build
# Check what will be published
npm pack --dry-runStep 2: Update package.json
{
"name": "trustagent",
"version": "0.1.0",
"description": "Trust enforcement middleware for AI agents on Celo",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"import": "./dist/index.js",
"types": "./dist/index.d.ts"
},
"./client": {
"import": "./dist/client/index.js",
"types": "./dist/client/index.d.ts"
}
},
"files": ["dist", "README.md", "LICENSE"],
"keywords": [
"ai-agents", "celo", "erc-8004", "reputation",
"selfclaw", "middleware", "web3", "blockchain"
],
"author": "Your Name",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/yourusername/trustagent"
}
}Step 3: Publish
# Create npm account if needed
npm login
# Publish
npm publish --access public
# Verify
npm info trustagentStep 4: Version Updates
npm version patch # 0.1.0 → 0.1.1 (bug fix)
npm version minor # 0.1.0 → 0.2.0 (new feature)
npm version major # 0.1.0 → 1.0.0 (breaking change)
npm publishLicense
MIT © 2025 Romario Kavin
Links
- 8004scan — ERC-8004 Agent Explorer
- SelfClaw — Agent Identity Verification
- Celo — Mobile-first EVM blockchain
- ERC-8004 Standard — Reputation standard spec
