8 min read

How to build scalable, safe execution environments for AI agents

Published on
November 5, 2026
Author
Norbert Liki
Norbert Liki
Lead Data Scientist Architect
Subscribe to our newsletter
Subscribe
How to build scalable, safe execution environments for AI agents

Executive summary:

  • The Problem: Standard function-calling AI assistants lack safe, stateful execution environments to validate their work.
  • The Solution: A decoupled architecture separating the control plane (orchestration, policy) from the execution plane (agent harness, workspace).
  • The Tech Stack: Google Cloud, GKE Agent Sandbox, opencode harness, and GKE Pod snapshots for resumable state.

The fundamental problem in AI engineering is how to provide developers with agents without the risk of them causing harm. Furthermore, how can one assign complex, undefined tasks—such as troubleshooting or feature development—to these agents? Additionally, how can knowledge be scaled across a team?

To answer these questions, agents need more than just a list of functions; they require a secure, persistent environment to safely explore, execute, and validate their work. In this article, we explain the architecture we designed to solve this for a data-engineering customer on Google Cloud.

The solution integrates an existing web application and agent orchestration layer, an embedded coding-agent harness, and a dedicated GKE Agent Sandbox for each workspace. This setup not only isolates execution but also uses snapshots to create resumable workspaces, ensuring an engineer's running processes are safely saved and restored after a break. We also share what this proof of concept taught us about isolation, identity, networking, persistence, latency, and operations. 

Why do AI agents need dedicated execution environments?

The customer wanted data engineers to use AI without installing and governing agent harnesses on every engineer's workstation. The team had no direct subscription with other model provider: Google Cloud had to remain the inference and billing boundary.

The customer had built an early web-based prototype connected it to Azure DevOps, BigQuery, Dataform, Cloud Composer, Power BI, and a curated knowledge base in Agent Search. The prototype used separate specialized agents with dedicated tools and prompts for jobs such as data pipeline development, architecture validation, and user-story creation based on vague feature ideas.

The prototype was useful, but it was a basic function-calling assistant without any loop, its architecture stopped at question → function call → answer. That shape has four limitations:

  1. There was no correction loop. The agent could not make a change, run a test, inspect the failure, and try again.
  2. Documentation became stale. The agents depended on manually maintained descriptions rather than inspecting the current repository and live environment.
  3. Tool selection was unreliable. A growing flat list of functions gave the model more choices, but not a robust work method.
  4. There was nowhere safe to execute. Giving the web application a general-purpose shell would have mixed users, credentials, files, and long-running processes in one trust boundary.

The missing capability was a controlled execution plane in which an agent could explore and validate its work, while continuing to use models through Google Cloud.

The limitations also pointed to a simpler agent structure, most roles did not need independent agents with duplicated function lists. They needed one capable execution loop with skills loaded for the task. A data pipeline skill can encode repository conventions and validation; a story-refinement skill can define its workflow and output; skills stored in a repository change together with its code. Separate agents remain useful for different identities or lifecycles, not merely different instructions.

What are the security constraints for AI agent sandboxes?

A production execution environment should be designed from the threat model, not from the demo. Treating all generated commands as untrusted, enforcing short-lived scoped identity via Workload Identity Federation, and blocking internal network ingress/egress while allowing only specific public HTTPS endpoints is crucial. Our key constraints were:

  • Treat generated commands as untrusted. Prompt injection, a malicious repository, or a model mistake can all produce dangerous shell activity.
  • Isolate concurrent work. One workspace's repository, generated files, process state, and credentials must not be visible to another.
  • Use short-lived, scoped identity. Avoid downloaded service-account keys. A task should receive only the APIs and repositories it needs.
  • Control both ingress and egress. Isolation is incomplete if a sandbox can scan internal services or send source code to arbitrary destinations.
  • Keep EU processing available. Compute location and model endpoint are separate decisions; both must meet the workload's residency requirements.
  • Preserve a human approval boundary. The target output is evidence plus a pull request, not an autonomous production change or merge.
  • Start quickly, scale down cheaply, and let engineers return. Interactive users will not wait minutes for every chat. Idle environments should not run forever, but an engineer who comes back after lunch should not lose a half-finished investigation.

How to choose an execution environment for AI agents

The comparison reflects the options as we assessed them in October 2026.

Option Primary Advantage Key Limitations/Risks Best fit
Shell in the application container Fastest prototype Shared blast radius; weak session and credential isolation Local experiments only
Container, Cloud Run job, or VM per task Familiar primitives and flexible images More lifecycle code; cold starts or idle cost; isolation is still our responsibility Short jobs or long-lived developer workspaces
Provider-managed cloud coding sessions (Claude Code on the web, Codex cloud, GitHub Copilot coding agent) Harness, compute, and scaling arrive together Usually tied to a provider subscription, provider-hosted inference, and GitHub-centric workflows; less control over residency and networking Teams already standardized on that provider and source-control platform
Agent Runtime + Agent Platform Code Execution sandbox Managed GCP agent runtime, sessions, identity, scaling, and isolated stateful code execution The standard code sandbox has a limited filesystem, no network, and fixed libraries; it is better for analysis than cloning repositories and running real build toolchains Agent Development Kit (ADK) agents executing bounded Python or data-analysis tasks
Third-party managed sandbox Fast integration and good cold starts Another vendor boundary; verify identity, egress, image, and residency controls Teams optimizing for speed to market
GKE Agent Sandbox per workspace Custom images, gVisor isolation, policy control, warm pools, Pod snapshots, and native GCP identity Kubernetes complexity and cluster cost Governed, interactive engineering execution

