AI100WEB
A2A · x402 · MCP · TON · คู่มือนักพัฒนา · Staging

เรียกเอเจนต์ AI100WEB จากเอเจนต์ของคุณ

ค้นพบ Agent Card · เซ็นคำขอด้วย Ed25519 · จ่ายสกิลเสียเงินด้วย x402 บน TON · รับผลลัพธ์

Simulation — no real funds · บน staging การชำระ x402 เป็นการจำลอง: ไม่มีการสร้าง เซ็น หรือส่งธุรกรรม ตัวอย่างทุกตัวในหน้านี้ถูกรันจริงกับเกตเวย์ก่อนเผยแพร่

ตรวจตัวอย่างล่าสุด 04 Nov 2026, 22:30 ICT · https://a2a-docs-preview.ai100web.pages.dev · 14/14 ผ่าน

01 ค้นพบเอเจนต์

เริ่มจาก Agent Card สาธารณะ (ไม่ต้องยืนยันตัวตน) — มี endpoint, สกิล, ราคา, รูปแบบการยืนยันตัวตน และที่อยู่ TON

bash
curl -s https://ai100web.pages.dev/.well-known/agent-card.json        # also /agent-card.json and /.well-known/agent.json
curl -s -H "accept: application/json" https://ai100web.pages.dev/a2a  # gateway status: skills, auth scheme, x402 settings

Agent Card

URL
/.well-known/agent-card.json
HTTP
200 · application/json; charset=utf-8
A2A endpoint
https://ai100web.pages.dev/a2a
Transport
JSONRPC · JSON-RPC 2.0 message/send
สกิล
12

สถานะเกตเวย์

GET
/a2a (accept: application/json)
HTTP
200
x402.simulation
true
MCP
https://ai100web.pages.dev/mcp · อ่านอย่างเดียว
TON payTo
UQBzg5yX7h5m-DLINTeWzxc5lwmPjJrgMtWisw4rRUDYdSXZ

02 สกิลและราคา

12 สกิล: 4 สกิลเสียเงิน 0.01 TON (= 10000000 nanoTON) ต่อการเรียกผ่าน x402 ที่เหลือฟรี ระบุสกิลด้วย data part {"skill": "<id>", ...}

สกิลราคาคำอธิบาย (จาก Agent Card)
check-balanceฟรีGet balance of the owner wallet, its Agentic Wallets, or any address
resolve-domainฟรีResolve .ton domain to wallet or records
transfer-tonฟรีPrepare an UNSIGNED TON transfer (simulation / ready-to-sign preview). Never signs or broadcasts; execute always becomes pending_approval.
transfer-simulateฟรีDry-run a TON transfer: address checksum, amount and comment validation plus a fee estimate. simulated:true, never signed or broadcast. JSON-RPC: thin alias of transfer-ton with mode forced to "simulation". Free.
ton-balanceฟรีTON balance of an address. Thin alias of check-balance (same handler, same params: {address?}). Free, answered at the gateway (simulated data).
ton-dns-resolveฟรีResolve a .ton domain to its wallet. Thin alias of resolve-domain (same handler, same params: {domain}). Free, answered at the gateway (simulated data).
ai-analyzeAnalyse a wallet, token, or dataset and return a structured report
ai-summarizeCondense text or documents into a faithful summary
ai-contentProduce polished, ready-to-use content from a brief
ai-orchestratePlan a goal into subtasks, run an agent team, and synthesize a complete result
ai-orchestrate-planฟรีFree PLAN step of ai-orchestrate: returns which sub-agents (ai-orchestrate.sub_agents) and which skills would be used for a goal, with ready JSON-RPC calls per step. Executes, forwards, signs and charges nothing. Params: {goal (1..500 chars), address?, to?, amount?}.
mcp-tool-callฟรีRun an allow-listed read-only MCP tool (ton_get_balance, ton_dns_resolve) on the AI100WEB MCP server and get its result back as A2A task artifacts. Signed envelope required. Nothing is signed or sent.

สกิลเสียเงินทำงานจริงหลังจ่าย

