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.jsonand posts the order facts. - Policy applies the rules in
refund_policy.mdand 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
- Install Docker Desktop and Switch Console (the Windows build is early access).
- In Console, choose "Run Switch on this computer".
- Install OpenCode and use one of its free models.
- Create three agents with New agent (provider OpenCode, run location This computer) and paste each agent's instructions.
- Create a room with the Mattermost bridge and add the three agents.
- 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-cliprocess and renaming theopencode.db*files in~/.local/share/opencodeto.backupfixed 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.



