◉GEMINI LABJP
●ARGON — gemini-4-argon is generally available as of 10/13, aimed at complex coding, agents, math and science●DEEP RES — deep-research-pro-preview-12-2025 shuts down 10/23, 6 days left. Move to deep-research-preview-04-2026●NANO — gemini-nano-banana-2.1 is GA (10/06). gemini-3.1-flash-image is deprecated with no shutdown date yet●MCP — One write-up cut an 85,000-token tool result to 310 tokens by wrapping it in an ADK FunctionTool●FLASH — gemini-3.7-flash and 3.5-flash now route automatically to newer Flash models (10/08)●NEW — Stop Re-Reading Every Crash Report: Gre…●ARGON — gemini-4-argon is generally available as of 10/13, aimed at complex coding, agents, math and science●DEEP RES — deep-research-pro-preview-12-2025 shuts down 10/23, 6 days left. Move to deep-research-preview-04-2026●NANO — gemini-nano-banana-2.1 is GA (10/06). gemini-3.1-flash-image is deprecated with no shutdown date yet●MCP — One write-up cut an 85,000-token tool result to 310 tokens by wrapping it in an ADK FunctionTool●FLASH — gemini-3.7-flash and 3.5-flash now route automatically to newer Flash models (10/08)●NEW — Stop Re-Reading Every Crash Report: Gre…
Articles/API / SDK
◈ API / SDK/2026-07-04Advanced

When Two Managed Agents Fight Over the Same Repo: External Leases and Fencing for Isolated Sandboxes

Every Managed Agents run gets its own isolated sandbox, so a local lock cannot stop two runs from touching the same repo or record. Here is how I serialize them safely with an external lease and a fencing token.

Gemini API249Managed Agents8agents9sandboxindie development28

✦ Premium Article

As an indie developer moving my personal site-update automation over to Managed Agents, I ran into a case where two runs hit the same repository almost simultaneously. One was a scheduled brush-up pass; the other was an article-generation run that had re-fired a little late. They started seven seconds apart. Both rewrote the same content/ directory and both tried to push to main.

Back when I ran my own loop on a single server, one line of file locking prevented exactly this. But Managed Agents spins up an independent Google-hosted Linux sandbox for every run. The two runs are effectively on different machines, and a lock held by one is not even visible to the other. That was the moment I had to redesign for a world where local locks simply do not work.

This article walks through how to safely serialize concurrent Managed Agents runs on isolated sandboxes using an external lease and a fencing token, with the code I actually run in production.

In an isolated sandbox, invisibility is what causes the collision

Let me describe precisely what happened. Both runs followed the same steps: shallow-clone the repo, write the article MDX, commit, and push. On their own, none of this is a problem. The trouble only appears when these critical sections overlap.

Measured over three weeks and roughly 210 automated runs, the period before I added leasing produced 3 duplicate pushes and 11 git pull --rebase conflict retries. A duplicate push is the case where both runs wrote different files and both succeeded. Nothing breaks, but you can end up publishing near-identical topics, and later it is hard to explain why there are two commits in a row. The 11 retries are cases where one run detected the push conflict and redid its work from a rebase; harmless, but each one burned tens of seconds for nothing.

On a single server you would put a mutual-exclusion lock at the entrance to that critical section and be done. Managed Agents does not let you. Here is why, layer by layer.

Why local locks do not work

"The lock does not work" actually hides several layers that all fail at once. Clearing them up front makes it easier to pick a replacement design later.

MechanismSingle serverIsolated sandbox (Managed Agents)
In-process mutexWorksDifferent process and machine, so meaningless
File lock (flock)WorksFilesystem is per-run and never shared
Holding a port or socketWorksSeparate network namespace, no collision
Conditional write to an external storeWorksWorks (the only shared point)

The point is singular. The only place both runs can reliably see the same thing is a shared store that lives outside the sandbox. So mutual exclusion has to be built on top of an atomic operation in that store. By atomic I mean the ability to read, check a condition, and write as one uninterruptible step. Firestore transactions, Postgres advisory locks or UPDATE ... WHERE, and Redis SET NX are all candidates.

I usually keep to Google-side stores, so here I build the smallest possible lease on Firestore transactions. It has three key behaviors: acquire, renew, and release.

✦

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
✦Why flock and in-process mutexes are useless across isolated sandboxes, and why an external store is the only shared point you have
✦A minimal acquire / renew / release lease built on Firestore transactions, with before and after code
✦How a fencing-token compare-and-set rejects the delayed writes of a zombie run whose lease already expired
Secure payment via Stripe · Cancel anytime
✦

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Gemini Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • ✦Copy-paste ready implementation code
  • ✦New advanced guides published daily
  • ✦$5/mo or $10 for lifetime access
View Membership →

Related Articles

◈ API / SDK2026-08-02
Measuring a Guard in environment hooks: 46 Microseconds to Decide, 23 Milliseconds to Start
A record of building a destructive-command guard for Managed Agents environment hooks. A regex denylist let 9 of 20 dangerous commands through; argv parsing reached 100 percent detection. The startup cost turned out to be 500 times the decision cost.
◈ API / SDK2026-09-29
The Size Column Said 'F6' and 'About A4' — I Let Gemini Read It, and Let a Table Do the Math
An artist's spreadsheet mixed 'F6', '41×31.8cm', and 'about A4' in one size column. Here is the small tool I built: Gemini reads each cell, a lookup table converts to centimeters, and the artwork image decides the orientation. Working code, step by step.
◈ API / SDK2026-09-11
When Transcription Keeps Mangling Proper Nouns: Choosing What Earns a Custom Vocabulary Slot
gemini-3.5-transcribe accepts up to 1,000 custom_vocabulary entries, but filling the list is not the goal. Here is a 60-line script that picks entries from your own reference-and-hypothesis pairs, plus the rules I use to decide what to leave out.