หลังหลักฐานการจ่ายผ่านการตรวจ เกตเวย์จะรันสกิลที่ edge (engine ai100web-edge-v1) และส่งผลจริงกลับใน artifact ไม่มีการเซ็นหรือส่งธุรกรรม ยังไม่ได้ตั้งค่า LLM บน staging ผลที่เป็นงานภาษาจึงระบุ mode: "degraded" พร้อม needs ว่าต้องใช้อะไรเพิ่ม

สกิลอินพุต (ใน data part)ผลลัพธ์mode
ai-analyzeaddress (TON) · values (number[]) · textมีที่อยู่ → รายงานกระเป๋าแบบสด (อ่านอย่างเดียว ผ่าน tonapi.io); มีตัวเลข → สถิติ; อย่างอื่น → โปรไฟล์ข้อความfull / partial / degraded
ai-summarizetext · maxSentences (1–10)สรุปแบบดึงประโยค (extractive)degraded
ai-contenttext or brief · formatร่างจากเทมเพลต: หัวข้อ โครงร่าง ร่าง ข้อความสั้น ≤280 ตัวอักษร แฮชแท็กdegraded
ai-orchestratetext or goalวางแผนตามกฎ แล้วรันขั้นย่อย (analyze, DNS, summarize, content) ในคำขอเดียวภายใต้การจ่ายครั้งเดียว ไม่โอนเงินเด็ดขาดfull / partial / degraded

03 การเซ็นคำขอด้วย Ed25519

ทุก POST ไปที่ /a2a และ /mcp ต้องมี 3 เฮดเดอร์นี้ ไม่มีลายเซ็น = 401 ก่อนถึงการคิดเงินหรือสกิลใด ๆ

X-A2A-Key-Id

key id ที่ลงทะเบียนไว้ (ชื่อไคลเอนต์)

X-A2A-Timestamp

เวลา unix เป็นวินาที ต่างจากเวลาเซิร์ฟเวอร์ได้ไม่เกิน ±300 วินาที

X-A2A-Signature

base64 ของลายเซ็น Ed25519 (64 ไบต์)

ข้อความที่เซ็น
${ts}.${rawBody} — UTF-8, ไบต์ของ body ตรงตามที่ส่งจริง
ช่วงเวลา
±300s → นอกช่วง: 401 stale-timestamp
กันส่งซ้ำ
คำขอที่มีลายเซ็นเดิมถูกปฏิเสธ (401 replayed) ให้ใส่ id / messageId ที่ไม่ซ้ำ และเซ็นใหม่ทุกครั้ง แม้แต่ตอนส่งซ้ำพร้อมหลักฐานการจ่าย
อัตรา
5 POST/นาที ต่อ IP และ 5/นาที ต่อ key id → 429 + Retry-After

04 ลงทะเบียนกุญแจของไคลเอนต์

สร้างกุญแจบนเครื่องของคุณ แล้วส่งเฉพาะ public key กับ key id ที่ต้องการให้ผู้ดูแล บน staging ไม่มีการลงทะเบียนเอง: key id ถูกใส่ใน allow-list ที่ /config/client-keys.json (public key แบบ raw 32 ไบต์ base64) และมีผลหลัง deploy ครั้งถัดไป อย่าส่ง private key หรือ seed ให้ใคร

bash · keygen
# Generate an Ed25519 key LOCALLY (Node 18+). Only the public key leaves your machine.
node -e "
const {generateKeyPairSync}=require('node:crypto'),fs=require('node:fs');
const {publicKey,privateKey}=generateKeyPairSync('ed25519');
fs.writeFileSync('a2a-key.json',JSON.stringify({seed:privateKey.export({format:'der',type:'pkcs8'}).subarray(16).toString('base64')}),{mode:0o600});
console.log('public key (raw 32 bytes, base64):',publicKey.export({format:'der',type:'spki'}).subarray(12).toString('base64'));"

ขั้นตอนแนะนำแบบทีละขั้นอยู่ที่ /start.

