# Architecting a Solo Multi-AI Studio: Separation of Powers and Deterministic Pre-Release Gates

> Source: <https://dev.to/zeuslab/architecting-a-solo-multi-ai-studio-separation-of-powers-and-deterministic-pre-release-gates-21o4>
> Published: 2026-11-13 22:08:03+00:00

One chat window, one model, every job: the idea, the structure, the code and the final check. Sooner or later, though, the same model can quietly approve its own mistake, and a leaked key, an unmeasured number or a broken link goes out with your name on it.

What changed things for us was not a better prompt. It was a separation of powers. The model that builds never grades its own work. A second reader sees only the finished text and the rules. And the checks that must never be argued with are done by plain code at commit time. In our own test, that commit-time leak gate stops 32 of 32 planted samples and raises 0 false alarms on 17 clean look-alikes. That is a figure for planted samples, not a detection rate for real folders.

Here is the setup, piece by piece, so you can rebuild it with the models you already use.

Three things go wrong when one conversation does everything.

None of this is a model problem. It is an organisational one, and the old fix applies: split the powers.

| Role | Owns | Does not | 
|---|---|---|
| Vision | the story, the market, the plan | write the final code | 
| Structure | math, prices, edge cases, a second opinion | approve its own numbers | 
| Execution | code, files, film, the scheduled runs | grade its own output | 
| Blind audit | reading the artifact against the rules | see the maker's reasoning | 

Above them sits one person who decides: execute, abort, or mutate with a stated reason. As one example of an assignment, in our setup a long-context model takes vision, a second vendor's model takes structure and, in a separate session, the blind review, and a coding agent executes. The assignment matters less than the rule that no role holds two powers.

Separation only works if the handoffs are clean.

Some questions are not up for debate: did a secret leak, does a number have a source, does every link answer. These run as plain code, at commit time and again before release.

The wiring is ordinary. A sketch, with placeholder file names:

``` bash
#!/bin/sh
# .git/hooks/pre-commit: a non-zero exit stops the commit
python3 tools/check_leaks.py --staged || exit 1
python3 tools/check_claims.py --staged || exit 1
```

The agent gets a seat belt too. Claude Code can run a hook before every tool call; exit code 2 refuses the call, and the message on standard error goes back to the agent. This one, from our MIT starter, refuses a commit that tries to skip the checks:

```
SKIP_FLAG = "--no-" + "verify"
RULE = re.compile(r"git\s+(commit|push)\b[^\n;|&]*" + re.escape(SKIP_FLAG))

def main() -> int:
    try:
        data = json.loads(sys.stdin.read() or "{}")
        if data.get("tool_name") == "Bash":
            command = str((data.get("tool_input") or {}).get("command", ""))
            if RULE.search(command):
                sys.stderr.write("guard: refused. Fix the cause instead.\n")
                return 2
    except Exception:
        return 0
    return 0
{"hooks": {"PreToolUse": [{"matcher": "Bash",
  "hooks": [{"type": "command", "command": "python3 \"$CLAUDE_PROJECT_DIR/hooks/guard_min.py\""}]}]}}
```

It is a text match on the command, nothing more. Treat it as a seat belt, not a sandbox. Exceptions raised inside the hook are caught and let the call through, so a bug in its logic does not block your work.

Metered API keys are the quiet way a solo studio overspends. The same hook pattern can refuse a tool call that touches a metered-key variable, so the agents work through the flat-rate tools you are already signed into. The cost follows the plan you chose rather than a per-call meter.

The studio wakes on a schedule (four times a day for us), catches up once after the machine has slept, and picks up any new directive the founder leaves in a shared folder. What reaches the human is one card: what changed, what was measured, and one decision, with execute, abort or mutate.

*Disclosure: this article was drafted with AI assistance (Claude) and checked against the measured results and the published files. Product links lead to our own paid kits.*
