Prompt

How do I set up an autonomous agent SDK for code execution workflows with sandboxing and retries?

Latest observation

Jul 19, 2026 · OpenAI APIWeb search: off

A good pattern is:

  1. Use an agent framework to plan and call tools.
  2. Run code in a sandbox that has strict resource and network limits.
  3. Wrap execution in retry logic for transient failures.
  4. Add guardrails: allowlisted files, timeouts, max output size, and human approval for risky steps.

Below is a practical setup that works well for code-execution workflows.


1) Choose the architecture

You generally want these pieces:

  • LLM / planner: decides what to do next
  • Tool layer: functions like run_code, read_file, write_file, git_diff, tests
  • Sandbox runner: isolated execution environment
  • Orchestrator: retries, state tracking, logs, cancellation

A common loop is:

  1. Agent proposes a step.
  2. Tool call runs in sandbox.
  3. Result is returned.
  4. If error is retryable, retry with backoff.
  5. If non-retryable, stop or ask for clarification.

2) Pick a sandbox strategy

Recommended options

A. Docker container per run

  • Good default for most teams
  • Easy to enforce:
    • filesystem isolation
    • CPU/memory limits
    • process limits
    • network disablement
  • Best for local or server-side code execution

B. Firecracker / microVM

  • Stronger isolation
  • Better for untrusted code at scale
  • More operational complexity

C. Language-specific sandboxes

  • e.g. Pyodide, JS VM, WASM
  • Great for limited use cases
  • Not ideal for general code workflows

If you’re starting out, use ephemeral Docker containers.


3) Define your tool interface

Typical tools:

  • run_code(language, code, files, timeout)
  • run_tests(command)
  • read_file(path)
  • write_file(path, content)
  • apply_patch(diff)
  • list_files(path)

Keep tools narrow. Don’t expose raw shell unless you must.


4) Implement sandbox execution

Example: Python worker with Docker

You can create a container per execution, mount a working directory, and disable network.

Pseudocode

def run_in_sandbox(image, workdir, cmd, timeout=30):
    return docker_run(
        image=image,
        command=cmd,
        mount=workdir,
        network_disabled=True,
        memory_limit="512m",
        cpu_limit="1.0",
        pids_limit=128,
        timeout=timeout,
        read_only_root=True,
    )

Key safety settings

  • network_disabled=True
  • timeout=...
  • memory and CPU limits
  • read-only root FS
  • mount only a temp workspace
  • run as non-root
  • cap stdout/stderr size

5) Add retry logic

Retries should only happen for transient failures:

  • container start failure
  • temporary resource contention
  • flaky tests
  • external service timeout, if you allow any networked tools

Do not retry endlessly on:

  • syntax errors
  • failing assertions
  • permission errors
  • missing file errors
  • deterministic crashes

Retry policy

  • max 2–3 retries
  • exponential backoff with jitter
  • classify errors into retryable / non-retryable

Example

import time, random

def retry(fn, max_attempts=3):
    for attempt in range(1, max_attempts + 1):
        try:
            return fn()
        except RetryableError as e:
            if attempt == max_attempts:
                raise
            sleep = (2 ** (attempt - 1)) + random.uniform(0, 0.5)
            time.sleep(sleep)

Error classification

  • Retryable: timeout, transient container failure, deadlock from resource limits
  • Not retryable: code error, test failure, bad input

6) Create the agent loop

Your orchestrator can look like this:

while not done:
    action = agent.next_action(context)

    if action.type == "run_code":
        result = retry(lambda: sandbox.run(action.payload))
        context.add(result)

    elif action.type == "write_file":
        workspace.write(action.path, action.content)

    elif action.type == "run_tests":
        result = retry(lambda: sandbox.run_tests(action.command))
        context.add(result)

    elif action.type == "finish":
        done = True

Important:

  • feed the agent only relevant outputs
  • truncate very large logs
  • keep state explicit

7) Put guardrails on code execution

Strongly recommended:

  • Allowlist commands
  • No arbitrary outbound network
  • File path restrictions
  • Execution timeouts
  • Output size limits
  • Max number of steps per task
  • Audit logs for every action

If the agent can edit files, restrict it to a project workspace only.


8) Use structured outputs from the LLM

Instead of free-form text, have the model output structured actions like:

{
  "tool": "run_tests",
  "args": {
    "command": "pytest -q"
  }
}

This reduces ambiguity and makes retries easier.


9) Observability and debugging

Track:

  • prompt and tool calls
  • sandbox command, exit code, duration
  • stdout/stderr
  • retries and reasons
  • final artifact/diff

This is essential for diagnosing flaky behavior.


10) A simple production-ready stack

A solid MVP stack could be:

  • Agent orchestration: LangGraph, Semantic Kernel, AutoGen, or your own loop
  • LLM: any tool-calling model
  • Sandbox: Docker
  • State store: Redis/Postgres
  • Job queue: Celery, RQ, Sidekiq, or managed queue
  • Logging: structured JSON logs + tracing

11) Minimal implementation plan

Phase 1

  • Build run_code tool in Docker
  • Disable network
  • Add timeout and memory limits

Phase 2

  • Add agent loop with structured tool calls
  • Add retries for transient execution failures

Phase 3

  • Add file tools and test runner
  • Add output truncation and audit logs

Phase 4

  • Add policy checks:
    • disallow dangerous commands
    • require approval for sensitive actions

12) If you want a concrete example

I can give you one of these:

  1. Python example using Docker + OpenAI tool calling
  2. Node.js example with a sandboxed executor
  3. LangGraph-based autonomous coding agent
  4. Kubernetes-backed sandbox runner design
  5. Firecracker microVM architecture

If you want, I can provide a full working starter template next.

Observation history

Unlock observation history

Create a free Obsurfable account to unlock historical responses, model comparisons, and deeper brand intelligence.

How did Obsurfable measure this prompt?

Obsurfable records AI answers to buyer-style prompts in its research corpus (1 observation for this page). Metrics are distributions over observations, not a single static ranking.

Which AI systems does Obsurfable collect answers from?

OpenAI, ChatGPT, Google, Gemini, Google AI Mode, Anthropic, Claude, Perplexity, Grok, DeepSeek, Mistral, Copilot, and Meta AI.