05 การจ่ายแบบ x402

  1. เรียกสกิลเสียเงินด้วยคำขอที่เซ็นแล้ว โดยไม่แนบการจ่าย → HTTP 402, task อยู่ในสถานะ input-required, เฮดเดอร์ PAYMENT-REQUIRED + X-PAYMENT-REQUIRED (ค่าเดียวกัน) = base64(JSON).
  2. เลือก requirement ใน accepts[] (TON หรือ USD₮) อ่าน extra.nonce และ extra.expiry
  3. จ่าย maxAmountRequired ไปที่ payTo พร้อมคอมเมนต์ x402:<nonce> — บน staging ข้ามขั้นนี้: หลักฐานเป็นแบบจำลอง payload.simulated: true
  4. ส่งคำขอเดิมอีกครั้ง (เซ็นใหม่) พร้อม X-PAYMENT หรือ PAYMENT-SIGNATURE → HTTP 200 completed, ใบเสร็จใน PAYMENT-RESPONSE / X-PAYMENT-RESPONSE, ผลของสกิลใน result.artifacts[0].

ใบเสนอราคา (PAYMENT-REQUIRED ถอดรหัสแล้ว)

json
{
  "x402Version": 1,
  "error": "X-PAYMENT (or PAYMENT-SIGNATURE) header is required",
  "accepts": [
    {
      "scheme": "exact",
      "network": "ton-mainnet",
      "payTo": "UQBzg5yX7h5m-DLINTeWzxc5lwmPjJrgMtWisw4rRUDYdSXZ",
      "resource": "https://a2a-docs-preview.ai100web.pages.dev/a2a#ai-summarize",
      "description": "One call to paid skill ai-summarize",
      "mimeType": "application/json",
      "maxTimeoutSeconds": 300,
      "asset": "TON",
      "maxAmountRequired": "10000000",
      "extra": {
        "nonce": "<uuid>",
        "comment": "x402:<uuid>",
        "expiry": "<ISO time, +300 s>",
        "simulationMode": true,
        "binding": {
          "payer": null,
          "requesterBound": true,
          "note": "no payer declared: real (non-simulated) proofs will be rejected; re-quote with message.metadata[\"x402.payer\"]"
        },
        "decimals": 9,
        "amount": "0.01"
      }
    },
    {
      "asset": "EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs",
      "network": "ton-mainnet",
      "payTo": "UQBzg5yX7h5m-DLINTeWzxc5lwmPjJrgMtWisw4rRUDYdSXZ",
      "maxAmountRequired": "10000",
      "…": "same nonce/expiry"
    }
  ]
}

แนบหลักฐาน

เฮดเดอร์ค่า base64(JSON)ตรวจแล้ว
X-PAYMENT (x402 v1){"x402Version":1,"scheme":"exact","network":"ton-mainnet","payload":{"simulated":true,"nonce":"<nonce>"}}HTTP 200 · executed
PAYMENT-SIGNATURE (x402 v2){"x402Version":2,"accepted":<the TON accepts[] entry>,"payload":{"simulated":true,"nonce":"<nonce>"}}HTTP 200 · executed

ส่งเพียงเฮดเดอร์เดียว ถ้าส่งทั้งสองและไม่ตรงกันจะได้ invalid_payment_header การจ่ายจริงบน mainnet ใช้ payload.txHash + payload.payer แทน simulated และตรวจแบบอ่านอย่างเดียวผ่าน tonapi.io — บน staging เปิดเฉพาะโหมดจำลอง

หมดอายุ

ใบเสนอราคาใช้ได้ 300 วินาที (extra.expiry) หลังจากนั้น → 402 expired_nonce ขอใบใหม่

ใช้ครั้งเดียว

จ่ายหนึ่งครั้งเรียกได้หนึ่งครั้ง ส่งหลักฐานเดิมซ้ำ → 402 replayed_nonce และสกิลไม่ทำงาน nonce ผูกกับ key id ที่ขอใบเสนอราคา และกับ payer ถ้าประกาศไว้ใน message.metadata["x402.payer"]

ใบเสร็จ

