# A Marketplace Invited Us to Bid From Scratch. Here Is the Full Trace, Including the Bugs

> Published: 2026-10-23 | Author: AgentBadge Team | Canonical: https://agentbadge.xyz/blog/gec-interop-field-report

## A demand that onboards itself

SaSame's GEC (Global Ecosystem) marketplace put a demand on its [public board](https://sasame.online/gec): prove that an independent external agent can walk their live production path — keyless discovery, wallet authentication, MCP session — and place a real bid. No registration flow, no sales call, no API key hand-out. Just a self-describing spec embedded in the demand itself.

We took the challenge with a throwaway wallet holding zero funds, one ~600-line script and no SDK. On 2026-10-23 the full loop completed: a read-only dry run through gec_open_demands (10 open demands), then a live gec_bid_submit — **bid 5ae9fd03…fc3 accepted, state SUBMITTED, 5,000,000 microUSDC**. Every step was recorded into redacted transcripts containing zero secrets. This is the field report.

![GEC projection page — open demands with embedded machine_entry spec](/images/blog/gec-interop-projection.webp)

## Their architecture, seen through our lens

GEC's model: Projects publish **OutcomeDemands** (budget cap in microUSDC + acceptance criteria + required capabilities), external providers place **Bids**, delivery is verified, payment settles. Two MCP surfaces split the trust boundary:

- **Public MCP** (/public-mcp) — keyless discovery: gec_open_demands, start_here, audit_mcp. Anyone's agent can browse.

- **User MCP** (/mcp) — wallet-bound participant actions: gec_bid_submit, gec_demand_search, award/deliverable/verification tools. 18 tools behind OAuth 2.1 + EIP-191 wallet proof.

The elegant part: every open demand carries a provider_action.machine_entry object — endpoints, chain id, cookie policy and a numbered step list. We implemented the client *from the projection alone*.

![Trust boundary diagram: keyless Public MCP zone (gec_open_demands, machine_entry, start_here) above an OAuth 2.1 PKCE + EIP-191 + consent gate, below it the wallet-bound User MCP zone (mcp-session-id, gec_bid_submit, idempotency fields)](/images/blog/gec-interop-d2.webp)

![Split composition: keyless public side with open demand cards versus wallet-bound side with a vault door — the agent crosses via OAuth 2.1 PKCE](/images/blog/gec-interop-2s.webp)

## The walk, step by step (real timings)

| # | Step | Endpoint | Result |
| --- | --- | --- | --- |
| 1 | Keyless demand projection | GET /api/gec/open-demands | 200, 918ms — 10 demands |
| 2 | OAuth authorize (PKCE S256, CIMD client_id) | GET /authorize | 302, ~1.1s → Account Control |
| 3 | Wallet challenge | POST …/wallet/challenge | 201, 320ms |
| 4 | EIP-191 personal_sign | local — never logged | — |
| 5 | Signature verify | POST …/wallet/verify | 200, 307ms |
| 6 | Participant consent → callback | POST …/participant-consent | 303+302, code+state |
| 7 | Token exchange (form-encoded) | POST /token | 200, ~305ms |
| 8 | MCP initialize (bearer) | POST /mcp | 200, mcp-session-id |
| 9 | tools/list | POST /mcp | 200, 894ms — bid schema |
| 10 | gec_open_demands | POST /public-mcp | 200, 310ms — 10 demands |
| 11 | gec_bid_submit | POST /mcp | 200, 900ms — SUBMITTED |

Total wall-clock for the write path: under 5 seconds of network time.

![Sequence diagram of the full run: projection, authorize, wallet challenge, local EIP-191 sign, verify, consent, token, MCP initialize, tools/list, public read gate, gec_bid_submit SUBMITTED](/images/blog/gec-interop-d1.webp)

![Terminal run of --phase=bid — all steps green, bid id echoed](/images/blog/gec-interop-terminal-bid.webp)

## Friction table — spec vs. production

Every stumble, with the fix. All were response-level discoveries; none blocked the flow.

| # | What the spec implied | What production wanted | Fix |
| --- | --- | --- | --- |
| 1 | "your EVM address" | JSON field wallet_address, not address | renamed — invalid_wallet_address gone |
| 2 | sign "the challenge" | message at challenge.message; verify wants all fields echoed | echo fields + signature |
| 3 | JSON POST to /token | RFC 6749 form-urlencoded | content-type swap — JSON got a bare 500 |
| 4 | call tools after initialize | mcp-session-id header on every call | echoed from initialize |
| 5 | tools work immediately | notifications/initialized first | else: misleading "Tool not found" |
| 6 | gec_open_demands on User MCP | lives on keyless **public-mcp** | read-side on /public-mcp |
| 7 | MCP returns JSON | text/event-stream (SSE) | unwrap data: payload |
| 8 | follow redirects | manual redirects — cookies leak otherwise | redirect:manual + replay |

![The agent stepping over eight small labeled pebbles — field-name, form-post, session-id, initialized-note, public-mcp, sse-unwrap, manual-redirect, challenge-echo — each turning from amber to cyan](/images/blog/gec-interop-3s.webp)

**What impressed us:** machine_entry self-describing onboarding, per-demand bid_constraints (machine-checkable before writing), idempotent gec_bid_submit (idempotency_key + duplicate flag + request_sha256), structuredContent next to content[], and an honest disclosure stance — "a Demand or budget cap is not proof of reserved funds or payment".

## What it cost

![Burner wallet: 0 ETH, 0 USDC on Base — personal_sign is gas-free](/images/blog/gec-interop-balance.webp)

Zero. The entire flow is off-chain HTTP plus one local EIP-191 signature. The burner wallet holds **0 ETH / 0 USDC on Base mainnet** (RPC-verified). Worst case if anything broke: a failed bid, not lost funds.

## What we are taking home

- **CIMD as a standard façade** — /.well-known/gec-client.json with client_id=self-URL is ~60 lines and replaces app registration. We're generalizing it for other marketplaces.

- **Bounded+redacted evidence model** — transcripts record response *shape*, secrets become <redacted>; publishable evidence by construction.

- **machine_entry in our own projections** — self-describing onboarding is the strongest DX move we saw.

- **Idempotent write pattern** — idempotency_key + duplicate flag belongs in our submit tools.

## Honest limits

- **One demand, one bid, one day** — this proves the path works, not that the market is liquid.

- **The bid is a commitment of work** (deliverable = this evidence + friction report), not a payment made.

- **Sibling demands carry MUST_EQUAL_ZERO rules** — read per-demand constraints, never assume.

- **Raw JSON-RPC, no SDK** — a real MCP SDK may handle session headers differently.

## Try it yourself

Their board is public: [sasame.online/gec](https://sasame.online/gec) — the keyless projection shows every open demand with its machine_entry. If you can do PKCE + EIP-191 + JSON-RPC, you can bid. Full redacted transcripts and the friction report live in our evidence bundle.

*Standalone field report — not part of the Arc Campaign series (different stack: SaSame GEC on Base). For our own interop work see [C33: A2A protocol](https://agentbadge.xyz/blog/arc-c33-a2a-protocol) and [C30: agent economy](https://agentbadge.xyz/blog/arc-c30-agent-economy).*

---

## For AI Agents

- Companion guide: https://agentbadge.xyz/agent-guide/articles/gec-interop-field-report
- Knowledge Index: https://agentbadge.xyz/agent-guide/
- LLM entry point: https://agentbadge.xyz/llms.txt
- Engineering services: https://agentbadge.xyz/agent-guide/team/services
