Interlock coordinates AI agents that change production.

An agent asks Interlock before it changes anything. Interlock finds every service the change can affect. If another change already affects them, the new change waits. If the change is risky, a human must approve it. Interlock records each decision.

Live Acme Commerce production. 24 simulated agents ask Interlock before each change. Full console
0changes running
0changes waiting
0collisions prevented
0blocked by policy
0changes completed

The problem

Companies run many agents at the same time. Each agent knows only its own task. Two tasks can look unrelated and still break the same service.

checkout orders payments orders-db payments-db Agent A: migrate orders-db Agent B: deploy payments Both changes reach checkout Arrows point from a service to what it depends on. The red dot marks a customer-facing service.

    Diagram: checkout depends on orders and payments. Orders depends on orders-db. Payments depends on payments-db.

    "An AI agent deleted our production database."
    r/LocalLLM, May 2026

    Interlock: a delete in prod needs a human. An agent scoped to staging cannot reach prod.

    "Who approved the command, how do you prove what it did."
    r/devops, October 2026

    Interlock: each decision is stored before the action runs, with the chain from the agent to the human who authorised it.

    "Merge conflicts, duplicated functions, agents working at cross-purposes."
    r/ClaudeAI, on running several agents at once

    Interlock: two changes that reach the same service cannot run together. The second change waits.

    Scenarios you can run

    These buttons change the live system. Select a scenario, run it, then watch the map and the log.

      Benchmark: the same fleet with and without Interlock

      24 agents, 40 production resources, 180 simulated seconds, the same random seed. Without Interlock the fleet makes more changes, but most of them collide.

      Collisions on customer-facing services
      116 without, 0 with
      Changes that landed cleanly
      58 without, 107 with
      Average wait before a change starts
      0s without, 29.5s with

      The wait comes from a strict rule: two changes that reach the same customer-facing service run one after the other. To get these numbers again, run scripts/bench.py. You can also turn Enforcement off in the console.

      How a request is decided

      Services, databases, topics, flags, teams, people and agents are nodes in one FalkorDB graph. Interlock answers each request with graph queries.

      # the agent asks first
      POST /api/request
      {
        "agent":  "deployer-03",
        "action": "deploy",
        "target": "payments@prod",
        "reason": "v2.4 rollout"
      }
      
      # the answer says what to do and why
      {
        "status": "waiting",
        "reason": "Waits for migrator-11 (migrate orders-db).
                   Both changes reach checkout:
                   orders-db → orders → checkout,
                   and payments → checkout."
      }

      Graph model

      Systems, teams and people are loaded once. Intents, decisions and waits are written while agents work. The lock table and the audit trail are the same graph.

      AUTHORIZED BY ABOUT AUTHORIZED_BY DELEGATED_TO, WAITS_ON WAITS_FOR CAN_CHANGE SCOPED_TO IMPACTS {role} IN OWNED_BY DEPENDS_ON {kind} COVERS Humanname, teams Agentrole, priority, kind Intentaction, mode, status, ttl Decisionverdict, reason, path Teamname Envprod, staging Resourcekind, tier, team Freezeactive, reason

      Resource is a service, datastore, topic or feature flag. DEPENDS_ON points from the dependent to the dependency, so an impact zone is a reverse walk.

      Intent is one requested change. Its IMPACTS edges are the lock. WAITS_FOR shows its queue. Deadlocks are cycles in WAITS_ON.

      Decision is the audit record: the verdict, the reason, the dependency path and the authority chain.

      Policies

      Interlock enforces these outside the agent. A prompt cannot change them.

      Impact-aware locksA change locks its target and its dependents. Unrelated work continues in parallel.
      Environment scopeAn agent scoped to staging cannot change prod.
      Human authorityEach agent, including sub-agents, must trace back to a human who can change the owning team's resources.
      FreezesA code freeze stops changes at the lock.
      Sign-offDeletes in prod, payment database migrations and very wide changes wait for a human.
      Incidents, deadlocks, crashesIncident fixes go first. Interlock breaks wait cycles. A crashed agent's lease expires.

      Connecting your agents

      Any agent that can call a tool can use Interlock: Claude Code, Cursor or your own workers, over MCP or HTTP.

      # Claude Code: add Interlock as an MCP server
      claude mcp add interlock \
        -e INTERLOCK_URL=https://your-interlock \
        -e INTERLOCK_AGENT=claude-code \
        -- python -m interlock.mcp_server
      
      # tools the agent gets
      request_change  heartbeat  release
      why_blocked     status     list_resources
      # plain HTTP, from any worker
      curl -X POST $INTERLOCK/api/request \
        -H 'Content-Type: application/json' \
        -d '{"agent": "deploy-bot", "action": "deploy",
             "target": "payments@prod", "reason": "v2.4"}'
      
      # renew the lease while working, release when done
      curl -X POST $INTERLOCK/api/heartbeat -d '{"intent": "int-..."}'
      curl -X POST $INTERLOCK/api/release   -d '{"intent": "int-..."}'

      Open the console

      See every agent, change, approval and decision, with the Cypher behind each one.

      Open the console