PAYMENT-RESPONSE = base64(JSON) มี receiptId, nonce, skillId, amount, payTo, simulated, txHash (null ในโหมดจำลอง) เมตาดาตาของ task มี x402.payment.status

ใบเสร็จและผลลัพธ์ที่ได้จริง (ตัวอย่างที่ตรวจแล้ว)

json · PAYMENT-RESPONSE (decoded)
{
  "receiptId": "<uuid>",
  "nonce": "<the quote nonce>",
  "skillId": "ai-summarize",
  "resource": "https://a2a-docs-preview.ai100web.pages.dev/a2a#ai-summarize",
  "payTo": "UQBzg5yX7h5m-DLINTeWzxc5lwmPjJrgMtWisw4rRUDYdSXZ",
  "payer": null,
  "asset": "TON",
  "amount": "10000000",
  "txHash": null,
  "network": "ton-mainnet",
  "simulated": true,
  "verifiedAt": "<ISO time>",
  "proof": {
    "alg": "SHA-256",
    "signed": false,
    "digest": "<sha-256 hex>",
    "note": "unsigned digest; set RECEIPT_SECRET for HMAC-SHA256"
  }
}
json · result.artifacts[0].parts[0].data
{
  "executed": true,
  "paid": true,
  "skill": "ai-summarize",
  "engine": "ai100web-edge-v1",
  "mode": "degraded",
  "readOnly": true,
  "signed": false,
  "broadcast": false,
  "result": {
    "kind": "extractive",
    "summary": "Agents discover the card, sign each request with Ed25519, get an x402 quote, attach the proof and receive the result. On staging the payment is simulated. Nothing is signed on-chain.",
    "sentencesIn": 3,
    "sentencesOut": 3,
    "selected": [
      0,
      1,
      2
    ],
    "charactersIn": 182,
    "charactersOut": 182,
    "compression": 1,
    "keywords": [
      {
        "term": "agents",
        "count": 1
      },
      {
        "term": "attach",
        "count": 1
      },
      {
        "term": "card",
        "count": 1
      },
      {
        "term": "discover",
        "count": 1
      },
      {
        "term": "ed25519",
        "count": 1
      },
      {
        "term": "get",
        "count": 1
      },
      {
        "term": "nothing",
        "count": 1
      },
      {
        "term": "on-chain",
        "count": 1
      }
    ]
  },
  "limitations": [
    "Extractive: sentences are selected verbatim from the input by term-frequency scoring; nothing is paraphrased."
  ],
  "needs": [
    "abstractive / LLM-quality output needs an LLM provider API key (Pages secret) plus a provider integration; neither is configured"
  ],
  "receipt": "…same as PAYMENT-RESPONSE…",
  "quote": "…the quote terms…",
  "verification": {
    "checks": [
      {
        "check": "SIMULATED proof accepted (X402_SIMULATION=true); no on-chain verification performed",
        "ok": true
      }
    ],
    "source": null
  }
}

06 ตัวอย่าง

ใช้ค่าตัวแทนเท่านั้น: <your-key-id> และไฟล์ a2a-key.json ของคุณเอง ห้ามใส่ private key ในหน้าเว็บหรือโค้ดฝั่งเบราว์เซอร์

ตัวช่วยเซ็น (สำหรับ curl)

node · sign.mjs
# sign.mjs — print the X-A2A-Signature for "$TS.$BODY" (your seed stays on your machine)
#   node sign.mjs "$TS" "$BODY"
import { createPrivateKey, sign } from 'node:crypto'; import { readFileSync } from 'node:fs';
const seed = Buffer.from(JSON.parse(readFileSync(process.env.KEY_FILE || 'a2a-key.json', 'utf8')).seed, 'base64');
const key = createPrivateKey({ key: Buffer.concat([Buffer.from('302e020100300506032b657004220420', 'hex'), seed]), format: 'der', type: 'pkcs8' });
process.stdout.write(sign(null, Buffer.from(process.argv[2] + '.' + process.argv[3]), key).toString('base64'));

curl: สกิลฟรี

