During the day, I work as a software engineer in a commercial team. After hours, I build private projects solo. But even when I'm working alone, I have a dedicated supporting team: two AI agents, Claude and Codex.
When I first adopted this multi-agent stack, I quickly hit a wall of blurry responsibilities. Claude would try to write implementation code from scratch, completely ignoring my project's established conventions. Conversely, Codex would try to guess the system architecture without having the full context.
The result? Wasted tokens, hallucinations, and constantly hitting the usage limits on my $20 subscription plans. Every single day, I found myself manually redrawing the line between "research this" and "implement that."
The solution wasn't better "prompt engineering." It was treating these agents like distributed systems that require a strict API. I wrote a formal, machine-readable contract in Markdown that strictly defines their roles, handoff conditions, and the exact moments they must stop and ask for human approval.
The Architecture: Who Does What?
In my workflow, Claude acts as a "thin orchestration layer" equipped with session memory and context. Codex is the workhorse—an implementation engine hooked into a mature, custom skill tree I've been developing over the last three months. The agents communicate with each other: Claude has full access to Codex via the Model Context Protocol (MCP).
The core directive of the contract, stored in a CLAUDE.md file, is simple: Claude analyzes, plans, and composes prompts. Codex implements.
There is only one exception. Claude is allowed to touch code directly only if the change is trivial (under ~100 lines, confined to a single file). Offloading tasks that small to Codex would generate unnecessary latency and token overhead.
Stop Conditions and Task Categorization
Before Claude invokes Codex (using the /codex:rescue command via MCP), it must evaluate the scope of the task. This is where the contract enforces hard stop conditions:
- Small Scope: The task is well-defined, the approach is obvious, and it maps to a single existing skill. Claude delegates it to Codex immediately, without asking for my input.
- Large Scope: A new feature, a refactor touching 3+ files, or ambiguous requirements. In this scenario, Claude is forbidden from delegating the work. It must first generate an execution plan, surface any ambiguities (a step I call Intent Refinement), and wait for my verification. Blindly delegating a massive feature guarantees wasting an entire Codex session on the wrong architectural direction.
- Risk Override: Even the smallest change is forcefully treated as Large Scope if it touches critical paths: authentication, payments, database mutations, or cross-repository boundaries (e.g., queue payloads, API DTOs).
If the system flags a task as high-risk, the contract also mandates running a /codex:adversarial-review pass after implementation, right before shipping.
The Handoff Protocol
Delegation in this system isn't just throwing a loose "build this" prompt over the fence. Since Claude can read the project structure, its primary job is to assemble a highly compressed context payload.
According to the contract, Claude must locate the correct routing branch in .codex/AGENTS.md, load the specific skill file (e.g., React implementation rules), and extract only the 3 to 7 most relevant constraints for the current task. It packages this into a standardized prompt and fires it via MCP:
TASK: <one-line description of what needs to happen>
PRELOAD (before starting):
- project-context
- technical-context-discovery
- <product-intent if new feature>
CONTEXT:
<file paths involved, current relevant code snippet if short>
APPLY THESE RULES (from skill: <skill-name>):
- <rule 1, verbatim or tightly paraphrased from the skill file>
- <rule 2>
- <rule 3>
ANTI-PATTERNS TO AVOID (from skill: <skill-name>):
- <anti-pattern -> correct approach, only if relevant to this task>
DEFINITION OF DONE:
- <concrete, checkable criteria — e.g., "Returns 401 for expired tokens">
Crucially, Claude is also responsible for dynamically selecting the model and "effort" level for Codex on the fly (e.g., assigning a cheaper, faster model for code exploration, and the heaviest model for complex business logic). It bases this decision on live data pulled from a local workflow-facts.sh script.
State Management and Continuity
In this setup, Codex is entirely stateless—every execution is a blank slate. Claude is responsible for maintaining continuity.
The contract forces Claude to read a .codex-handoff.md file at the start of every session and log any anomalies into a FAILURES.md file. Furthermore, I built a deep integration with my local Obsidian vault. Claude's job is to proactively write architectural decision records (ADRs), debug logs, and session summaries into the vault.
It does not wait for me to say "save this note." I defined hard triggers in the contract. If a trigger fires (e.g., the word "decision" is used during a technical trade-off discussion), the note must be created. The system also checks file paths for idempotency—if a note already exists, Claude updates it in place rather than spawning duplicates.
Because of this, even if I return to a project days later, Claude reconstructs the state from logs and vault notes, feeding that exact context back to Codex before the next delegation.
Trade-offs and Results
Implementing this level of strict process engineering came with a heavy upfront cost.
While testing and optimizing this workflow, my actual coding throughput dropped significantly for about two weeks. The Codex custom skill system took me three months to build iteratively, and the Claude-Codex MCP integration (along with refining the contracts) took another 6 weeks. The system also demands continuous maintenance, like weekly tweaks whenever AI models are updated, as relying on beta custom Codex routing can occasionally be fragile.
So why was it worth it?
The primary return on investment is a drastic reduction in token consumption and massive workflow predictability. Previously, I was constantly hitting API rate limits. Now, because Claude delegates precise, highly constrained "work packets" to Codex and no longer hallucinates logic from scratch, I operate comfortably within standard $20 subscription tiers. Even with heavy daily use across both commercial and private codebases, usage limits are no longer a bottleneck.
I stopped playing guessing games with how a model might behave. Instead of relying on clever prompt engineering, I wrote strict documentation for machines—and now they enforce the process themselves.