About Portfolio Cases Services Blog Contact 🎙 Talk to AI
EN DE RU
🎙 Talk to AI
October 25, 2026 · 5 min read

One agent hit its quota, the other lost context: how to run Claude Code + Codex as one team without manual handoffs

I’m Denis Shokhirev, an Agentic AI Systems Architect based in Freiburg im Breisgau, Germany, and I build production AI systems for DACH B2B clients at DennisCraft AI Studio using Claude, Supabase, n8n, Doppler, and self-hosted Postgres. One of the most expensive failures I see is not a model crash but a silent handoff failure: Claude Code hits a quota or timeout, Codex picks up the task without enough state, and 30 minutes later the repo has conflicting edits, duplicated commands, and a human dr

Denis Shokhirev
Denis Shokhirev
Agentic AI Systems Architect
Telegram LinkedIn

I’m Denis Shokhirev, an Agentic AI Systems Architect based in Freiburg im Breisgau, Germany, and I build production AI systems for DACH B2B clients at DennisCraft AI Studio using Claude, Supabase, n8n, Doppler, and self-hosted Postgres. One of the most expensive failures I see is not a model crash but a silent handoff failure: Claude Code hits a quota or timeout, Codex picks up the task without enough state, and 30 minutes later the repo has conflicting edits, duplicated commands, and a human dragged in just to reconstruct what already happened.

If you run two coding agents like two people sharing a keyboard, this will keep happening. If you run them like a coordinated system with explicit state, exit contracts, and event-driven routing, manual restarts mostly disappear. The shift is operational, not magical.

The real problem is not model quality, it is state loss

Teams often describe this as a “context window issue,” but that is only part of it. The actual failure is that the second agent receives a prompt instead of a task state. A prompt can summarize intent. It cannot reliably capture the current branch, the last successful test run, the list of changed files, security scan output, or the exact reason the first agent stopped.

Anthropic’s documentation in 2024 emphasizes structured outputs and tool use for machine-readable workflows, not just chat UX: https://docs.anthropic.com/. OpenAI Cookbook examples in 2024 make the same point from another angle: orchestration works better when each step emits explicit artifacts and the next step reads state instead of guessing from conversation history: https://cookbook.openai.com/.

What usually breaks in production

I keep seeing the same three failure modes. First, quota or timeout interrupts a long implementation task after meaningful progress has already been made. Second, the replacement agent scans too much of the repository because no scoped state exists. Third, the handoff strips away risk signals, so the next agent “fixes” code without knowing which tests failed or which guardrail already triggered.

Failure mode Typical cause Operational fix
Quota or timeout Long-running coding session Persist state and route automatically
Context loss Prompt-only handoff External task state in Postgres
Unsafe patching Missing test and scan artifacts Attach checks to every handoff
Human reconstruction No event log Store command history and outputs

Run both agents against a shared state contract

The simplest fix is also the least glamorous: store task state outside the model. I usually put it in Postgres or Supabase Postgres and let n8n handle orchestration events. Claude Code and Codex should not “remember” each other. They should read and write the same normalized task record.

Minimum handoff schema

Do not ask the outgoing agent for a narrative. Ask for a contract. If the contract is incomplete, the workflow should fail closed and request remediation instead of forwarding a weak handoff.

from pydantic import BaseModel
from typing import List, Literal

class HandoffState(BaseModel):
    task_id: str
    agent: Literal["claude_code", "codex"]
    branch: str
    commit_sha: str
    changed_files: List[str]
    test_status: Literal["passed", "failed", "not_run"]
    security_status: Literal["passed", "failed", "not_run"]
    next_action: str
    blocker: str | None = None

This schema is intentionally boring. That is a feature. In production, boring beats clever because boring survives at 6:40 p.m. on a Friday when one agent stopped mid-refactor and another needs to continue without guessing.

Use event-driven routing instead of manual restarts

On my stack, n8n usually acts as the traffic controller. Claude Code gets the initial task. If it hits a quota, loses session continuity, or times out, n8n stores the latest validated state in Postgres, marks the current agent as unavailable for that task, and routes the task ID to Codex. Codex starts by reading state, not by reading a giant handoff paragraph.

