Credentials API for Gemini Managed Agents
We recently shipped the Credentials API for Managed Agents (antigravity-preview-09-2026). It lets your agent authenticate with external services like GitHub, Notion, or the Gemini API without putting raw secrets inside the Linux sandbox.

If you pass an API key as a normal environment variable, any dependency or script inside the sandbox can read os.environ and leak it. With the Credentials API, the secret stays on the server and is injected on the wire by the egress proxy.
How it works
1. Store the secret once
Register a credential with credentials.create(). Secrets are write-only and encrypted at rest; API responses only return metadata (id, type, status, timestamps).

There are 3 credential types:
bearer_token: Static tokens and API keys injected as HTTP headers (Authorization: Bearer <token>by default, or customheader_nameandprefix).oauth2: Refresh tokens (client_id,client_secret,refresh_token,token_url). Gemini exchanges and refreshes access tokens automatically before expiry.environment_variable: For CLIs and SDKs that read secrets from the process environment. The container receives a placeholder (__GEMINI_CRED_<id>__), and the egress proxy swaps in the real value only for requests totrusted_domains.
2. Reference it by ID
Pass the credential id when defining a reusable agent with agents.create() (or per run in interactions.create()) on a remote mcp_server tool, a domain in network.allowlist, or a variable in base_environment.env.

3. Injected on the wire
When the agent calls an MCP tool or makes an outbound HTTP request from the sandbox, the egress proxy checks the target domain and injects the real credential on the wire.

Example Reviewing and smoke-testing GitHub PRs
Here is a practical examples on a reusable custom agent that manages google-gemini/cookbook via the Github MCP server and can make securte Gemini API calls. The GEMINI_API_KEY is bound as a credential, untrusted code in the sandbox can call generativelanguage.googleapis.com without ever seeing the real API key.

Create a read-only GitHub token
- Open GitHub Fine-grained Personal Access Tokens and click Generate new token.
- Scope Repository access to your target repositories and set Pull requests and Contents permissions to Read-only.
- Export
GITHUB_PATandGEMINI_API_KEYlocally.
Run the agent
Install the SDK (bun add @google/genai) and run:
import { GoogleGenAI } from "@google/genai";
const ai = new GoogleGenAI({});
// 1. Store credentials once
const github = await ai.credentials.create({
id: "github-mcp",
type: "bearer_token",
token: process.env.GITHUB_PAT!,
});
const geminiKey = await ai.credentials.create({
id: "gemini-key",
type: "environment_variable",
value: process.env.GEMINI_API_KEY!,
injection_location: ["header", "query"],
trusted_domains: ["generativelanguage.googleapis.com"],
});
// 2. Define a reusable agent wired to both credentials
const agent = await ai.agents.create({
id: "cookbook-pr-reviewer",
base_agent: "antigravity-preview-09-2026",
system_instruction:
"You are a maintainer for google-gemini/cookbook. Use the github tools to inspect pull requests, and use the sandbox to smoke-test Gemini API snippets and draft release notes.",
tools: [
{ type: "code_execution" },
{
type: "mcp_server",
name: "github",
url: "https://api.githubcopilot.com/mcp/",
credential: github.id,
},
],
base_environment: {
type: "remote",
env: {
GEMINI_API_KEY: { credential: geminiKey.id },
},
},
});
// 3. Run the agent
const interaction = await ai.interactions.create(
{
agent: agent.id,
environment: "remote",
input:
"Draft a release note for the 3 most recently merged PRs in google-gemini/cookbook, and run a live smoke test against gemini-3.8-flash in the sandbox to verify the code snippet works.",
},
{ timeout: 300000 },
);
console.log(interaction.output_text);Output:
# Release Notes: `google-gemini/cookbook`
### 1. [PR #1347](https://github.com/google-gemini/cookbook/pull/1347) - Zero-Cloud Local Hybrid RAG Recipe with SQLite FTS5 & Gemini
- **Author:** @Cagrik34 | **Merged At:** 2026-09-28 10:49:52 UTC
- **Summary:** Combines SQLite FTS5 (`unicode61`) BM25 search with `text-embedding-004` dense vectors and Reciprocal Rank Fusion (RRF, k=60) in `examples/Zero_Cloud_Hybrid_RAG_SQLite_FTS5_Gemini.ipynb`.
### 2. [PR #1383](https://github.com/google-gemini/cookbook/pull/1383) - Fix `musicGenerationConfig` Schema in Lyria RealTime Notebook
- **Author:** @kkorpal | **Merged At:** 2026-09-28 10:29:00 UTC
- **Summary:** Updates `music_generation_config` to `musicGenerationConfig` and flattens the payload in `quickstarts/Get_started_LyriaRealTime.ipynb`.
### 3. [PR #1384](https://github.com/google-gemini/cookbook/pull/1384) - Fix HTTP 400 BadRequest via File API in Prompting Notebook
- **Author:** @kkorpal | **Merged At:** 2026-09-25 12:29:48 UTC
- **Summary:** Switches multimodal image upload in `quickstarts/Prompting.ipynb` to `client.files.upload`.What happens during the run:
- GitHub MCP (
github-mcp): Connects toapi.githubcopilot.com/mcp/and callsgithub:list_pull_requestsandgithub:pull_request_readto inspect the latest merged PRs (#1347,#1383,#1384). - Sandbox execution (
gemini-key): Inside the container,$GEMINI_API_KEYis__GEMINI_CRED_gemini-key__. When the smoke test callsgenerativelanguage.googleapis.com, the egress proxy swaps the placeholder for the real key on the wire. - Domain restriction: Any request carrying
__GEMINI_CRED_gemini-key__to a domain outsidetrusted_domainsis blocked (403).
Rotate or delete credentials
Update a credential by ID to rotate its secret without changing your agent definition, or delete it when it is no longer needed:
await ai.credentials.update("github-mcp", {
type: "bearer_token",
token: process.env.GITHUB_PAT_NEW!,
});
await ai.credentials.delete("github-mcp");
await ai.credentials.delete("gemini-key");See the Credentials API docs, Custom Agents guide, and Managed Agents Quickstart for full details.
Thanks for reading! If you have any questions or feedback, please let me know on Twitter or LinkedIn.