{"slug": "architecting-a-solo-multi-ai-studio-separation-of-powers-and-deterministic-pre", "title": "Architecting a Solo Multi-AI Studio: Separation of Powers and Deterministic Pre-Release Gates", "summary": "A developer built a solo multi-AI studio that enforces a separation of powers, assigning vision, structure, execution and blind audit to different models so no model grades its own work. Hard checks for leaked secrets, unsourced numbers and dead links run as plain code in git pre-commit hooks and again before release; in testing, the commit-time leak gate caught 32 of 32 planted samples with 0 false alarms on 17 clean look-alikes, a figure the developer notes applies to planted samples rather than real folders. A Claude Code PreToolUse hook (exit code 2) blocks commits that try to skip the checks, and the same pattern can refuse tool calls touching metered API keys.", "body_md": "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.\n\nWhat 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.\n\nHere is the setup, piece by piece, so you can rebuild it with the models you already use.\n\nThree things go wrong when one conversation does everything.\n\nNone of this is a model problem. It is an organisational one, and the old fix applies: split the powers.\n\n| Role | Owns | Does not | \n|---|---|---|\n| Vision | the story, the market, the plan | write the final code | \n| Structure | math, prices, edge cases, a second opinion | approve its own numbers | \n| Execution | code, files, film, the scheduled runs | grade its own output | \n| Blind audit | reading the artifact against the rules | see the maker's reasoning | \n\nAbove 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.\n\nSeparation only works if the handoffs are clean.\n\nSome 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.\n\nThe wiring is ordinary. A sketch, with placeholder file names:\n\n``` bash\n#!/bin/sh\n# .git/hooks/pre-commit: a non-zero exit stops the commit\npython3 tools/check_leaks.py --staged || exit 1\npython3 tools/check_claims.py --staged || exit 1\n```\n\nThe 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:\n\n```\nSKIP_FLAG = \"--no-\" + \"verify\"\nRULE = re.compile(r\"git\\s+(commit|push)\\b[^\\n;|&]*\" + re.escape(SKIP_FLAG))\n\ndef main() -> int:\n    try:\n        data = json.loads(sys.stdin.read() or \"{}\")\n        if data.get(\"tool_name\") == \"Bash\":\n            command = str((data.get(\"tool_input\") or {}).get(\"command\", \"\"))\n            if RULE.search(command):\n                sys.stderr.write(\"guard: refused. Fix the cause instead.\\n\")\n                return 2\n    except Exception:\n        return 0\n    return 0\n{\"hooks\": {\"PreToolUse\": [{\"matcher\": \"Bash\",\n  \"hooks\": [{\"type\": \"command\", \"command\": \"python3 \\\"$CLAUDE_PROJECT_DIR/hooks/guard_min.py\\\"\"}]}]}}\n```\n\nIt 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.\n\nMetered 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.\n\nThe 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.\n\n*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.*", "url": "https://wpnews.pro/news/architecting-a-solo-multi-ai-studio-separation-of-powers-and-deterministic-pre", "canonical_source": "https://dev.to/zeuslab/architecting-a-solo-multi-ai-studio-separation-of-powers-and-deterministic-pre-release-gates-21o4", "published_at": "2026-11-13 22:08:03+00:00", "updated_at": "2026-11-13 22:21:26.576291+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "developer-tools", "ai-safety", "mlops"], "entities": ["Claude Code", "Claude", "Anthropic", "git"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/architecting-a-solo-multi-ai-studio-separation-of-powers-and-deterministic-pre", "markdown": "https://wpnews.pro/news/architecting-a-solo-multi-ai-studio-separation-of-powers-and-deterministic-pre.md", "text": "https://wpnews.pro/news/architecting-a-solo-multi-ai-studio-separation-of-powers-and-deterministic-pre.txt", "jsonld": "https://wpnews.pro/news/architecting-a-solo-multi-ai-studio-separation-of-powers-and-deterministic-pre.jsonld"}}