Refunds are money. An agent that approves everything is risky, and an agent that asks a human about everything is useless. For the Flip the Switch hackathon I built Refund Desk: three agents that decide the easy cases, stop at the risky ones, and wait for a person.

What it does

Three OpenCode agents (free models) share one Switch room backed by Mattermost:

  • Records reads orders.json and posts the order facts.
  • Policy applies the rules in refund_policy.md and posts a verdict.
  • Reply writes the customer message.
Order What happened
$20 Auto-approved, the customer got an approval message
$320 Policy stopped and asked me. Only after @riyaa-policy APPROVE did Reply write
$180 I rejected it, the customer got a polite refusal
$899 Flagged as fraud (4 refunds in 90 days, mismatched addresses). No refund, and the customer was only told the account is under review

Why Switch matters here

The agents hand work to each other by @mention, with no glue code. They share one room history, so when I asked for an order that was already approved, Policy replied DUPLICATE and Reply did not send a second message. The human gate is just a room message: Policy waits until a person replies.

Setting it up as a first-timer on Windows

  1. Install Docker Desktop and Switch Console (the Windows build is early access).
  2. In Console, choose "Run Switch on this computer".
  3. Install OpenCode and use one of its free models.
  4. Create three agents with New agent (provider OpenCode, run location This computer) and paste each agent's instructions.
  5. Create a room with the Mattermost bridge and add the three agents.
  6. Post @riyaa-records Refund request for order 1007.

Things that tripped me up

  • Switch's OpenCode sign-in failed with "Database is not empty and has no session table". Stopping the opencode-cli process and renaming the opencode.db* files in ~/.local/share/opencode to .backup fixed it. I renamed instead of deleting, so nothing was lost.
  • Creating my first room failed with an HTTP 500. It worked after I shortened the description and changed the name, but I can't be sure which one fixed it.
  • Agents only listen when mentioned, so even the human approval must be @riyaa-policy APPROVE <order>.
  • A room template can only add agents that already exist, so I created the agents by hand.
  • Free models can take up to a minute per step.

What I would add next

Real orders from an API instead of a JSON file, and PII redaction before messages reach the room.

Demo and code

I built this with AI assistance (Claude) and can explain every part of it.