How I put three AI agents in a Slack channel with Switch
Every small team has a person who gets asked the same questions all week. "Can we refund this?" "Is this okay to expense?" For the Flip the Switch hackathon, I built Precedent: a Slack channel where that person answers
Every small team has a person who gets asked the same questions all week. "Can we refund this?" "Is this okay to expense?"
For the Flip the Switch hackathon, I built Precedent: a Slack channel where that person answers once, and AI agents remember the answer as a tested rule. Next time, the agent brings the answer and the person just confirms it.
This post shows how I built it, step by step, and what broke along the way. If you're trying Switch for the first time, I hope it saves you a few hours.
What is Switch?
Switch is open source software that puts AI agents into team chat. A Slack channel becomes a room, and agents join it like teammates, each with its own name. People and agents all read the same conversation.
You bring the agents and the chat app. I used Claude Code and Slack.
The plan: three agents, one room
I split the job into three small roles:
| Agent | Its job | Who can give it instructions |
|---|---|---|
| Clerk | Turns a request into a structured case | Anyone in the room |
| Judge | Checks the case against the rules and asks the manager | Only the owner and the owner's agents |
| Auditor | Turns the manager's words into a rule and tests it | Only the owner and the owner's agents |
Here's how a request moves through the room:
- Sam, a support agent, asks the Clerk: "Refund for order 4821, INR 64, unopened, bought 17 days ago."
- The Clerk makes a case and hands it to the Judge.
- No rule covers it, so the Judge asks Priya, the manager.
- Priya approves and adds: "make it a rule: unopened items up to 30 days."
- The Auditor tests that rule on past cases, and Priya decides whether to adopt it.
- The next similar request arrives with the answer and the rule, and Priya confirms in one line.
Step 1: Set up Switch
- Install Switch Console, the desktop app.
- Choose Add a server β Run a server on this computer.
- Click Connect and connect Slack.
- On the server's Home page, click Link and choose This is me, so Switch knows your Slack account.
- Under Your Agents, turn on Run managed agents on this computer.
Step 2: Describe the team in one template
This was my favourite part of Switch. One YAML file describes the agents and the room, and Console creates all of it. Here's a shortened version of mine:
agents:
- name: "{team}-clerk"
display_name: Clerk
provider: claude
addressing: anyone
instructions: |
You are the Clerk. People bring you requests; you turn each
into a case and hand it to the Judge. You never decide anything.
- name: "{team}-judge"
provider: claude
addressing: owner-agents
instructions: |
...
room:
name: "{team}-approvals"
bridge: "{bridge}"
agents: ["{team}-clerk", "{team}-judge", "{team}-auditor"]
users: ["{$creator}"]
Look at addressing. It decides who can instruct an agent. With anyone, the whole room can ask the Clerk. With owner-agents, only the owner and the owner's agents can instruct the Judge, so a random message can't tell it what to do.
To use it, go to Templates β Import template in Console, then click Create all. The agents and the Slack channel appear.
Step 3: Let the AI read, and let plain code decide
I didn't want an AI deciding who gets a refund. So the agents only handle the words, and every decision goes through a small command-line tool written in plain Python, with no AI in it.
- The agents read messages, fill in the case and write the replies.
- The engine checks the rules, tests new ones and saves every step as a git commit.
So the Clerk's instructions tell it to run commands like this:
uv run precedent --home <state folder> --as clerk case new --type refund ...
Step 4: Check who really approved
This is the most useful Switch trick I learned. If an agent says "Priya approved this", how do you know that's true? An agent could get it wrong, or be tricked.
So the agent passes the engine only a message id. The engine then asks Switch for that message through the agent API (read_context) and reads the sender Switch recorded. An agent can't set that value for a person.
The approval also has to quote a short code, like this:
approve C-043 #e3cf9b
That code is a hash of this exact case and answer, so it can't be reused on a different one. When I offered an agent's own message as an approval on the live server, the engine refused it:
precedent-judge is not an approver
Step 5: Test each rule on past decisions
Before a rule is saved, the engine replays past cases with and without it. On my made-up demo data, the result was:
- 43 cases, of which 41 could be checked
- 12 newly covered by the rule
- 0 conflicts
- 3 past cases where the manager said no, but the rule would say yes
The manager sees those 3 before agreeing. They aren't treated as mistakes, because the manager may have had a reason.
What broke, and how to fix it
I ran this on Windows with Console 0.40.1. These are the problems that cost me the most time:
| What I saw | Cause | Fix |
|---|---|---|
| Every provider said Not supported here | A Windows bug in Console's provider picker (#1511) | Write provider: claude in the template, and turn on managed agents |
An agent reported {engine_dir} in its instructions |
Console doesn't fill {params} in managed agents' instructions (#1577) |
Put the real paths into the template before importing it |
missing_scope when linking Slack |
The Slack app wasn't made from Switch's manifest | Paste the manifest into App Manifest, save, and reinstall |
| An agent said it only takes instructions from its owner | My Slack account wasn't linked | Click Link on the server's Home page |
| "Could not reach http://localhost:..." | The server process had stopped | Quit Console fully and reopen it |
My main lesson: test with a live agent early. My template passed validation, and I only found the {engine_dir} problem when an agent told me about it in the room.
I also found bugs in Switch
Building this led me to report four bugs:
-
#1577: Console leaves
{params}unfilled in managed agents' instructions -
#1578: Telegram can split a long message in the middle of
< - #1579: Discord treats a one-line code fence as an open code block
- #1580: Mattermost drops posts over the server's limit
The last one taught me something. From reading the code, I reported a limit of 4,000 characters. When I tested on real servers, it was 16,383 on Mattermost 10.5 and 262,144 on 12.0, so I posted a correction. Run it before you report it!
What it can't do yet
- A person still confirms every case, so cases wait while the manager is away.
- Tampering with the saved data is detected, not prevented.
- The past cases and people in the demo are made up, and no real team has used it yet.
- The live run used one Slack account and has only been run on Windows.
Try it
You can try the whole flow in about two minutes, without Switch or Slack:
git clone https://github.com/rushibhosalepro/precedent.git
cd precedent
uv sync
uv run pytest -q
uv run python scripts/rehearse.py
- Code and full setup: github.com/rushibhosalepro/precedent
- Demo video: youtu.be/rHvyygxSsvI
I built this with Claude Code as my pair programmer. Claude Code also wrote this post, working from the project and our notes.
HowISwitch #FliptheSwitch
Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes β full credit and traffic to the original publisher.