n4nAI

How to give AutoGen agents code execution tools

Step-by-step guide to adding AutoGen code execution tools so agents can run Python securely, with runnable examples and verification tips.

n4n Team3 min read753 words

Audio narration

Coming soon — every post will get a voice note here.

AutoGen code execution converts a language model into an agent that can write and run Python to accomplish tasks. This guide shows how to stand up a sandboxed executor, attach it to a UserProxyAgent, and verify the full loop with a real computation.

Step 1: Install AutoGen and its code-execution dependencies

Use the pyautogen package (AutoGen 0.2.x). It ships the agent orchestration and the local code executor.

pip install pyautogen docker

The docker extra is optional but recommended if you want container isolation. For a quick local test, the local executor works without Docker.

Step 2: Configure the model client

AutoGen expects an OpenAI-style client config. If you run your own gateway or want a single endpoint that fronts many models, point base_url at an OpenAI-compatible server. For example, n4n.ai exposes one OpenAI-compatible endpoint covering 240+ models with automatic fallback when a provider is rate-limited, which simplifies model routing.

llm_config = {
    "model": "gpt-4o-mini",
    "api_key": "sk-...",  # or from env
    "base_url": "https://api.n4n.ai/v1",  # optional: use your gateway
    "temperature": 0.2,
}

If you omit base_url, the client hits OpenAI directly. Keep api_key in environment variables; don’t hardcode it in source. The temperature setting matters: lower values make the assistant stick to deterministic code generation rather than creative prose.

Step 3: Pick a code executor and lock down the workspace

AutoGen provides LocalCommandLineCodeExecutor and DockerCommandLineCodeExecutor. The local executor runs code in a designated directory on your machine. The Docker executor runs it inside a container with a mounted volume.

from autogen.coding import LocalCommandLineCodeExecutor
import os

work_dir = os.path.join(os.getcwd(), "autogen_workspace")
os.makedirs(work_dir, exist_ok=True)

executor = LocalCommandLineCodeExecutor(
    work_dir=work_dir,
    timeout=60,  # seconds
    virtual_env_path=None,  # or path to venv
)

For production, swap in DockerCommandLineCodeExecutor:

from autogen.coding import DockerCommandLineCodeExecutor

executor = DockerCommandLineCodeExecutor(
    image="python:3.11-slim",
    work_dir="/workspace",
    timeout=60,
)

The executor only writes and runs files inside work_dir. That limits blast radius, but local execution still grants full user-level access to the host. Use Docker or a dedicated VM for untrusted input.

You can test the executor in isolation before involving agents:

result = executor.execute_code_blocks([
    ("python", "print(2**10)")
])
print(result.exit_code, result.output)

A clean run prints 0 1024. This confirms the AutoGen code execution backend is healthy.

Step 4: Attach AutoGen code execution to a UserProxyAgent

The UserProxyAgent is the component that actually invokes the executor. Pass the executor instance inside code_execution_config.

from autogen import UserProxyAgent

user_proxy = UserProxyAgent(
    name="user_proxy",
    human_input_mode="NEVER",  # fully autonomous for demo
    code_execution_config={
        "executor": executor,
        "silent": False,  # print code and output
    },
    max_consecutive_auto_reply=10,
)

Setting human_input_mode="NEVER" lets the agent run without prompting you. In a real product, you may want APPROVE to gate code runs. The code_execution_config dict also accepts a shorthand {"work_dir": "coding"} which builds a local executor implicitly, but passing an explicit executor gives you control over timeouts and Docker.

The AutoGen code execution loop works because the assistant emits a code block, the user proxy executes it, and the result is fed back as a message. Without the proxy configured for execution, the assistant’s code is just text.

Step 5: Define the AssistantAgent that writes code

The assistant generates the Python. Its system message should explicitly permit code use.

from autogen import AssistantAgent

assistant = AssistantAgent(
    name="assistant",
    llm_config=llm_config,
    system_message=(
        "You are a helpful AI assistant. "
        "Solve tasks by writing Python code when appropriate. "
        "Prefer using the code execution tool to compute answers."
    ),
)

If the model tends to answer from memory instead of running code, add a stricter line: “You MUST use code to verify any numeric answer.” The assistant does not execute anything itself; it only proposes.

Step 6: Run an end-to-end task

Initiate a chat with a concrete problem that requires computation.

task = "Compute the first 10 prime numbers and write them to primes.txt."

chat_result = user_proxy.initiate_chat(
    assistant,
    message=task,
    cache=None,
)

print("Chat completed:", chat_result.summary)

Expected behavior: the assistant writes a script, the proxy runs it, the script writes primes.txt in work_dir, and the assistant reports the list. The terminal shows the code block, the execution log, and the final summary.

Step 7: Verify the execution succeeded

Check three things:

  1. Exit code: The executor logs exitcode: 0. If you see non-zero, inspect the traceback in the proxy output.
  2. Artifact: The file autogen_workspace/primes.txt exists and contains 10 numbers.
  3. Agent response: chat_result.summary or the last assistant message includes the prime list.
import os

artifact = os.path.join(work_dir, "primes.txt")
assert os.path.exists(artifact), "primes.txt was not created"

with open(artifact) as f:
    lines = f.read().strip().splitlines()

assert len(lines) == 10, f"Expected 10 primes, got {len(lines)}"
print("Verification passed:", lines)

If the assertion fails, raise silent=False logging and check the raw code block the model produced. Often the fix is a tighter system prompt or a higher timeout. You can also inspect user_proxy.chat_messages to see the exact transcript.

Step 8: Harden the setup for real workloads

The default local executor trusts the model completely. For any external input, switch to Docker and add resource limits:

executor = DockerCommandLineCodeExecutor(
    image="python:3.11-slim",
    work_dir="/workspace",
    timeout=30,
    auto_remove=True,
    extra_hosts=None,
)

Also set max_consecutive_auto_reply low (e.g., 5) to avoid runaway loops. If you use a gateway that fronts multiple providers, you can enforce per-token metering and provider cache-control at the routing layer without touching agent code.

Debugging common failures

  • Module not found: The local executor uses system Python. Install needed packages in the same environment, or use a virtual_env_path.
  • Permission denied: Ensure work_dir is writable by the process running the executor.
  • Model ignores code: Add “You MUST use code to answer” to the system message and set temperature lower.
  • Timeout: Long-running scripts need a larger timeout value; default is 60 seconds.

AutoGen code execution is a pragmatic way to give agents grounded computation. Wire the executor once, keep the workspace isolated, and verify artifacts after each run. The pattern scales from a local notebook to a containerized service with minimal changes to the agent definitions.

Tagsautogentool-usecode-execution

Written by

n4n Team

The team building n4n — a single OpenAI-compatible API in front of 240+ models, with automatic fallback, load balancing and pay-per-token metering.

More from n4n Team →

All autogen & microsoft agent framework posts →