ANTIGRAVITY LABJP
Articles/Agents & Manager
Agents & Manager/2026-06-14Advanced

When Managed Agents Run in the Cloud, How Do You Hand Them Credentials?

The Antigravity 2.0 Managed Agents API runs agents in the cloud, away from your machine. Convenient, but the credential handling that was trivial on your own laptop suddenly gets hard. Here is a design for not handing over long-lived tokens, but issuing them per run and expiring them quickly.

Managed Agents3Antigravity233credentialsleast privilegeshort-lived tokenssecurity designcloud executionindie development11

Premium Article

While you run agents locally, credentials rarely come to the surface. An API key sits in your machine's environment variables and the agent just reads it. You know where the key is, and closing the laptop stops the run.

The first day I offloaded a task to the cloud via the Managed Agents API, I realized that comfort lived only on my desk. I went to pour a production deploy token into an environment variable for a cloud-run agent, the same way I always had, and my hands stopped.

That token would leave my machine, be used in a place I couldn't see, at a time I wasn't watching. If something leaked mid-flight, I couldn't quickly stop how far the damage reached or how long it lasted.

The essence of offloading an agent to the cloud is that execution leaves your hands. If so, the credentials have to be remade into a form that is safe once it leaves your hands too.

The fear of a long-lived token leaving your desk

Most credentials we use day to day are built to live a long time. Issue one, and it's valid until you explicitly revoke it. On the assumption that only you use it locally, that's fine.

The problem is that this property is a poor fit for cloud execution.

A long-lived token has three weaknesses. First, a leak doesn't stop: it can be reused until revoked, so the later you notice, the wider the wound. Second, the privilege is too broad: it's tempting to hand over a strong key "so it just works," and it reaches resources the agent never needed to touch. Third, you lose the trail: reuse the same token across runs and you can no longer separate which run did what.

Locally, all three stay latent. The blast radius is confined to your machine, broad privilege is an extension of your own actions, and your memory fills in the trail. But in the cloud, all three become operational risk as-is.

So the design stance is simple. Keep the long-lived strong key on your desk, and hand the cloud a different credential that lives briefly and reaches narrowly. That's the whole of it.

Issue per run, throw away when done

The first pillar is matching the token's lifetime to the run's lifetime.

Before starting an agent, issue a token meant only for that run. When the task ends, success or failure, revoke it. The next run receives a fresh token. With this in place, even if a token leaks mid-run, it is valid only for the short window until that run finishes.

It takes the shape of inserting a broker. Only the broker layer holds the strong key on your desk; the agent receives only the short-lived token the broker issued.

# token_broker.py — a broker that issues and revokes short-lived tokens per run
import time
import secrets
from dataclasses import dataclass
 
 
@dataclass
class LeasedToken:
    value: str
    scope: tuple[str, ...]      # only the actions this run is allowed
    expires_at: float
    run_id: str
 
 
class TokenBroker:
    """Hide the strong key inside; lend out only short-lived, narrow tokens."""
 
    def __init__(self, master_key: str, default_ttl: int = 600):
        self._master_key = master_key      # never leaves the desk
        self._default_ttl = default_ttl
        self._active: dict[str, LeasedToken] = {}
 
    def issue(self, run_id: str, scope: tuple[str, ...], ttl: int | None = None) -> LeasedToken:
        ttl = ttl or self._default_ttl
        token = LeasedToken(
            value=f"agt_{secrets.token_urlsafe(24)}",
            scope=scope,
            expires_at=time.time() + ttl,
            run_id=run_id,
        )
        self._active[token.value] = token
        return token
 
    def authorize(self, token_value: str, action: str) -> bool:
        token = self._active.get(token_value)
        if token is None:
            return False
        if time.time() > token.expires_at:
            self.revoke(token_value)        # expired means immediately invalid
            return False
        return action in token.scope         # reject anything outside the granted scope
 
    def revoke(self, token_value: str) -> None:
        self._active.pop(token_value, None)
 
 
# Usage
broker = TokenBroker(master_key="hide the strong production key here")
 
def run_agent_task(run_id: str):
    # pass only the actions this run needs
    token = broker.issue(run_id, scope=("read:articles", "write:draft"), ttl=300)
    try:
        dispatch_to_cloud_agent(run_id, token.value)   # the agent gets only the short-lived token
    finally:
        broker.revoke(token.value)                     # always revoke, success or failure

The key point is that revoke always runs in finally. Whether it crashes on an exception or finishes cleanly, the token dies at the end of the run. The short ttl is a second layer of insurance: even if the revocation itself never runs, the token stops working on its own once time runs out.

The agent-side code doesn't even need to be aware that its token is short-lived. It uses it as an ordinary token, and it naturally goes invalid when the run ends. The complexity is sealed inside the broker.

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 you must not hand long-lived tokens to cloud-run agents, and a design that replaces them with per-run short-lived tokens
A broker-layer implementation that exchanges one strong key for least-privilege tokens scoped to only what the agent touches
An operational pattern that revokes issued tokens reliably at run end, capping any leak's damage by time
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

Antigravity 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

Agents & Manager2026-06-14
Making My Managed Agents Batch Survive a Crash Without Redoing Everything
Running a 200-item batch on the Managed Agents API kept torching tokens, because every mid-run failure restarted from item one. Here is the checkpoint-and-idempotency design I added so the batch resumes from where it died.
Agents & Manager2026-06-12
Running Gemini's Managed Agents API: Where Cloud Execution Ends and My Local Agents Begin
A hands-on record of launching Gemini's Managed Agents (public preview) from Python — polling, artifact retrieval, and a cost guard — plus five criteria I use to decide what stays on my local CLI agents.
Agents & Manager2026-04-28
Before Your Antigravity Agent Bill Goes Sideways: A Solo Developer's Forecast and Cutback Playbook
Discovering your monthly bill is an order of magnitude larger than expected is the first big trap of running agents. Here's the forecasting and cutback playbook I've built up as a solo developer, plus the monthly review cycle I use.
📚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 →