v0.1 · agent action manifest · live

What can I do?

The first question every agent asks. The protocol for the agent web. When an AI agent calls your service, whatcanido hands it a manifest, a federated key, and a coin slot at the door. Five primitives. One JSON file at /.well-known/agent-actions.json. No platform between you and the agent.

MIT specJWKS-pinned identityx402 + stripe railssigned manifests
5
primitives
9
tenants live
4
vertical SaaS
2
payment rails
RS256
manifest signing
MIT
spec license
01five primitives

Everything an agent needs at the door.

whatcanido is one product made of five composable parts. Adopt any one without the others; or run the whole stack and ship in an afternoon.

01 / studio

Studio

Describe your service in chat. Studio designs the resources, actions, and AAM manifest. Iterate by talking. Ship by clicking. Hot-reload, no migrations.

Open Studio
02 / identity

Identity

One sign-in, every door. AAM ID is the JWKS-pinned credential the agent carries from site to site. Verified locally, federated, never re-authed.

See the key
03 / discover

Discover

A federated map of every agent-callable service we know about. Yours, ours, the neighbours'. Agents read it when they don't know where to knock.

Open the atlas
04 / payments

Payments

Two rails. x402 for cents-per-call. Stripe Connect for booking-grade flows. Both run before the action does, so the door never opens for free.

See the slot
05 / audit

Audit

Every visit gets a stamp. Who came, what scope, did they pay, did the door stick. Read it back by user-hash. Trust accrues across the network.

Read the log
appendix / spec

The Protocol

AAM v0.1 is open and MIT. Reference SDK in TypeScript, conformance suite for any implementer, signed manifests over RS256 JWS. Portable by design.

Read the spec
02on the wire

A small contract, plain JSON.

Every AAM site publishes one file at a fixed path. The agent fetches it on demand — no platform installation, no agent-side memory pollution, no proprietary library.

  • aam_versionSpec version. v0.1 is the current contract.
  • siteName, domain, description. What humans and agents see first.
  • authIdentity proofs accepted: AAM ID JWKS, OAuth handoff, none.
  • actions[]Each: id, params schema, scopes, optional pricing.
  • aam_signatureDetached JWS over the canonical body. Tamper-evident.
  • security_notesUntrusted-content marker convention for IPI defense.
GET https://whatcanido.dev/b/tadeas-reads/.well-known/agent-actions.json200 OK
{
  "aam_version": "0.1",
  "site": {
    "name": "Tadeáš's Reading List",
    "domain": "whatcanido.dev",
    "description": "Personal reading log..."
  },
  "auth": {
    "type": "delegated_oauth",
    "accepted_identity_proofs": [{
      "type": "aam_id",
      "issuer": "https://whatcanido.dev",
      "jwks_url": "/.well-known/aam-jwks.json"
    }]
  },
  "actions": [
    { "id": "list_books",       "access": "public" },
    { "id": "search_books",     "access": "public" },
    { "id": "add_book",         "auth_required": true },
    { "id": "tip_the_curator",  "pricing": "paid",
      "payment": {
        "scheme": "x402",
        "network": "base-sepolia",
        "amount": "0.005",
        "pay_to": "0x209693…287C"
      }
    }
  ],
  "aam_signature": {
    "alg": "RS256",
    "kid": "whatcanido-2026-05",
    "digest": "1a28bb681dcb…",
    "signature": "eyJhbGciOiJSUzI1NiIs…"
  }
}
03request flow

One round-trip when the agent has the key.

  1. 01
    Agent fetches the manifest.
    GET /.well-known/agent-actions.json. Returns the action list, parameter schemas, payment rails, and identity proofs accepted.
    GET 200
  2. 02
    Lock asks for a key, if any.
    Auth-gated actions return 401 with a connect_url and the JWKS the agent should pin against. No platform call required.
    401
  3. 03
    Agent presents an AAM ID JWT.
    RS256, signed by the issuer, verified locally by the site. Per-tenant scope; cross-tenant replay rejected.
    Bearer
  4. 04
    Toll, if there is one.
    Paid actions return 402 with an x402 USDC challenge or a Stripe Connect intent. Agent signs, retries, walks in.
    402
  5. 05
    Service runs the action.
    Your typed dispatcher executes against jsonb storage. JSON comes back. Untrusted fields wrapped in IPI markers.
    POST 200
  6. 06
    Visit gets stamped.
    An audit row lands: who, what scope, paid, latency, outcome. User-hash only. Aggregated into the reputation graph.
    audit++
live on the protocol · 9 deployments
04live demos

Three doors you can knock on right now.

Public reads, no setup. Curl them, paste them into Claude, run the included x402 demo script. See what an agent finds when it lands.

/b/tadeas-readspublic · auth · paid

Reading list

Personal book log with public reads, AAM ID gated writes, and an x402 paid tip jar that stamps the payer on the row.

7 actions·x402 0.005 USDC
/b/tadeas-consultpublic · auth

Freelance consulting

Booking calendar with a required topic field. Public slot listing, gated booking via AAM ID. Booking acts on a per-resource scope.

2 actions·AAM ID scope
/b/kitchen-vaultpublic · auth

Recipe vault

Tag-able, ingredient-search, prep-time-filter. The kind of thing you ask an agent at 7pm. Free-text search across title + ingredients + notes.

3 actions·full-text search
05try it
# read what's on offer
$ curl https://whatcanido.dev/b/tadeas-reads/.well-known/agent-actions.json | jq .actions[].id

"list_books"
"search_books"
"add_book"
"update_book"
"remove_book"
"tip_the_curator"
"list_tips"
# call a public action
$ curl https://whatcanido.dev/api/b/tadeas-reads/list_books

{
  "ok": true,
  "count": 3,
  "books": [
    { "id": "b_x1...", "title": "The Pragmatic Programmer",
      "author": "David Thomas, Andrew Hunt",
      "status": "finished", "rating": 5 },
    ...
  ]
}
# pay 0.005 USDC at the door (x402, base-sepolia)
$ npm run x402:demo  -- --base whatcanido.dev

[1] POST /api/b/tadeas-reads/tip_the_curator           HTTP 402
    challenge: { network: base-sepolia, pay_to: 0x2096…287C, amount: 0.005 }
[2] sign  EIP-3009 TransferWithAuthorization           viem.signTypedData()
[3] POST  with X-Payment: base64(proof)                HTTP 201
    record: { id: "rec_z4...", payer: "0xf39F…6266", amount_usdc: "0.005" }

✓ Door opened. Tip recorded.