Most people running AI coding agents have the same setup: Claude Code in one terminal, Cursor open in the editor, both working on the same codebase. It works until it doesn't.
The failure mode is not dramatic. There is no crash. One agent quietly overwrites what the other just wrote. You notice twenty minutes later when something stops compiling and the diff makes no sense.
This is what happened on a recent runshift session, and what a trust gate did about it.
The setup
Two active sessions. Claude Code working on the API layer — adding a new route handler and updating the shared types file. Cursor on the frontend, building the component that would consume that route.
Both legitimate. Both necessary. Running in parallel because running them sequentially would take twice as long.
The shared file was src/types/agent.ts. Claude Code needed to add a field. Cursor's component was already importing from it.
What happened without a gate
Before runshift, this would have resolved silently. Claude Code writes the updated types file. Cursor, mid-session, reads a stale version. The component builds against the old interface. The API expects the new one. TypeScript catches it eventually, or it ships and breaks at runtime.
The operator finds out after. There is no record of what either agent saw when it made its decision.
What happened with a gate
Claude Code reached the point where it needed to modify src/types/agent.ts. Before writing, it signaled runshift via the MCP hook:
action: modify shared types file
summary: adding gateActionType field to Agent interface — required for RelayBanner action mapping
content: [proposed diff]
runshift intercepted. A trust gate fired in the dashboard.
The gate showed which agent was requesting the change, exactly what it wanted to write, which other sessions were currently active and might be affected, and the proposed diff.
One decision: approve or deny.
The relevant question was not whether the change was correct. It was. The question was sequencing — Cursor's frontend session needed to finish its current component before the interface changed underneath it.
Deny. Route the message to Cursor's session to complete first. Approve Claude Code's types change after.
Total time: thirty seconds. The conflict that would have taken twenty minutes to debug never happened.
What the audit trail recorded
Every gate decision writes an immutable entry:
gate_events {
agent_id: claude-code-session-a
action: modify src/types/agent.ts
agent_output: [full proposed diff]
status: denied
resolved_at: 2026-03-28T14:32:07Z
cost_usd: 0.0018
}
The deny was not a rejection of the work. It was a sequencing decision. That distinction matters when you are reviewing what happened an hour later and trying to understand why things ran in a particular order.
The cross-repo case
The same pattern applies across repos. A backend agent modifying a shared library that a frontend repo depends on. An infrastructure agent updating an environment variable that three services read at startup. An outreach agent about to send a message that references a pricing tier the product agent just changed.
In each case the agent does not know what it does not know. It sees its task, its context, its output. It does not see the other sessions.
runshift does. Relay holds the session graph. When an agent reaches a consequential action, that context is what makes the gate decision meaningful — not just "should this change happen" but "should this change happen now, given what else is in flight."
What relay is not doing
Relay is not running the agents. It is not generating the code. It is not making the architectural decision about whether gateActionType belongs on the Agent interface.
That is the agent's job. The agent is better at it than the operator.
What relay is doing is holding the moment before execution. Surfacing what the agent is about to do. Giving the operator thirty seconds to answer one question: does this action make sense given everything else that is happening right now.
That is a different kind of intelligence than writing code. It is coordination intelligence. And it compounds — every approved and denied gate becomes part of the signal that makes the next routing decision faster.
The gate is not friction. It is the moment where operator judgment enters the loop at exactly the right time — before the action executes, after the agent has done the work.
That is the only moment it matters.