Governed, interactive engineering execution

The provider-managed options were poor fits because the customer had no model-provider subscription and wanted inference to remain in GCP. Agent Runtime was strategically attractive, but its standard Code Execution sandbox did not provide the networked, customizable engineering workspace needed to clone Azure Repos and run project toolchains. Custom containers can narrow that gap, and Agent Runtime remains an option as the managed control plane matures. A VM per engineer also gives long-lived workspaces, but it keeps paying for idle machines and leaves isolation, images, and lifecycle to us. Pod snapshots let us keep sandbox isolation while a suspended workspace costs only its snapshot storage.

For the proof of concept we chose GKE Agent Sandbox. It combines Kubernetes scheduling and policy with a gVisor-isolated runtime designed for agent-generated code, while allowing our own harness image and Gemini Agent Platform inference. It is not a complete security system by itself: IAM, network policy, secret delivery, image security, quotas, and audit logging still matter.

Architecture: Decoupling the control and execution planes

We defined a hard boundary: the control plane authenticates and applies policy, while the execution plane (the sandbox and harness) does the actual work with bounded CPU, memory, time, and network access. The key design decision is to keep orchestration outside the sandbox and the agent's work inside it.

The control plane authenticates the user, applies policy, creates and resumes workspaces, and records lifecycle events. It should not run model-generated commands. The sandbox image and the harness configuration define which models, tools, and permissions are available; the harness loads skills itself. A SandboxClaim is the GKE Agent Sandbox resource that requests a sandbox; when a pre-started sandbox is free in the warm pool, the claim binds to it at once. In the prototype, the gateway serves opencode's own web UI from the sandbox. Providing a nice UI for not just chatting with the agents but actually observing what they change and edit files directly.

The execution plane contains the coding-agent harness and workspace. It can use file, shell, and repository tools, but only inside a sandbox with bounded identity, network access, CPU, memory, time, and storage.

The execution environment and the harness are separate choices. We selected opencode because the complete harness was open source, built to embed as a server, and had a directly validated Gemini-on-Vertex path without a separate provider subscription. It already provided repository exploration, file and shell tools, a multi-step work-check-correct loop, event streaming, and permissions. In the second iteration of our prototype, we replaced our own chat UI with opencode's native web interface, which already provides session, file, diff, and terminal views. A chat alone is not enough: engineers need to inspect, edit, and comment on what the agent changed before they continue the conversation. One workspace, one sandbox

A shared sandbox is acceptable for proving that a model can clone and inspect a repository. It is not a multi-user architecture. A Kubernetes Service in front of a pool is also insufficient: normal load balancing may send consecutive requests to different filesystems.

Our first iteration bound each chat thread to its own sandbox and deleted it after an idle timeout. That model was safe, but it lost context: every new conversation started from an empty disk, and engineers often wanted a second conversation about the same checkout. The second iteration therefore makes the workspace the isolation boundary:

  • A workspace owns one stable SandboxClaim, one gVisor Pod at a time, its /workspace files, and its snapshots.
  • A session is an opencode conversation inside a workspace. Several sessions share the workspace's files and processes, which is what engineers expect when they discuss the same repository. Sessions are not isolated from each other: two agents changing the same checkout at the same time can conflict, as two engineers in one clone would. Use separate workspaces for independent parallel changes.
  • Creating a new workspace is the way to get a new isolation boundary.

The workspace gateway keeps one durable record per workspace (in our prototype, a Kubernetes ConfigMap). The record holds the claim, the snapshot group, the lifecycle state, and the last activity time. A gateway restart or deployment therefore does not lose or delete workspaces. Each workspace is served on its own browser origin, because opencode's web UI selects its server by origin and separate origins let two workspaces stay open side by side. The gateway resolves the workspace's current Pod address on every request instead of caching it, because a restored Pod usually gets a new IP address.

A warm pool keeps a few sandboxes started in advance, so a new workspace does not wait for a new node, which can take minutes. When a workspace is closed, its sandbox and snapshots are deleted rather than returned for reuse, and the warm pool provisions a fresh replacement. Filesystem and process state therefore do not cross workspace boundaries.

Resumable workspaces with Pod snapshots

GKE Pod snapshots capture a whole Pod: its filesystem and the memory of its running processes. That is the difference from a persistent volume. A volume keeps files, but the agent harness would restart cold. A Pod snapshot brings back the running opencode server, including its sessions, so the engineer sees the same conversation, files, and diffs after a resume.