version: "3"
steps:
  - name: run_claude_code
    on_error: persist_state
  - name: persist_state
    action: write_postgres
  - name: run_checks
    action: bash
  - name: route_next_agent
    when: "quota_hit || context_loss || timeout"
    action: assign_codex
  - name: require_review
    when: "security_failed"
    action: notify_human

The point is not n8n specifically. The point is event-driven transfer. A human should not be the queue manager for agent failures if the failure mode is already predictable.

What signals are worth routing on

I generally use five: quota hit, context truncation, command timeout, failed tests, and failed security scans. The first three are routing events. The last two are quality gates. Sometimes they send the task back to the same agent with a narrow repair objective; sometimes they require human review, especially for auth, SQL, secrets, or payment logic.

Security gates must survive the handoff

The most dangerous assumption is that handoff is only a productivity problem. It is also a software assurance problem. The replacement agent often edits under time pressure and with weaker context. That is exactly when unsafe code slips in.

OWASP Top 10 in 2021 still lists injection among core application risks: https://owasp.org/Top10/. So I do not allow an automatic coding handoff to move forward without fresh checks. For Python-heavy repos, that usually means bandit. For generalized code patterns, semgrep. For secret exposure, gitleaks.

#!/usr/bin/env bash
set -euo pipefail

pytest -q
semgrep --config auto .
bandit -r app -q
gitleaks detect --no-banner --redact

echo "checks_passed=true"

On three recent agent deployments, I caught the same pattern more than once: the first agent used parameterized database access correctly, then the second agent, trying to patch a regression quickly, introduced raw SQL into a helper layer. That was not a model branding problem. It was a handoff quality problem.

What this looks like in a regulated European stack

For DACH clients in logistics, fintech, and industrial automation, I keep the architecture auditable. Source changes live in Git, task state lives in Postgres, secrets live in Doppler, orchestration runs in n8n, and each task keeps attached artifacts for tests and scans. This matters for operations, but it also matters for traceability. You need to answer who changed what, with which agent, under which checks, and where a human stepped in.

If you already use Supabase, do not limit it to app backend duties. It is a practical state layer for agent run logs, task routing, and simple operator views. The key is to avoid storing “memory” as one giant blob. Normalize fields so your system can route, audit, and block work deterministically.

FAQ

Do I need n8n for this pattern?

No. You can implement the same orchestration in Python with a job queue. I use n8n when teams want fast changes to routing logic, notifications, and webhooks without adding a separate orchestration service.

Should both agents work on the same branch?

Often yes, but only if commit SHA and task state are pinned. In higher-risk flows, create a fresh branch from the last validated commit and let the next agent continue from a controlled checkpoint.

Is a long handoff prompt enough?

No. A long prompt can summarize intent, but it cannot replace structured task state, command history, changed files, test output, and security results. Treat prompts as summaries, not as the source of truth.

When do you force human review?

Whenever the change touches authentication, authorization, SQL, secrets, payments, or personal data handling. The closer code is to a trust boundary, the less I want a fully automatic relay between agents.

How do I know my current handoffs are already failing?

If agents keep rescanning the whole repo, replaying the same commands, contradicting earlier decisions, or generating conflicting patches, your state transfer is too weak. That is an orchestration issue before it is a model issue.

Which stage in your LLM pipeline creates the most real production pain right now: quota interruptions, context loss, static analysis failures, or human review bottlenecks? I’d genuinely like to compare notes with teams shipping in regulated environments.
I run a free 30-min stack audit for DACH founders building AI in regulated markets. DM me on LinkedIn or write to @ger_dennis_ai.

Continue reading
Always-on agents are here: how to stop Claude Duet from becoming a source of leaks, false actions, and access chaos
LiteLLM got hijacked again: how to avoid losing SSH keys and API secrets through your AI gateway in production
If your AI agent needs web access, MCP is becoming the standard: what Firecrawl MCP actually fixes in production
MCP finally reached Go: how to build a production-ready agent server without drowning in custom glue code
All articles →
Where this is applied
Services — what we build
Talk to the voice agent
Case studies
Ready to build?

Turn your process into an AI system

Production quality. DACH B2B focus.

Start a project → ← All articles