Dev.to · 8 min read

Two coding agents broke each other's code on different laptops. So I built them a control tower on Switch.

Two coding agents broke each other's code on different laptops. So I built them a control tower on Switch.

A first-timer's guide to Switch, through the project I built for Flip the Switch: Detente, traffic control for coding agents. [Demo video: add the YouTube embed here before publishing] The break nobody sees coming My agent changes create_session(user) to create_session(user, ttl) in auth/session.py. My teammate's agent, on another laptop, is writing billing/refunds.py, which calls create_session(user). Different files, no shared lines, nothing pushed yet. File locks see nothing. Git sees nothing. The first sign is a broken build after both of us push. Coding agents make this worse: they write fast, they don't chat with each other, and each one only sees its own laptop. I wanted something that sees both laptops at once, catches the break before anyone pushes, and lets a person pick the fix. That needs three things: a place where agents on different machines, from different vendors, can hear each other; a way to talk to exactly the agents involved; and somewhere a person can decide. That's what Switch is for. What Switch is, in plain words Switch is open-source infrastructure that puts AI agents and people in the same team chat. The pieces I used: Rooms. A room is a conversation that people and agents both join. Switch bridges rooms to a chat app, so in a chat app such as Mattermost a room just looks like a channel. The agent protocol. Any program can be an agent. It reads one event stream per room, and does everything else (posting, creating rooms, editing documents) with plain HTTP calls. Switch Console. A desktop app that runs a coding agent, such as Claude Code or Codex, on your laptop and puts it in rooms. The Gateway. A web admin for agents, people and who may talk to whom. Detente is a custom agent on that protocol. It sits in a room called tower, reads every message, and acts like a control tower: agents file flight plans before they edit, and Detente clears them, warns them about traffic, or holds them. Step 1: run Switch on your own machine Switch ships as a Docker Compose file. The core is Postgres plus the Switch server. Two optional profiles add a bundled Mattermost (collab) and the Gateway (gateway), so you get a working team chat with no outside accounts: docker compose -p detente-switch --env-file switch/.env -f switch/compose.yml \ --profile collab --profile gateway up -d One tip: Switch defaults to ports 8000 and 3000, which collide with half the projects on a developer's laptop. The env file lets you move them. I use API_HOST_PORT=8110 and GATEWAY_HOST_PORT=3110. Step 2: register your own agent A custom agent registers once with the server's registration token and gets back an id and an API key. The key is shown only once, so save it straight away: response = await http.post( "/agents", headers={"Authorization": f"Bearer {registration_token}"}, json={ "name": "detente", "display_name": "Detente", "connector_type": "external", "integration_profile": {"connection_model": "always_on", "message_exchange": True}, }, ) From then on, every action is one HTTP call: response = await http.post(f"/agents/{agent_id}/ops/{operation}", json=arguments) and listening is one server-sent event stream per room, at /agents/{agent_id}/events. That's the whole protocol surface I needed. Step 3: the Switch features that made Detente possible Here's what each Switch feature does in Detente. Without Switch, none of it works: the agents can't see each other, and there's nowhere for a person to decide. Switch feature What Detente does with it Rooms across laptops and vendors Claude Code on my laptop and Codex on yours both sit in #tower Room instructions Every agent learns the flight-plan rules the moment it joins send_targeted_message CLEARED and HOLD go only to the agents involved, not the whole room create_room + link_rooms A break opens a conflict room with both people and both agents, linked to #tower list_participants Detente checks that the A or B came from a person, never an agent Room documents A live "Airspace" board of who is cleared for what Exclusive roles Detente holds the tower role, so there's only ever one controller read_context After a restart, Detente catches up on anything said while it was down archive_room The conflict room closes once the code fits again When a real break happens, the room sees this: [O_O]! COLLISION lay-claude changed create_session(user) to create_session(user, ttl) a-codex's billing/refunds.py:42 is missing required argument ttl Nothing pushed. Both flights holding. Opened conflict-create-session-3f1a. A person replies A or B in the conflict room, the chosen agent makes the fix, and the room is archived. Step 4: put a coding agent in the room with Console On each laptop where an agent writes code: Install Switch Console and choose Connect to an existing server. Enter your team's Switch address, not Console's own built-in server, or your agent ends up in a different chat. Create the agent and point it at the folder it works in. Check who can talk to it (gotcha 1 below). Add it to the room. The gotchas I wish someone had told me These are the things a first-time Switch user will actually hit. 1. A new agent only listens to its owner. In Console, "Who can talk to your agent" starts as you and your own agents. With that default, Detente's CLEARED and HOLD messages can't reach the coding agents, so each one needs a rule that lets the agent detente talk to it. If your agents ignore another agent, check this first. 2. The same goes for people addressing your agent. Other people's mentions of an agent get a refusal from Switch until the owner widens that agent's addressing policy in the Gateway. Detente checks who's a person itself, so its commands still work, but your teammates will see the refusal. 3. One message in two rooms can wake two sessions. Switch runs a session per room for each agent. When I told the fixing agent "you're up" in both the conflict room and #tower, two sessions started and both tried the same fix. Now Detente tells the fixer in one room only, and posts a plain record in the other. 4. Room instructions live in the room, not in your repo. Editing my instructions file changed nothing for an existing room. Update them in Console's room Configuration, or recreate the room. 5. Make restarts boring. read_context returns recent history. On the very first start Detente marks it all as seen; on later starts it handles anything it missed. My crash test kills Detente in the middle of a collision, and the hold is still in force after the restart. 6. Not every chat app can do everything. Switch can't create chats on Telegram, so anything that opens rooms on the fly won't work fully there. I tested on Mattermost. 7. Coding agents take your words literally. My tower first answered a safe but related plan with TRAFFIC, meaning "go ahead, I'm watching". The agents read anything other than a plain CLEARED as a hold and refused to edit. Now the heads-up rides inside the clearance: CLEARED lay-claude · auth/passwords.py Traffic: developer-a-claude uses hash_password, which lay-claude is changing. Watching. 8. Agents remember the room. Deleting old chat posts doesn't reset a Console agent: it still remembers earlier sessions in that room. Before a clean run, stop its sessions in Console. What it can do Every number here comes from a command in the repo, with no LLM anywhere in the loop. Detection is plain Python ast, so a catch is exact: this signature changed, this call breaks. 564 breaks planted in Django, Flask, Requests, FastAPI and Rich: Detente stopped all of them, each with the exact reason. git merge-tree flagged none. 274 harmless changes in the same projects: Detente stopped none. 449 real merged PRs from NumPy, Matplotlib, pytest, pip, IPython and Django, used as a test bed: it stopped the 11 that conflict in git, and none of the 438 clean ones. What I learned Switch makes agents social. The hard part of multi-agent work isn't making one agent smarter; it's giving agents on different machines a shared place to talk, with people in the loop. Switch gives you that out of the box. Keep the judgment human. Detente never picks a fix. Both flights hold until a person replies, because the person knows which change the team actually wants. Deterministic beats clever, for a gate. A tool that blocks edits has to be right every time and has to explain itself. Static analysis can do that; a model guessing can't. Try it Play the person in charge, in your browser: mydetente.vercel.app/showcase Or in your terminal, with only uv installed: uvx detente showcase The code, with every benchmark: github.com/laypatel13/detente Demo: https://youtu.be/obMUDCzWLgg Built for WeMakeDevs × Switch: Flip the Switch.

This is a summary aggregated from Dev.to. Read the complete article on the original site:

Read full article at Dev.to

More AI & Machine Learning News