Built for Flip the Switch (WeMakeDevs, DevTools Academy, Switch AI), Track 01: Best Business Workflow. Code: github.com/manoj1698/soc-shift-relay.
The problem: the handover
Security operations teams work in shifts, and two things go wrong every night. At 2 AM an alert waits for a person who is asleep, or it wakes someone up for a scan the team approved last week. At 9 AM the next analyst opens a wall of alerts with no idea which three matter. Context is lost at every handover.
I wanted agents that behave like shift colleagues, not a chatbot: they keep watch, fix the safe things, ask a person before anything risky, and tell the next shift exactly where to start.
The idea: five agents, one room
SOC Shift Relay puts five Claude Code agents into the team's Discord through Switch:
@triage checks every alert against the runbook, closes known false positives, and answers employees who report problems in #security-help.
@responder is the only agent that can change anything: block an IP, disable an account, isolate a host. It proposes first, and the action runs only after the on-call analyst taps Allow once in chat.
@scribe keeps the shift log and the on-call roster, briefs the next analyst, and writes a shift or incident report on request.
@appsec scans every code push: leaked secrets, risky code, vulnerable dependencies, malware patterns. It flags the push, hands attacker addresses to @responder, and writes a fix that it re-scans clean. It never merges.
A SIEM agent replays a night of sample alerts and a code push.
The safety design: a runbook with three tiers
The runbook is a room document every agent reads, and its tiers decide everything:
Tier 0, agents alone: lookups, closing known noise, safety steps for an employee, scanning a push, preparing a fix as a proposed change, writing the logs.
Tier 1, on-call approves: block or unblock an IP, disable or re-enable an account, isolate or release a host.
Tier 2, people only: delete data, touch protected targets, merge code, rotate a leaked key.
A brief that says "wait for approval" is only a request. So every rule is also held by something outside the prompt. @responder runs with Auto mode off, and its Claude Code settings mark every action script ask, so the script cannot start until Switch's approval request is answered. The scripts refuse protected targets even when approved. Deny rules block edits to the lab state and all network tools. @appsec cannot write, run or install the code it scans. Every action writes a JSON line to an audit log, and the reports quote that log, so a report cannot invent an approval.
Building it on Switch
Switch is what turns five chatbots into a team:
Roles (jobs). People address the job, @scribe, not the agent. If an agent goes offline, another can take the job, which is the shift idea applied to agents. triage is shared; responder, scribe and appsec are exclusive, so there is never a second agent acting in parallel.
Approvals in chat. The approval request shows the exact command. On-call answers Allow once or Decline, and Switch records who answered.
Room documents as memory. Only the agent that created a document can change it, so the shift log has exactly one author. The roster lives there too: tell @scribe "Asha is on leave until Monday, Spider covers her" and her follow-ups go to Spider. Absence never counts as approval.
Who can talk to an agent. Employees can reach @triage, never @responder. When my second account told the responder to disable a user, Switch refused it in the channel.
Linked rooms. #security-help escalates to #soc-shift.
A template. One YAML file recreates all five agents, both rooms, the link, the roles, the runbook and the kickoff. A judge imports it and gets the same room I recorded.
The code push at 02:40
The new part I am proudest of: at 02:40 a contractor account pushes a "hotfix" to payments-api. @appsec scans only the lines the push adds and returns BLOCK with five findings:
a curl | sh from an unknown host in the deploy script
a live payment API key, redacted in every output
an f-string SQL query
PyYAML 5.3 and requests 2.19.1, with five public CVEs between them
@responder blocks the host after Allow once. @appsec writes the fix as a proposed change that keeps the payment retries, re-scans it to PASS, and leaves merging and key rotation to people. The scanner is standard library and offline, with rules modelled on Gitleaks, Semgrep, OSV-Scanner and YARA, so the demo runs on any machine.
What went wrong, and what I learned
Windows is early access. Switch Console on Windows could not fill a provider field in a template, so the template pins Claude Code for every agent. That is the honest choice anyway: the guardrails are Claude Code settings.
Trust changes everything. Claude Code ignores a folder's allow rules until the folder is trusted, and Switch starts agents without the trust dialog. Every harmless status check asked on-call for approval, until I added a --trust step to the setup script.
Agents doubt what they cannot see. The responder never sees the approval itself, so in one rehearsal it called an approved block "unconfirmed", and the morning brief was wrong. One sentence in its brief fixed it: if your command ran, on-call approved it.
Exact commands matter. cd folder && python actions/status.py did not match the allow rule for python actions/status.py. The briefs now say to run commands exactly as written.
Agents only hear @. A message that does not address an agent never reaches it, which is why the shift change is "@scribe end of shift" and why the employee room has triage as its main agent.
Run it yourself
Clone the repo, follow the setup guide (Windows and Discord, about an hour the first time), import the template, run python tools/reset_demo.py, and type @soc-siem start night shift.
Beyond security
Only the runbook and the lab are security-specific. Swap them and the same room serves an IT helpdesk, a customer-support shift or a network operations team: triage, an approval-gated responder, a scribe that briefs whoever starts the next shift, and an agent that checks every change before it ships.
Top comments (0)