369 DEVELOPER DOCS
Publish an agent to the 369 Agent Store and reach every 369 wallet user. You implement one signed HTTPS endpoint — we handle distribution, payments, and on-device approval. Anyone can register an agent on-chain; getting listed in the store is reviewed, and only agents that meet the 369 Agent Spec are approved.
On-chain registration is permissionless. Store listing is curated — 369 reviews submissions before they appear in the catalog. Registration is briefly paused while we finalize the spec and review pipeline.
ERC-8004 identity·90% creator revenue·EIP-712 signed responses·No custody, ever
WHY 369
369 is a non-custodial wallet. Agents don't move funds; they make recommendations the user approves on-device. That trust model is why people install agents at all — and why a listing here is worth earning.
Your agent shows up where decisions happen — inside the wallet, next to the user's balances and approvals. No separate app, no audience to acquire.
Charge per run in USDC or offer it free. You earn 90% of every paid run, settled on-chain to your owner wallet. No invoices, no held balances.
No mobile code, no user key management, no payment integration. Implement a single signed HTTPS endpoint that returns text and cards.
OPEN · Registration is permissionless
Calling registerAgent on the ERC-8004 IdentityRegistry is open to anyone. Your agent gets an on-chain identity and a tamper-evident manifest the moment you register.
REVIEWED · Listing is curated
Appearing in the 369 catalog is reviewed for a valid manifest, a working signed endpoint, the correct tier, honest pricing, and safe behavior. Only approved agents are listed.
HOW IT WORKS
The 369 mobile app never calls your endpoint directly. All traffic flows through the 369 Agent Gateway, which signs requests to you, verifies your signed response, and only then shows anything to the user. The user makes the final on-device decision.
In the 369 app, a user runs your agent. The Gateway creates a usageId, hashes the request, and sends your endpoint a gateway-signed request — including only the permitted, data-minimized context your manifest declares.
Within 6 seconds, your endpoint returns a JSON envelope (≤256 KB) containing text and cards — no transactions. You sign it with EIP-712 over the 369AgentResponse domain, using your declared response-signing key.
The Gateway checks your signature, validates the schema, confirms provenance (the echoed usageId and requestHash), and recomputes the responseHash. Anything that fails verification never reaches the user.
The user sees a verified recommendation and approves or ignores it. If your agent is paid, settlement happens non-custodially on-chain — your 90% is paid out automatically. Nothing stateful happens without the user's own signature.
Treat every agent response as an untrusted recommendation. The user always holds the keys and makes the final signature.
SPECIFICATION
An agent is a manifest plus a signed HTTPS endpoint. The manifest is pinned to IPFS and referenced on-chain (getAgent().metadataURI) so it's tamper-evident — what we reviewed is exactly what runs. Fields marked MVP-locked must hold the stated value to pass review.
Submissions that set any locked flag to true are rejected automatically.
{
"name": "Approval Sentinel",
"version": "1.0.0",
"slug": "approval-sentinel",
"description": "Scans a wallet for risky ERC-20/NFT approvals and advises which to revoke. Read-only — it can never move funds.",
"category": "security",
"supportedChains": [8453],
"capabilities": ["approval-scan", "revoke-advice"],
"permissions": { "canReadBalance": true, "canPrepareTransaction": false, "canSign": false, "canMoveFunds": false },
"riskTier": 3,
"endpoint": "https://agents.acme.xyz/sentinel/run",
"responseSigning": { "type": "eip712", "publicKey": "0xResponseSignerKeyDistinctFromOwner" },
"storeProfile": {
"category": "security",
"tagline": "Find risky approvals. Revoke with confidence.",
"icon": "shield-checkmark",
"accent": "#06B6D4",
"pricing": { "model": "per_run", "priceMicro": 50000 }
}
}operator/owner are set from your SIWE session at submit; networks[] is filled by the register flow per chain. The manifest is pinned to IPFS and referenced on-chain via metadataURI — editing it changes the CID, so material changes require re-registration and re-review. The full field-by-field spec lives in AGENT_SPEC.md.
ENDPOINT CONTRACT
Executable agents implement one HTTPS endpoint. It receives a gateway-signed request and must return a signed envelope. The Gateway verifies everything before the user sees a thing.
POST https://your-endpoint/run
X-369-Gateway-Signature: <eip712 sig by the Gateway signer>
{
"usageId": "0x9f8c…", // unique per run; echo back verbatim
"agentId": 42, // your on-chain agent id
"requestHash": "0x4b2a…", // keccak256 of the canonical request; echo
"ts": 1764700000, // unix seconds; reject if skew > 60s
"context": { // OPTIONAL, permitted fields only
"chainId": 8453,
"address": "0xUser…", // only if canReadBalance granted
"input": { "…": "agent-specific" }
}
}200 OK · Content-Type: application/json
{
"usageId": "0x9f8c…", // echo — MUST match
"agentId": 42, // echo — MUST match
"requestHash": "0x4b2a…", // echo — MUST match
"responseHash": "0x77de…", // keccak256(canonicalJSON(content))
"version": "1.0.0", // your manifest version
"ts": 1764700003, // unix seconds, your signing time
"content": {
"text": "3 risky approvals found…",
"cards": [ /* text + cards only — NO transactions */ ]
},
"signature": "0xEIP712…" // 369AgentResponse, signed by responseSigning key
}const domain = {
name: "369AgentResponse",
version: "1",
chainId: 8453, // the run's chainId
verifyingContract: "0x0000000000000000000000000000000000000369"
};
const types = {
AgentResponse: [
{ name: "usageId", type: "bytes32" },
{ name: "agentId", type: "uint256" },
{ name: "requestHash", type: "bytes32" },
{ name: "responseHash", type: "bytes32" },
{ name: "version", type: "string" },
{ name: "ts", type: "uint256" }
]
};
// sign with responseSigning.publicKey's key — NOT the owner wallet
const signature = await signer.signTypedData({
domain, types, primaryType: "AgentResponse",
message: { usageId, agentId, requestHash, responseHash, version, ts }
});If verification fails — bad signature, wrong hash, schema mismatch, timeout — the run is rejected and the user sees nothing. Build defensively; sign every response.
BUILDING WITH LLMS
Many of the best agents are LLM-powered. If you host your own model, the rules are the same as any endpoint agent: the Gateway sends you a signed request, you return a signed envelope of text and cards within 6 seconds and 256 KB, and the user signs nothing the agent didn't earn.
The whole turn — model + any RPC/tool reads + signing — must finish in 6 s. Use a fast small model for advisory/security, and set a hard model timeout below 5 s. The Gateway receives one non-streaming JSON envelope (no token streaming in v1).
Cap output tokens, summarize, and put structure in cards rather than long prose. The body is text + cards only — never transactions.
On-chain data (token names, approval labels, memos) can prompt-inject your model. Never let model output decide a permission, destination, or price. In MVP the agent can only inform/advise, so a hijacked model misleads text — it never moves funds. Escape chain/user text before it enters the prompt.
The LLM produces content; YOUR server computes responseHash = keccak256(canonicalJSON(content)) and signs the 369AgentResponse with your responseSigning key. The model never touches the key.
// 1. verify X-369-Gateway-Signature BEFORE any model call
// 2. build a prompt from req.context ONLY (data-minimized, escaped)
const out = await llm.generate({
system: AGENT_SYSTEM_PROMPT,
input: sanitize(req.context), // strip chain/user text injection
maxOutputTokens: 400,
timeoutMs: 4500, // whole turn must finish < 6 s
});
const content = { text: out.text.slice(0, 1200), cards: out.cards ?? [] };
const responseHash = keccak256(canonicalJSON(content));
// YOUR server signs — the model never touches the key
const signature = await signer.signTypedData({
domain, types, primaryType: "AgentResponse",
message: { usageId, agentId, requestHash, responseHash, version, ts },
});
return json({ usageId, agentId, requestHash, responseHash, version, ts, content, signature });Cost is yours to manage: the user pays your per-run price; your inference bill comes out of your 90%. Price so a paid run more than covers a model call — or run free and monetize reputation.
PROMPT-ONLY AGENTS
Don't want to host anything? Ship a prompt-only agent. You write a system prompt, declare your capabilities, permissions, and price — and 369 runs the inference on the same rail that powers our built-in agents. No endpoint, no signing key, no servers, no uptime. You get distribution, metering, and your share of every paid turn.
You host a signed HTTPS endpoint. Full control of model, tools, and data — and you manage uptime + the EIP-712 key. Free or paid; you keep 90%.
369 hosts the model. You ship a system prompt + declarations — no endpoint, key, or uptime. Must be paid (369 covers inference); you keep 70%.
{
"name": "Gas Coach",
"version": "1.0.0",
"agentType": "prompt",
"description": "Read-only advisory agent that explains your gas spend and suggests cheaper timing.",
"category": "research",
"supportedChains": [8453],
"capabilities": ["gas-analysis", "timing-advice"],
"permissions": { "canReadBalance": true, "canPrepareTransaction": false, "canSign": false, "canMoveFunds": false },
"riskTier": 2,
"aiProfile": {
"systemPrompt": "You are Gas Coach, a read-only advisory agent. Explain the user's gas spend and suggest cheaper timing. You NEVER move funds, sign, or prepare transactions; if asked, decline and say you are advisory-only.",
"model": "default",
"tools": ["getArcHistory"],
"greeting": "Want to spend less on gas? Ask me anything."
},
"storeProfile": {
"category": "research",
"tagline": "Understand your gas. Spend less.",
"icon": "sparkles",
"accent": "#06B6D4",
"pricing": { "model": "per_run", "priceMicro": 20000 }
}
}369 loads your systemPrompt as the persona on its hosted model. Each turn is metered — your per-run price is debited in USDC and your share settles on-chain; the platform absorbs the token cost out of its 30%.
Tiers 1–3 only, read-only — no tx/sign/move. Declared tools are capability-gated; write-class tools aren't listable in MVP.
Your systemPrompt is pinned to IPFS and reviewed; changing it needs a new CID + re-review. We screen for jailbreaks, fund-movement instructions, and deceptive advice. The user controls every on-device signature.
Prompt-only is the fastest way to ship: no infrastructure, same review bar. Start here, graduate to a self-hosted endpoint when you need a custom model or private data.
MODEL CONTEXT PROTOCOL
369 will support agents that expose a Model Context Protocol server as an alternative to the HTTPS signed-envelope contract. The trust model is unchanged: the Gateway is the MCP client, signs every tools/call to you, and verifies an EIP-712-signed result before the user sees anything. In v1 the field is reserved and documented, but only protocol: "http" is accepted at review — build the HTTPS version today.
You already run an MCP server with read-only tools, or you want the Gateway's LLM to call your tools directly. Same tiers 1–3, same read-only scope, same on-device user signature.
HTTPS only · JSON · ≤256 KB result · 6 s per tools/call. EIP-712 369AgentResponse signed by your responseSigning key (≠ owner). The 7 Gateway checks still run; provenance rides in the result. Text + cards only — no transactions, resources, or prompts.
{
"name": "Approval Sentinel (MCP)",
"version": "1.0.0",
"agentType": "endpoint",
"category": "security",
"supportedChains": [8453],
"permissions": { "canReadBalance": true, "canPrepareTransaction": false, "canSign": false, "canMoveFunds": false },
"riskTier": 3,
"endpoint": { "protocol": "mcp", "url": "https://agents.acme.xyz/mcp" },
"responseSigning": { "type": "eip712", "publicKey": "0xResponseSignerKeyDistinctFromOwner" }
}Every declared MCP tool must map to a permissions{} flag and be read-only. The Gateway pins your tool list at review — adding undeclared tools after approval fails verification. Submitting protocol: "mcp" before MCP ships is rejected; ship the HTTPS signed-envelope version today.
PRICING & EARNINGS
Choose your model per agent. There are no listing fees, no monthly costs, and no held balances — 369 never custodies your earnings.
Charge nothing per run. Good for growth, reputation, or agents you monetize elsewhere. Still fully reviewed and listed like any agent.
Set a price from 0.01 to 1.00 USDC per run. The user pays only when they invoke your agent. Paid in Base USDC on mainnet, Arc USDC on testnet.
90%
Your share of every paid run
10%
Platform fee
On-chain
Non-custodial — paid to your owner wallet automatically
There is no claim or withdrawal step. Settlement is automatic and on-chain to your payout address, which is your on-chain owner wallet. On submit, the price is encoded as priceMicro = round(priceUsdc × 1e6).
REVIEW & CURATION
On-chain registration through the ERC-8004 IdentityRegistry is permissionless — your agent exists on-chain the moment you register. Appearing in the 369 Agent Store catalog is separate and curated. Every submission is reviewed by 369, and only approved agents are listed. Think App Store: open identity, reviewed listing.
We aim to give every submission a first decision within 3 business days. Most agents need at least one round of changes — we'll tell you exactly what to fix, and you can resubmit immediately with no penalty. Complex or novel agents may take longer.
Register on-chain → submit for review → 369 review (manifest + live endpoint signature/schema/SSRF/health) → approved → listed. Healthy agents rank higher.
Listing is not permanent. Agents that fail health checks are demoted, then marked Offline, and may be delisted until they recover. Reputation is earned from real on-chain validated runs (ERC-8004 ValidationRegistry) and runner-gated feedback — only people who actually ran your agent can rate it. The platform never slashes reputation.
AGENT TIERS
MVP accepts agents that inform and advise. None of them can move funds — every recommendation is approved by the user on-device. We'll expand scope deliberately, after the trust model is proven.
riskTier 1
Market data, research, news, and RWA discovery. Read-only context in, text and cards out.
Price feeds · protocol research · RWA listings · news digests.
Read-only · user signsriskTier 2
Portfolio analysis, risk scoring, and yield comparison. Reads balances you permit; never acts on them.
Portfolio health · risk score · yield/APR comparison.
Read-only · user signsriskTier 3
Finds risky approvals and advises revocation. It identifies the problem and recommends the fix — it cannot execute it.
Approval scanners · revoke advisors · exposure checks.
Read-only · user signs✕ Not accepted in MVP
Agents that prepare transactions, sign on the user's behalf, or move funds — including contract executors, vaults, traders, and bridges — are rejected for now. canPrepareTransaction, canSign, and canMoveFunds must all be false. Build the read-only advisory version today and the user keeps the final signature.
FAQ
Yes. On-chain registration is permissionless and you only pay network gas. There are no listing fees and no platform subscription.
Identity is open so the ecosystem stays permissionless. The 369 store catalog is curated so users can trust what they install. Anyone can register an agent on-chain; only agents that pass review appear in the store.
We aim for a first decision within 3 business days. Most agents need one round of fixes — we tell you exactly what to change and you resubmit with no penalty. It's an aim, not a guarantee.
Not in MVP. canPrepareTransaction, canSign, and canMoveFunds must all be false. Agents inform and advise; the user signs on-device. Build the read-only version today.
Free or 0.01–1.00 USDC per run. You earn 90%, settled non-custodially on-chain to your owner wallet, automatically. No claim or withdrawal step.
No. All traffic goes through the 369 Agent Gateway, which signs requests to you and verifies your signed responses before anything reaches the user.
responseSigning.publicKey signs your endpoint's responses (EIP-712, 369AgentResponse domain). Your on-chain owner wallet holds identity and receives payouts. Keep them separate — a leaked signing key never touches custody or earnings.
The Gateway health-checks uptime and latency. Failures demote your ranking, then show an Offline badge, and can lead to delisting until you recover. Reputation from past real runs is never slashed.
Yes, but the manifest is pinned to IPFS and referenced on-chain, so material changes produce a new CID and require re-registration and re-review. Minor operational changes behind a stable endpoint don't.
Base USDC on mainnet and Arc USDC on testnet in v1.
Register your agent on-chain, submit it for review, and reach every 369 wallet user. Free to start. Non-custodial. You keep 90%.
Connect wallet → SIWE sign-in → submit manifest → IPFS pin → registerAgent → review → listed. We review every submission and list only approved agents.