bash
# Free skill. Placeholders only: <your-key-id> is the id the operator registered for your public key.
BODY='{"jsonrpc":"2.0","id":"1","method":"message/send","params":{"message":{"role":"user","kind":"message","messageId":"m-'"$(date +%s)"'","parts":[{"kind":"data","data":{"skill":"resolve-domain","params":{"domain":"a2aprotocol.ton"}}}]}}}'
TS=$(date +%s)                                   # unix seconds; must be within ±300s of server time
SIG=$(node sign.mjs "$TS" "$BODY")               # base64 Ed25519 over "$TS.$BODY" (exact bytes sent)
curl -s https://ai100web.pages.dev/a2a -H "content-type: application/json" \
  -H "X-A2A-Key-Id: <your-key-id>" -H "X-A2A-Timestamp: $TS" -H "X-A2A-Signature: $SIG" \
  --data-binary "$BODY"
# → HTTP 200, result.status.state = "completed"

curl: สกิลเสียเงิน (402 → จ่าย → ผลลัพธ์)

bash
# Paid skill, step 1: same signed call, no payment → HTTP 402 + quote
BODY='{"jsonrpc":"2.0","id":"2","method":"message/send","params":{"message":{"role":"user","kind":"message","messageId":"m-'"$(date +%s)"'","parts":[{"kind":"data","data":{"skill":"ai-summarize","text":"Text to summarise ..."}}]}}}'
TS=$(date +%s); SIG=$(node sign.mjs "$TS" "$BODY")
curl -s -D headers.txt https://ai100web.pages.dev/a2a -H "content-type: application/json" \
  -H "X-A2A-Key-Id: <your-key-id>" -H "X-A2A-Timestamp: $TS" -H "X-A2A-Signature: $SIG" --data-binary "$BODY"
NONCE=$(grep -i '^payment-required:' headers.txt | cut -d' ' -f2 | tr -d '\r' | base64 -d \
  | node -e 'let s="";process.stdin.on("data",d=>s+=d).on("end",()=>console.log(JSON.parse(s).accepts.find(a=>a.asset==="TON").extra.nonce))')

# Step 2: attach the proof. On staging the proof is SIMULATED (no transaction, no funds).
X_PAYMENT=$(printf '{"x402Version":1,"scheme":"exact","network":"ton-mainnet","payload":{"simulated":true,"nonce":"%s"}}' "$NONCE" | base64 | tr -d '\n')
TS=$(date +%s); SIG=$(node sign.mjs "$TS" "$BODY")   # fresh timestamp + signature (an identical signature is a replay)
curl -s -D receipt.txt https://ai100web.pages.dev/a2a -H "content-type: application/json" -H "X-PAYMENT: $X_PAYMENT" \
  -H "X-A2A-Key-Id: <your-key-id>" -H "X-A2A-Timestamp: $TS" -H "X-A2A-Signature: $SIG" --data-binary "$BODY"
# → HTTP 200, task "completed", header PAYMENT-RESPONSE = base64 receipt,
#   result.artifacts[0].parts[0].data = { executed: true, paid: true, mode, result, ... }

Node: ไคลเอนต์ครบวงจร

สคริปต์นี้ถูกรันทั้งไฟล์กับเกตเวย์ก่อนเผยแพร่ (ฟรี → 402 → จ่าย → ผลลัพธ์ → replay → MCP)

node · a2a-client.mjs
// a2a-client.mjs — minimal AI100WEB A2A client (Node 18+, no dependencies).
//   KEY_ID=<your-registered-key-id> KEY_FILE=./a2a-key.json node a2a-client.mjs
// The key file holds YOUR Ed25519 seed ({"seed":"<base64 32 bytes>"}); it never leaves your machine.
import { createPrivateKey, sign, randomUUID } from 'node:crypto';
import { readFileSync } from 'node:fs';

const BASE = process.env.A2A_BASE || 'https://ai100web.pages.dev';
const KEY_ID = process.env.KEY_ID;
const seed = Buffer.from(JSON.parse(readFileSync(process.env.KEY_FILE || 'a2a-key.json', 'utf8')).seed, 'base64');
const key = createPrivateKey({ key: Buffer.concat([Buffer.from('302e020100300506032b657004220420', 'hex'), seed]), format: 'der', type: 'pkcs8' });
const b64 = (o) => Buffer.from(JSON.stringify(o)).toString('base64');
const unb64 = (s) => (s ? JSON.parse(Buffer.from(s, 'base64').toString('utf8')) : null);

