How we built a custom Switch-protocol agent that helps a running club make footwear decisions — private in-browser measurement, signed fit passports, human approval, and honest stock checks.
A running club is picking shoes for a weekend relay. The chat is doing what chats do: "get the Pegasus, trust me", "UK 9 or 9.5??", "just buy two sizes and return one". Forty messages of confident opinions — zero data on how anyone actually moves.
This is the problem we built vertiqal's Switch integration to solve for the Flip the Switch hackathon: not a bot that posts shoe links, but a room where a team decision gets made with evidence — and where the agent is a participant that answers to the humans in it.
The privacy constraint that shaped everything
Our product measures how you move — cadence, foot strike, overstride for running; reach, hip position and precision for climbing — from a short clip or live camera. The core promise: the video never leaves your browser. MediaPipe pose runs entirely on-device.
So posting movement video into a chat room was never an option — it would break the product's own line. What travels instead is a signed fit passport: an HMAC-signed token carrying the metrics, signals, size and profile. The room sees the receipt; the footage stays on the laptop.
That one constraint turned out to be the whole design. The agent doesn't get footage to interpret — it gets a verifiable artifact. If the measurements are wrong, the signature is checkable against the issuing endpoint (GET /api/passport/<token>).
The agent: a custom Switch client, no coding-agent credits
We didn't have Claude Code or Codex credits, so we wrote the agent ourselves — switch/room-agent.mjs, a ~400-line Node script with zero dependencies that speaks the Switch agent protocol directly: WebSocket in for room frames, HTTP ops out for posting. The only model calls happen inside vertiqal's own endpoints, which the agent orchestrates (a Featherless/Nebius chain — resiliency matters more than one good provider).
The workflow in the room:
- A teammate shares a passport — either pasting the link or clicking Send to team room in the app, which posts it via
/api/room-share. - The agent fetches and verifies it, then posts a human-readable summary: "Demo road runner at 164 spm with rearfoot strike and 14cm overstride — seeking cushioned daily-mileage shoes."
- It waits. Nothing runs until a human types
approve £140. The approval gate is the point — the agent can't spend money or even search on its own authority. - On approval it runs the real fitting: catalogue search, measurement-grounded picks with retailer links.
- Then the honest bit: it checks stock on the retailers' own pages, and when a cookie modal or a 403 blocks verification it says "stock: unclear — we never guess."
- Final plan lands in the room with every receipt attached. With two passports in the room it even proposes a relay order (a cadence heuristic, labelled as such).
What the room looks like
This is a real Mattermost channel (#relay-fitting), not a mockup — two teammates worked the whole flow on camera for the demo: one shares the passport, another approves the budget, the agent posts back between them.
There's also a check <shoe> command — paste a product name and the agent scores it against the latest passport via the signed fit-verdict endpoint. Second approval loop, same receipts.
The kicker: it refuses to guess (WIP)
Any demo can show an agent returning shoe links. Ours shows it coming back and saying "the size is on the page — a cookie modal blocks me from confirming it. Verdict: unclear." A fabricated success is worth less than an honest failure, and in a shared room the honesty is what makes the receipts worth anything. Judges kept telling us this was the moment they trusted the rest of it.
Protocol notes for the next builder
A few things we learned the hard way on real Switch (v0.31.0), now written up in switch/README.md:
- Frames are
{event, data}— not{type, payload}— and message fields nest one level deeper underdata.payload. - You must claim rooms on open (
rooms=[...]in the connect frame) or you see no room events at all. - Your own posts don't echo back to you — keep a local context fallback or your state machine stalls.
- Addressing policy defaults to opt-in — we set
anyonevia the Gateway'sPUT /agents/{id}/addressing-policy(cookie auth). -
thread_idis accepted on the message route but renders flat in the Mattermost bridge today — plan for flat replies.
To iterate without Switch at all we built pnpm switch:mock, a 100-line stand-in (registration, WS, posting, /inject to fake room messages). Whole loop runs on localhost.
What I'd like Switch to do next
The protocol is genuinely thin — writing a client took an afternoon. Three wishes: thread support that actually renders in the bridge; a signed-receipt primitive so agents can attach verifiable provenance to their posts (we had to bring our own HMAC); and tunnel/console reconnection affordances — ours dropped mid-demo once.
Try it
- Repo:
github.com/thisyearnofear/vertiqal—switch/README.mdis the runbook - Live app:
vertiqal.vercel.app - 78-second demo video: linked in the repo README
The bigger idea, if you zoom out: any purchase a group makes together — team kit, club gear, shared equipment — follows the same shape. Measure privately, carry a signed receipt, decide in the room. Shoes were just the proof.






![[CVE-2026-123158] *sshole : How Two Unrelated '*' Strings Broke OpenSSH on musl](https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fynqp1ja78wh3r8tfey9q.png)