Skip to main content
Glama

Sato Hub: Build Onchain & Crypto Agents

Change a Sato Passport: sign with a wallet that is on it

onchain_agent_passport_action

USE WHEN an agent already has a Sato Passport and a wallet ON it needs to change it by signing: add or remove a wallet, make a wallet primary, prove the wallet an older passport already lists, update the public profile (name, description, links, built-with), issue a new owner claim code, unlink the owner account, keep a wallet that is waiting to be removed or cancel a waiting claim code. This WRITES. NOT FOR creating a passport (use onchain_agent_join_passport) or reading one (use onchain_agent_get_agent_passport).

ONE TOOL, TEN ACTIONS. action picks the action and the other fields are that action's request: add_wallet { authorizer, wallets }; prove_wallet { wallet }; remove_wallet { authorizer, remove }; set_primary { wallet }; update_profile { authorizer, patch }; issue_claim { wallet, claim_sha256 }; unlink_owner { wallet }; keep_wallet { wallet, keep? }; cancel_claim { wallet }; read_pending { wallet } (a signed read of what is waiting; changes nothing). Each signer is { address, signature }. Leave every signature out and the answer is the exact message to sign and the issued_at to send back, with nothing written; sign with that wallet's key and call again with the signatures.

WHO MAY SIGN: a wallet already on the passport (the new wallets in add_wallet sign too). A request is refused when it is not newer than the passport's last change or was used before. Removing another wallet, changing the primary, unlinking the owner and (with 2 or more wallets) a new claim code take effect 72 hours after signing. WHO CAN CANCEL depends on who asked (owner, then primary wallet, then any other wallet): a removal the primary asked for cannot be cancelled by the wallet being removed, and that wallet can only remove itself meanwhile; a removal another wallet asked for is cancelled by its target only with keep_wallet (no other signature cancels anything) or by the primary; a primary change a wallet asked for is cancelled by the current primary with set_primary for itself; any wallet cancels a waiting claim code with cancel_claim; the owner cancels on satohub.ai, and what the owner asked for only the owner can cancel. A wallet removing itself is immediate. The last wallet and the primary cannot be removed.

WHAT SIGNING PROVES: control of that wallet's key and agreement to a message that says it moves no funds. Nothing about the agent. No action earns points.

LIMIT: 5 write calls an hour per caller; an unsigned call does not count.

RETURNS (json): { ok, action, passport_id, … } per action, with note when a change is waiting; or { ok, step: "sign", messages, issued_at } for an unsigned call. A refusal names a stable code, for example not_authorized, cancel_not_allowed, nothing_pending, under_removal, stale, replay or last_wallet.

Example: { action: "update_profile", passport_id: "sato:agt:…", authorizer: { address: "0x…" }, patch: { description: "Swaps USDC on Base." } }

Input Schema

