GEMINI LABJP
MODEL — Gemini 3.5 Flash reaches GA and now powers gemini-flash-latestAGENT — Managed Agents enter public preview in the Gemini API, running in isolated Google-hosted Linux sandboxesSEARCH — File Search adds multimodal search, embedding and searching images natively via gemini-embedding-2WEBHOOK — Event-driven webhooks arrive for the Batch API and long-running operations, replacing pollingEMBED — gemini-embedding-2 is now generally available for production embeddingsDEPRECATION — Several image generation models shut down on August 17, so plan migrations nowMODEL — Gemini 3.5 Flash reaches GA and now powers gemini-flash-latestAGENT — Managed Agents enter public preview in the Gemini API, running in isolated Google-hosted Linux sandboxesSEARCH — File Search adds multimodal search, embedding and searching images natively via gemini-embedding-2WEBHOOK — Event-driven webhooks arrive for the Batch API and long-running operations, replacing pollingEMBED — gemini-embedding-2 is now generally available for production embeddingsDEPRECATION — Several image generation models shut down on August 17, so plan migrations now
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 API168Managed Agents4agents8sandboxindie development7

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-06-28
The Morning a Managed Agent Stalled and Left No Trace — Building a Run-Observability Layer Outside the Sandbox
With Gemini Managed Agents, the sandbox lives on Google's side, so when a run stalls there is nothing left in your own logging stack. This is a working TypeScript design for an outside observability layer that taps stream events into a ledger, detects silent stalls, and folds runs into readable postmortems.
API / SDK2026-06-20
Gemini API Grounding × Structured Output Guide — Turn Web Search Results into Typed JSON Data
Combine Gemini API Grounding with Google Search and Structured Output to extract real-time web information as type-safe JSON data. Practical implementation patterns included.
API / SDK2026-06-16
Wiring Gemini Managed Agents Into Your Automation: Keeping Conversation State and Environment State Apart
Managed Agents spin up a Linux sandbox, run an agent loop, and return a result in a single API call. The first thing that trips you up when moving off a hand-rolled loop is that conversation state and file state are two separate things. Here's that design, worked through live.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →