Documentation
These calls match the running API. A write is confirmed only after a Monad receipt is indexed.
What is AgentTrace?
AgentTrace gives an AI agent a persistent identity, a firewall for what that agent may do, and a verifiable history of what it actually did on Monad.
Identity, permissions, executions, proofs, and outcomes are separate. A successful execution is not an outcome. An outcome is not a score.
Architecture
Human accounts use Google sign-in. That session is not a wallet and not an agent. A wallet is requested only when a chain transaction is submitted.
The registry, firewall, and proof contracts are the source of chain state. The database is an index of events the indexer has observed. If a contract address is not configured, the API returns a failed status and null ids. It does not invent a transaction hash.
Verified history is aggregated from indexed executions, receipt checks, and outcome rows. It is not stored as a mutable score and there is no ranking.
Quickstart
- Create an API key. Copy it then. It is not shown again.
- Use the SDK in this repository. agenttrace-monad is packaged for npm but not yet published.
- Create an agent. Until the registry is deployed, the response is failed, with a null agent id and a null transaction hash.
- Create a firewall the same way. No firewall id is assigned without a confirmed createFirewall receipt.
- Execute only through firewalls.execute. There is no direct-execution method.
- Wait for a proof. The SDK stops at its timeout and does not report a receipt as verified unless the verifier did.
- Verify an outcome with EVENT_EMITTED and a Solidity event signature. Demo Protocol state checks need source, field, and expectedValue. Other shapes are rejected.
import { AgentTrace } from "agenttrace-monad";
const agenttrace = new AgentTrace({
apiKey: process.env.AGENTTRACE_API_KEY,
network: "monad-testnet",
baseUrl: process.env.AGENTTRACE_BASE_URL,
});
const agent = await agenttrace.agents.create({
name: "Research Agent",
description: "AI research agent",
capabilities: ["Research", "Data"],
});
// agent.status is "failed" and agent.agentId is null
// while the registry contract is not deployed.Authentication
Send Authorization: Bearer and the API key. Keys in the query string are rejected. Development keys start with at_test_. Production keys start with at_live_. Revoked keys return 401.
Public reads accept missing keys at a lower rate limit. Writes require a key. Limits are per minute: 60 without a key, 300 with a valid key. A 429 includes Retry-After.
Agent identity
POST /api/v1/agents accepts name, description, and capabilities (Trading, DeFi, Payments, Yield, Research, Data, Social, Gaming, Other). Names are matched without case. The API does not submit the registry transaction.
If you already broadcast registerAgent, send that transaction hash. Status stays pending until the receipt is readable, and confirmed only when AgentRegistered is indexed. A hash the RPC cannot find is not confirmation.
GET /api/v1/agents/:id returns the indexed agent or AGENT_NOT_FOUND. PATCH does not change indexed fields and does not send a transaction.
Firewalls
POST /api/v1/firewalls takes agentId, executor, and policy (value transfer flag, per-transaction limit, period limit, period duration). Without a deployed firewall contract the status is failed and no id is returned.
POST /api/v1/firewalls/:id/targets and /functions describe an allow-list change. They do not write the policy unless a confirmed owner transaction is supplied, which this API does not send.
Execution
POST /api/v1/firewalls/:id/execute checks the indexed pause flag, target, selector, and value limits. A rejected call returns executionId: null and no transaction hash.
A call that matches policy still is not sent: there is no executor signer on the server. The response code is CHAIN_WRITE_UNAVAILABLE. The firewall is not bypassed.
GET /api/v1/executions/:id returns an indexed AgentAction. A reverted firewall call is absent.
Proofs
GET /api/v1/proofs/:executionId and POST /api/v1/proofs/:executionId/verify use the receipt verifier. Verify does not accept a transaction hash. Status stays one of executed, requested, receipt_verified, unverifiable, or temporary_error.
proofs.waitForVerification polls with backoff for at most 120 seconds.
Outcomes
Supported expectation: EVENT_EMITTED with eventSignature, for example Deposited(uint256,uint256). The event name alone is rejected. Conditions accept greater-than, less-than, and equality comparisons. Demo Protocol also accepts VALUE_CHANGED, BALANCE_CHANGED, and STATE_CHANGED for deposits or swapped when expectedValue is the exact onchain value. Other sources are not verified.
The verdict is read from the execution receipt. failed means a condition was not met. unverifiable means the receipt or the log could not be judged. Neither is stored as verified.
Webhooks
Create a webhook with POST /api/v1/webhooks. The signing secret is in that response only. Delivered events: execution.executed, proof.verified, proof.unverifiable, outcome.verified, outcome.failed, outcome.unverifiable.
{
"id": "evt_…",
"type": "proof.verified",
"createdAt": "…",
"data": { "executionId": "…", "agentId": "…", "proofHash": "…" }
}Verify X-AgentTrace-Signature against the raw body.
const ok = agenttrace.webhooks.verifySignature(rawBody, signature, secret);
SDK
Construct new AgentTrace({ apiKey, network: "monad-testnet", baseUrl }). baseUrl is required in Node. Network values other than Monad testnet throw before any request.
Methods: agents.create, agents.get, agents.update, firewalls.create, firewalls.get, firewalls.targets.allow, firewalls.functions.allow, firewalls.execute, executions.get, proofs.get, proofs.verify, proofs.waitForVerification, outcomes.get, outcomes.verify, webhooks.verifySignature.
REST API
- POST /api/v1/agents
- GET /api/v1/agents/:id
- PATCH /api/v1/agents/:id
- POST /api/v1/firewalls
- GET /api/v1/firewalls/:id
- POST /api/v1/firewalls/:id/execute
- POST /api/v1/firewalls/:id/targets
- POST /api/v1/firewalls/:id/functions
- GET /api/v1/executions/:id
- GET /api/v1/proofs/:executionId
- POST /api/v1/proofs/:executionId/verify
- GET /api/v1/outcomes/:executionId
- POST /api/v1/outcomes/:executionId/verify
- GET /api/v1/webhooks
- POST /api/v1/webhooks
- DELETE /api/v1/webhooks/:id
Errors use { "error": { "code", "message" } }. Write calls that cannot be confirmed also include status: "failed" and null ids.
Errors
AGENT_NOT_FOUND, UNAUTHORIZED, FIREWALL_NOT_FOUND, FIREWALL_PAUSED, FIREWALL_INACTIVE, TARGET_NOT_ALLOWED, FUNCTION_NOT_ALLOWED, VALUE_LIMIT_EXCEEDED, EXECUTION_FAILED, EXECUTION_NOT_FOUND, PROOF_NOT_FOUND, PROOF_TIMEOUT, OUTCOME_UNSUPPORTED, REGISTRY_NOT_DEPLOYED, FIREWALL_NOT_DEPLOYED, CHAIN_WRITE_UNAVAILABLE, CHAIN_UNAVAILABLE, RATE_LIMITED, INVALID_REQUEST, MAINNET_UNAVAILABLE
Monad testnet
Chain id 10143. RPC https://testnet-rpc.monad.xyz. Explorer https://testnet.monadvision.com. Mainnet is not deployed from this app and is not accepted by the SDK.
Contract addresses come from one configuration record. A null address means that contract is not deployed. These values are not placeholders.
- AgentRegistry 0xfa66d202dae4b7fb9aa5c6ee80390ca8bb48739e
- AgentFirewall 0x694178a2396b54bff6a25caa0aa9cca6eb079441
- AgentProof 0x3ea5602072d6028f569f45ea164d5cbe36cbbd3e
- DemoProtocol 0x1664be58ee54af91c756428f466bad6e4f9911c3
Security
API keys are shown once and stored as a hash. They are not accepted in the query string. Webhook secrets stay on the server. Private keys are not in the client bundle.
Firewall checks in the API read the indexed policy and refuse the call. They do not replace the contract. The server has no executor key, so a matching policy still returns CHAIN_WRITE_UNAVAILABLE instead of a fabricated transaction.
Proof verification recomputes the receipt. It does not accept a caller-supplied proof hash. Outcome status is written only after that receipt check. Reputation has no write API.