NameRequiredDescriptionDefault
keepNokeep_wallet: the address of the wallet whose pending removal is cancelled (default: the signing wallet itself; the primary wallet may name any wallet).
patchNoupdate_profile: only the fields to change, exactly as they will be shown (name, description, website_url, x_url, repo_url, docs_url, image_url, built_with { kind, detail? }); null clears a field. The signature covers this patch byte for byte.
actionYesWhich action: add_wallet { authorizer, wallets }, prove_wallet { wallet }, remove_wallet { authorizer, remove }, set_primary { wallet }, update_profile { authorizer, patch }, issue_claim { wallet, claim_sha256 }, unlink_owner { wallet }, keep_wallet { wallet, keep? }, cancel_claim { wallet }, read_pending { wallet } (a signed READ of what is waiting; changes nothing).
removeNoremove_wallet: the address to take off the passport.
walletNoThe wallet that signs (prove_wallet, set_primary, issue_claim, unlink_owner, keep_wallet, cancel_claim, read_pending). It must be on the passport, except for prove_wallet, where it is the wallet an older passport already lists.
walletsNoadd_wallet: the new wallets, each signing too.
issued_atNoISO 8601 UTC with milliseconds, like 2026-10-21T18:04:05.123Z; valid for ten minutes. Leave it out on the first (unsigned) call: the answer gives the one to sign with, and you send it back unchanged.
authorizerNoA wallet already on the passport that authorizes the action (add_wallet, remove_wallet, update_profile).
passport_idYesThe passport the action is for: sato:agt: and 12 characters (the id join_passport returned).
claim_sha256Noissue_claim: the SHA-256 digest of the new owner claim code (64 lower-case hex). With one wallet on the passport it works at once and the earlier unused code stops; with two or more it works after 72 hours (the working code keeps working until then) and another wallet (cancel_claim) or the owner can cancel it.
response_formatNoText format; structuredContent is JSON either way.markdown

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed5 schema fields changed
    • changedInput schema / properties / action / description
      Previous value: -"Which action: add_wallet { authorizer, wallets }, prove_wallet { wallet }, remove_wallet { authorizer, remove }, set_primary { wallet }, update_profile { authorizer, patch }, issue_claim { wallet, claim_sha256 }, unlink_owner { wallet }."New value: +"Which action: add_wallet { authorizer, wallets }, prove_wallet { wallet }, remove_wallet { authorizer, remove }, set_primary { wallet }, update_profile { authorizer, patch }, issue_claim { wallet, claim_sha256 }, unlink_owner { wallet }, keep_wallet { wallet, keep? }, cancel_claim { wallet }, read_pending { wallet } (a signed READ of what is waiting; changes nothing)."
    • changedInput schema / properties / action / enum
      Previous value: -[
      -  "add_wallet",
      -  "prove_wallet",
      -  "remove_wallet",
      -  "set_primary",
      -  "update_profile",
      -  "issue_claim",
      -  "unlink_owner"
      -]New value: +[
      +  "add_wallet",
      +  "prove_wallet",
      +  "remove_wallet",
      +  "set_primary",
      +  "update_profile",
      +  "issue_claim",
      +  "unlink_owner",
      +  "keep_wallet",
      +  "cancel_claim",
      +  "read_pending"
      +]
    • changedInput schema / properties / claim_sha256 / description
      Previous value: -"issue_claim: the SHA-256 digest of the new owner claim code (64 lower-case hex); the earlier unused code stops working."New value: +"issue_claim: the SHA-256 digest of the new owner claim code (64 lower-case hex). With one wallet on the passport it works at once and the earlier unused code stops; with two or more it works after 72 hours (the working code keeps working until then) and another wallet (cancel_claim) or the owner can cancel it."
    • addedInput schema / properties / keep
      Added value: +{
      +  "description": "keep_wallet: the address of the wallet whose pending removal is cancelled (default: the signing wallet itself; the primary wallet may name any wallet).",
      +  "maxLength": 100,
      +  "type": "string"
      +}
    • changedInput schema / properties / wallet / description
      Previous value: -"The wallet that signs (prove_wallet, set_primary, issue_claim, unlink_owner). It must be on the passport, except for prove_wallet, where it is the wallet an older passport already lists."New value: +"The wallet that signs (prove_wallet, set_primary, issue_claim, unlink_owner, keep_wallet, cancel_claim, read_pending). It must be on the passport, except for prove_wallet, where it is the wallet an older passport already lists."
  2. Added

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only give readOnlyHint=false and destructiveHint=false; the description goes far beyond, disclosing the 5-writes-per-hour limit, the 72-hour delay on removals/primary changes/claim codes, the full cancellation hierarchy, replay/staleness refusals, the last-wallet and primary removal guards, and what a signature does and does not prove. These are material behavioral facts an agent could not infer from annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with USE WHEN / NOT FOR / action map / signing rules / returns / example, which is the right order for a 10-action tool. The 'WHO CAN CANCEL' block is a dense chain of nested clauses that is hard to parse in one pass, and some action/field mapping restates the schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 11-parameter, nested-object mutation tool with no output schema, the description supplies the return shapes for both signed and unsigned calls, the sign-step contract, and stable refusal codes. An agent has everything needed to call it correctly on the first attempt.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3, but the description adds cross-parameter meaning the flat schema does not: which fields belong to which action, and the two-step flow where omitting all signatures yields the exact message plus issued_at to return. Some of this duplicates the action enum's own text, which keeps it below a 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb+resource ('change a Sato Passport') and immediately enumerates the ten concrete actions it performs. It explicitly distinguishes itself from the two obvious siblings: creating (onchain_agent_join_passport) and reading (onchain_agent_get_agent_passport).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Opens with 'USE WHEN an agent already has a Sato Passport and a wallet ON it needs to change it', then names both exclusion cases with the alternative tool to use instead. The preconditions (wallet already on the passport, signature flow) are spelled out rather than implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.