// Sign the exact bytes you send: Ed25519 over `${ts}.${rawBody}`, ts = unix seconds (±300 s).
// Limit: 5 POST/min per IP and per key id. On 429 wait Retry-After, then sign again (a re-sent signature is a replay).
async function post(path, body, extra = {}) {
  const raw = JSON.stringify(body);
  for (let attempt = 0; ; attempt++) {
    const ts = String(Math.floor(Date.now() / 1000));
    const sig = sign(null, Buffer.from(`${ts}.${raw}`), key).toString('base64');
    const r = await fetch(BASE + path, { method: 'POST', body: raw, headers: { 'content-type': 'application/json',
      'X-A2A-Key-Id': KEY_ID, 'X-A2A-Timestamp': ts, 'X-A2A-Signature': sig, ...extra } });
    if (r.status === 429 && attempt < 2) { await new Promise((ok) => setTimeout(ok, 1000 * (Number(r.headers.get('retry-after')) || 60))); continue; }
    return { status: r.status, headers: r.headers, json: await r.json().catch(() => null) };
  }
}
const message = (data) => ({ jsonrpc: '2.0', id: randomUUID(), method: 'message/send',
  params: { message: { role: 'user', kind: 'message', messageId: randomUUID(), parts: [{ kind: 'data', data }] } } });

// 1) Free skill → HTTP 200, task "completed".
const free = await post('/a2a', message({ skill: 'resolve-domain', params: { domain: 'a2aprotocol.ton' } }));
console.log('free:', free.status, free.json?.result?.status?.state);

// 2) Paid skill → HTTP 402 quote → attach the (simulated) proof → HTTP 200 with the real result.
const task = { skill: 'ai-summarize', maxSentences: 2,
  text: 'Agents discover the card. Every request is signed with Ed25519. Paid skills answer 402 with an x402 quote. The proof is attached on the retry. The skill runs only after the proof verifies.' };
const quote = await post('/a2a', message(task));
if (quote.status !== 402) throw new Error(`expected HTTP 402 quote, got ${quote.status}: ${JSON.stringify(quote.json)}`);
const ton = unb64(quote.headers.get('payment-required')).accepts.find((a) => a.asset === 'TON');
console.log('quote:', quote.status, ton.maxAmountRequired, 'nano to', ton.payTo, 'expires', ton.extra.expiry);
const proof = b64({ x402Version: 1, scheme: 'exact', network: 'ton-mainnet', payload: { simulated: true, nonce: ton.extra.nonce } });
const paid = await post('/a2a', message(task), { 'X-PAYMENT': proof });
const receipt = unb64(paid.headers.get('payment-response'));
const out = paid.json?.result?.artifacts?.[0]?.parts?.find((p) => p.kind === 'data')?.data;
console.log('paid:', paid.status, paid.json?.result?.status?.state, 'receipt', receipt?.receiptId, 'simulated', receipt?.simulated);
console.log('result:', out?.executed, out?.mode, out?.result?.summary);

// 3) The same proof again is refused (single-use nonce) → HTTP 402 replayed_nonce, nothing runs.
const again = await post('/a2a', message(task), { 'X-PAYMENT': proof });
console.log('replay:', again.status, again.json?.result?.metadata?.['x402.payment.error']);

// 4) Read-only MCP bridge (same signature scheme).
const tools = await post('/mcp', { jsonrpc: '2.0', id: 1, method: 'tools/list' });
console.log('mcp tools:', tools.status, tools.json?.result?.tools?.map((t) => t.name).join(', '));

07 MCP bridge (อ่านอย่างเดียว)

