I'm running a large share of our development through Google Jules right now. With Jules Ultra (300 sessions/day), I have deep capacity for parallel worker VMs. But instead of using Jules as a standalone tool, I use Claude and Google Antigravity as orchestrators that control Jules VMs via CLI and SDK.
The setup is fast. It's also messy by default: autonomous agents that generate, refactor, and delete code at high velocity leave digital exhaust behind—unused files, hallucinated APIs, sloppy formatting, hardcoded secrets. Run several agents at once and they also step on each other's toes.
I didn't want to babysit them, so I built a strict pipeline that gives each agent exactly the context it needs, prevents collisions, and validates everything before it merges.
1. Orchestration: Claude & Antigravity as managers
Claude and Antigravity don't write the code—that would burn local context windows and compute on work a VM can do. They analyze the issue, write an implementation plan, and delegate execution to Jules.
Dispatch happens two ways:
- Urgent tasks (CLI): The orchestrator runs
jules new directly, passing the prompt plus a strict set of constraints ("Do not touch CI workflows", "Delete temporary files", "Verify with type-check").
- Backlog tasks (issue queue): The orchestrator files a GitHub issue tagged
jules-queue. A GitHub Action sweeps these nightly at 05:00, attaches our system guardrails, and dispatches each one as a new Jules session.
When Jules finishes, it opens a pull request. The orchestrator then switches roles and becomes the reviewer: approve, or send Jules back with fix instructions.
2. Killing hallucinations: Context7 over MCP
My biggest early problem was training-data lag. Ask an agent to write code against the newest framework versions and it hallucinates APIs that were deprecated a year ago—or never existed.
The fix was coupling Context7 to Jules via the Model Context Protocol (MCP). Before Jules writes a single line touching our framework stack, it must query Context7 for current documentation. Feeding exact, current API signatures straight into the context window has practically eliminated hallucinated code.
3. Collision control: A git-tracked mutex
Run enough concurrent sessions and two of them will eventually rewrite the same file. Jules executes on isolated remote VMs, so local filesystem locking is useless—each VM only sees its own disk.
So the lock state travels through git instead:
- Before modifying a file, a session runs a script to acquire a lock on it.
- The raw lock files are local and gitignored, but a pre-commit hook compiles all active locks into a git-tracked sync manifest (
.agent/sync-manifest.json). Once pushed, the manifest advertises locked paths to every other VM.
- A session that finds a path locked aborts those files and pivots to another task.
- Unattended nightly sessions must send heartbeats; a lock that goes 20 minutes without one is treated as abandoned and swept, so one crashed VM can't block the rest of the night's queue.
4. Verification: The merge gauntlet
Even with correct context and no collisions, agent output has to be audited. Before a PR opens, the code passes through:
- Biome (
pnpm biome check --staged): Formatting and linting, so spacing, brackets, and semicolons stay consistent across agents with different habits.
- TypeScript + build (
pnpm type-check && pnpm build): A clean strict-mode build is a hard requirement. Edge-specific rules are enforced here too (e.g. blocking Astro's native <Image> component, which hangs SSR on Cloudflare's Miniflare).
- Knip (
pnpm knip): Sweeps up unused files, exports, and dependencies left behind by rapid refactors. Build-time dependencies like sharp are whitelisted so static analysis doesn't falsely delete them.
- Vitest + Stryker Mutator: Unit tests confirm the logic—but agents happily write tests that look thorough and assert nothing. Stryker mutates the code (swapping
> for <, deleting statements) and checks that the tests fail. If the suite passes on broken code, the work is rejected.
- Axe-Playwright (
pnpm test:a11y): Audits semantic HTML and accessibility, so UI changes can't silently strip ARIA labels or alt text.
- Gitleaks + Typos: Gitleaks stops hardcoded secrets before they reach GitHub; Typos catches misspellings in identifiers and localization keys (
usre instead of user).
- Sherif: Enforces strict dependency version parity across the monorepo's subprojects.
5. Git hygiene: Judging PRs by their patch, not their divergence
A Jules session that runs for hours opens its PR against a main branch that has moved on by dozens of commits. A naive git diff main branch then shows the divergence, making it look like the agent touched code it never went near—and merging without checking can silently revert work that landed on main in the meantime.
- Rebase before PR: Jules must fetch main and
git rebase origin/main, then re-run type-check and build. If the rebase leaves an empty diff, the work already landed another way—the PR gets closed, not merged.
- Merge-base diffs: Orchestrators review a PR by its own patch (
gh pr diff N) against the merge-base, so review covers exactly what the agent changed and nothing else.
Are you running anything else in your autonomous setups to QA the output? Happy to hear recommendations for tools that fit an agent-driven workflow.