After about 15 minutes without user or agent activity, the gateway suspends the workspace. Suspension must never capture a workspace in the middle of a change, so the gateway follows a strict order:

  1. Block new writes to the workspace and let requests in progress finish.
  2. Ask opencode, for every project directory it has opened in the workspace, whether an agent turn or terminal is active. If either is active, the workspace stays running.
  3. Take the snapshot and accept it only after GKE reports it as complete.
  4. Suspend the sandbox and wait until the original Pod is gone before the workspace is marked as suspended.

A resume is accepted only when a different Pod reports that it restored the recorded snapshot. A Pod that starts without that confirmation is not accepted as a restore, even if Kubernetes reports it as ready.

This verification proved necessary. In our October 2026 tests, on newly provisioned Autopilot nodes, some restores started an empty Pod instead of the saved state, with the error the storage backend may not be available. The saved snapshots were intact and restored correctly once the nodes were initialized. We did not establish the root cause. The gateway now keeps the workspace blocked, removes the empty Pod without taking a snapshot of it, and retries the same snapshot once. If that also fails, the engineer sees a Retry restore action instead of a silently empty workspace.

Other practical lessons:

  • Snapshots need supported hardware. Whole-Pod snapshots do not support the E2 machine family, so sandboxes are pinned to N2 nodes through a ComputeClass.
  • Pin images per workspace. A snapshot can only restore into a compatible image. New sandbox images go to a new, versioned warm pool, and existing workspaces stay on their original image until they are closed.
  • Group snapshots per sandbox. Snapshot grouping by the sandbox's identity label prevents one workspace from restoring another workspace's state. We keep at most three snapshots per workspace to bound storage.
  • Know your recovery point. The latest completed snapshot is the recovery point. Work done after it can be lost if a Pod or node fails unexpectedly. A snapshot taken on suspension is not a continuous backup.
  • Suspend and resume take seconds. On initialized nodes, suspend took about 16 seconds and resume about 18 seconds in a single measured run.

At the time of our tests, Google's suspend/resume tutorial used a manually installed Agent Sandbox controller. In our tests, the managed GKE add-on completed snapshot, suspend, and resume, so we kept the manual controller only as a documented fallback.

Security is a stack of boundaries

The sandbox is only one layer. The prototype implements gVisor isolation, Workload Identity Federation, a non-root runtime with resource limits, images pinned by digest, and a dedicated, access-restricted snapshot bucket. The rest of this list is our recommended production baseline; the gaps are listed further below.

  • Identity: use Workload Identity Federation instead of key files. Grant permissions by task, separate read from write, and use delegated user access where downstream row- or column-level authorization must follow the human.
  • Network: default-deny ingress and egress. Use Kubernetes NetworkPolicy for pod and IP/CIDR boundaries, and route external HTTPS through an egress proxy or firewall with an FQDN-aware allowlist for model, source-control, and Google API endpoints. Add narrow rules separately for DNS and the identity metadata server. Test the policy: blocking DNS or metadata breaks the workload, while broad HTTPS egress defeats data-loss controls.
  • Runtime: run a minimal, approved image as a numeric non-root user; enforce CPU, memory, time, and storage limits; delete the workspace and its snapshots when the user closes it.
  • Secrets: inject short-lived credentials only when needed. Keep them out of prompts, logs, repositories, image layers, and persistent volumes.
  • Snapshots: a whole-Pod snapshot contains process memory, which can include short-lived tokens and repository content. Protect the snapshot bucket like the workspace itself: a dedicated bucket, narrow IAM, an encryption-key policy that meets your requirements, a retention limit, and deletion on close.
  • Actions: allow low-impact reads and tests, but require confirmation for writes. Keep merges, production mutation, IAM changes, and schema migrations outside the agent's authority. Cap retries and spend.
  • Supply chain and audit: pin, scan, and sign images. Record the image, identity, policy, tool calls, resource use, and resulting artifacts without logging sensitive content by default.

The broader lesson: The Death of the Specialized Agent

For complex problems—where you aren't just addressing a single workflow—a different kind of solution is required.

Specialized agents with their own dedicated tools are becoming obsolete, probably they were not the answer in the first place; instead,  you need a general-purpose harness, augmented with your domain knowledge and access to your tools.

Furthermore, you need a secure environment where this harness can operate without causing any harm.

Agent safety comes from making the environment safe when the model is wrong.

In practical terms: reuse a capable harness, run each workspace in its own sandbox, suspend it safely when idle, grant the minimum identity and network access, collect evidence, and stop at a human approval gate. This architecture lets agents inspect the current code and systems instead of depending on stale documentation, while keeping their execution bounded enough to earn trust incrementally.

Providers no longer only host models: they now offer whole agent harnesses as managed APIs. Claude Managed Agents and Google’s Managed Agents (Gemini API and Agent Platform) each run the vendor’s own agent loop in a hosted sandbox. Google’s open-source Agent Substrate gives GKE built-in, sub-second suspend and resume, which covers much of the lifecycle code we wrote by hand. In October 2026, the two managed APIs were in preview or beta, tied to the vendor’s harness and models, and had no EU inference pin. Agent Substrate was for non-production use only. We expect the build-versus-buy line for agent execution to move soon.

‍

Author
Norbert Liki
Lead Data Scientist Architect
Subscribe to our newsletter
Subscribe