muretai For site owners

For consumer agents

Read. Sign. POST.

One door for Instinct, Meta Muse, Grok Bot, and any principal that can sign.

No Muretai node is required. No invitation is required. The site publishes its terms before contact. Your first verified message opens the account.

The recipe

Four steps, one round trip.

Keep one Ed25519 key for this agent. A new key is a new visitor.

Read the card.

GET https://store.example/.well-known/agent-card.json. Read did, url, skills, and agentEntry.open_door. If the door is not open, stop. For a verified card, GET the signed envelope beside it and verify its signature under the card DID.

Make or load your did:key.

Use an Ed25519 key. The public half is did:key:z + base58btc(0xed01 || publicKey). Keep the private half outside model context and sign at the tool boundary.

Sign the six fields.

Canonicalise exactly contextId, from, messageId, text, timestamp, and to as sorted, compact UTF-8 JSON. Sign those bytes with Ed25519 and encode the signature as base64.

POST message/send.

POST the A2A JSON-RPC body to the card's url. Use your DID as from and the card DID as to. The signed answer or a structured refusal returns on this request.

Signed bytes

The payload and the request.

The JSON-RPC wrapper is not the signed payload. These six values are.

{"contextId":null,"from":"did:key:z6Mk…","messageId":"01J…","text":"Book court 2 at 18:00.","timestamp":1789293600,"to":"did:key:z6MkSTORE…"}
{
  "jsonrpc": "2.0",
  "id": "1",
  "method": "message/send",
  "params": {
    "message": {
      "kind": "message",
      "role": "user",
      "parts": [{"kind": "text", "text": "Book court 2 at 18:00."}],
      "messageId": "01J…",
      "contextId": null,
      "metadata": {
        "timestamp": 1789293600,
        "from": "did:key:z6Mk…",
        "to": "did:key:z6MkSTORE…",
        "sig": "BASE64_ED25519_SIGNATURE"
      }
    }
  }
}

Use the current protocol vectors before shipping an implementation: Agent Entry conformance. Raw request bytes must reach the door unchanged.

Refusals

HTTP success can carry a refusal.

Protocol refusals use HTTP 200 with a JSON-RPC error. Read the envelope before reading the body as a reply.

{
  "jsonrpc": "2.0",
  "id": "1",
  "error": {
    "code": -32001,
    "message": "…",
    "data": {"accepts": {"…": "…"}}
  }
}

Read it in this order.

First read error.code. Then show error.message as the reason. Then inspect error.data for the next usable input. Code -32001 means the request had no signature; data.accepts repeats the accepted scheme from the card. Form a new signed request. Do not send the unchanged request again.

Separate an edge refusal from a door refusal.

A door refusal is JSON-RPC JSON. Plain text, HTML, HTTP 403, or HTTP 1010 is from an intermediary. Report that distinction to the owner; changing signature bytes will not fix a request the door never received.

Access rule

The signature is the admission format.

An open Agent Entry accepts a signed principal regardless of vendor. Instinct membership, Meta membership, a Muretai node, and an invitation are not admission requirements.

The store still decides what its responder will answer, which rate applies, and whether a requested action needs a person.