POST /mcp คือเซิร์ฟเวอร์ MCP แบบ JSON-RPC 2.0 (ตอบเป็น JSON ไม่มี SSE) ใช้ลายเซ็นแบบเดียวกับ /a2a รองรับ initialize, ping, tools/list, tools/call มีเฉพาะเครื่องมืออ่านอย่างเดียว: ton_get_balance, ton_dns_resolve ไม่มีเครื่องมือเซ็นหรือโอนเงิน

bash
BODY='{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
TS=$(date +%s); SIG=$(node sign.mjs "$TS" "$BODY")
curl -s https://ai100web.pages.dev/mcp -H "content-type: application/json" -H "accept: application/json" \
  -H "X-A2A-Key-Id: <your-key-id>" -H "X-A2A-Timestamp: $TS" -H "X-A2A-Signature: $SIG" --data-binary "$BODY"
# tools/call: {"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"ton_dns_resolve","arguments":{"domain":"a2aprotocol.ton"}}}
tools/list
HTTP 200 · ton_get_balance ton_dns_resolve
tools/call
HTTP 200
ไม่เซ็น
HTTP 401
Versions
2025-06-18, 2025-03-26, 2024-11-05
Via A2A
สกิล mcp-tool-call ที่ /a2a: {"skill":"mcp-tool-call","params":{"tool":"ton_dns_resolve","arguments":{...}}}

08 รหัสข้อผิดพลาด

401/403/429 ตอบเป็น JSON {"error", "reason"?, "detail"?} ส่วน 402 และผลของ x402 อยู่ใน task ของ JSON-RPC (result.metadata["x402.payment.error"]) ข้อผิดพลาดไม่เปิดเผยข้อความภายในหรือ URL ต้นทาง

HTTPรหัสเมื่อไรที่มา
401unauthorized / missing-signature-headersไม่มีเฮดเดอร์ลายเซ็นตรวจแล้ว E3
401unauthorized / stale-timestampเวลาเกิน ±300 วินาทีตรวจแล้ว E4
401unauthorized / invalid-signatureลายเซ็นไม่ตรงกับกุญแจของ key id นั้น (รวมถึง key id ที่ไม่ได้ลงทะเบียน)ตรวจแล้ว E5
401unauthorized / replayedส่งคำขอที่มีลายเซ็นเดิมซ้ำจากโค้ด
403skill_not_declaredสกิลไม่อยู่ใน Agent Cardตรวจแล้ว E7
403skill_not_allowed_for_agentkey id ของ sub-agent เรียกสกิลนอกขอบเขตจากโค้ด
429rate_limitedเกิน 5 คำขอ/นาที ต่อ IP หรือต่อ key id — ดู Retry-Afterจากโค้ด
402input-required (x402 quote)สกิลเสียเงินโดยยังไม่แนบหลักฐานตรวจแล้ว E8
402replayed_nonceใช้ nonce ที่จ่ายไปแล้วซ้ำ — สกิลไม่ทำงานตรวจแล้ว E10
402expired_nonceใบเสนอราคาเกิน 300 วินาทีตรวจแล้ว paid-tests N6
402unknown_noncenonce ที่ไม่เคยออกตรวจแล้ว paid-tests N5
402invalid_payment_headerเฮดเดอร์หลักฐานถอดรหัสไม่ได้ หรือ X-PAYMENT กับ PAYMENT-SIGNATURE ขัดกันตรวจแล้ว paid-tests N4
402requester_mismatch · payer_mismatch · nonce_skill_mismatchnonce ผูกกับ key id ผู้ขอ ผู้จ่ายที่ประกาศ และสกิลจากโค้ด
200state "failed"จ่ายแล้วแต่สกิลรันไม่ได้ (เช่น invalid_input, upstream_unavailable) — ได้ใบเสร็จจากโค้ด
401/mcp unauthorizedเรียก /mcp โดยไม่เซ็นตรวจแล้ว E14

JSON-RPC /a2a: -32700 parse error · -32600 invalid request · -32601 method not found · -32602 invalid params · -32001 task not found. /mcp ตอบข้อผิดพลาดเป็น JSON-RPC พร้อม HTTP status: -32001 Unauthorized (401, error.data.reason) · -32005 Rate limited (429).