Building agents that turn natural language into runnable Python requires a loop of generation, execution, and feedback. This autogen code execution tutorial python shows how to wire Microsoft AutoGen’s AssistantAgent and UserProxyAgent to execute generated code locally and capture results, starting from a bare environment.
Prerequisites
- Python 3.10 or newer
pipaccess to install packages- An OpenAI-compatible API key (OpenAI, Azure, or a gateway like n4n.ai)
- Basic familiarity with Python and async concepts
Install the framework and plotting dependencies:
pip install pyautogen matplotlib numpy
Set your API key in the environment:
export OPENAI_API_KEY="sk-..."
If you prefer a gateway that fronts multiple providers, export that key instead and note the base URL for later.
Project layout
Create a working directory. AutoGen will write generated scripts into a subfolder you control:
mkdir -p autogen_demo/coding
cd autogen_demo
Configuring the agents
AutoGen separates concerns: the AssistantAgent drafts code and reasoning, while the UserProxyAgent executes code and returns stdout/stderr. The following snippet defines both with local execution enabled.
import os
from autogen import AssistantAgent, UserProxyAgent
llm_config = {
"model": "gpt-4o",
"api_key": os.environ["OPENAI_API_KEY"],
"temperature": 0.2,
}
assistant = AssistantAgent(
name="assistant",
llm_config=llm_config,
system_message=(
"You are a senior Python engineer. "
"Solve tasks by writing small, correct scripts. "
"Prefer numpy and matplotlib. Explain briefly."
),
)
user_proxy = UserProxyAgent(
name="user_proxy",
code_execution_config={
"work_dir": "coding",
"use_docker": False,
},
human_input_mode="NEVER",
)
use_docker=False runs code in the local Python process. Never use this on untrusted prompts; we cover isolation later.
Running your first prompt-to-Python task
Initiate a chat with a concrete instruction. The user proxy forwards the message to the assistant, which returns a code block. The proxy writes the block to coding/xxx.py and runs it.
chat_result = user_proxy.initiate_chat(
assistant,
message=(
"Plot sin(x) for x in [0, 2*pi] with 100 points. "
"Save the figure to coding/sine.png and print the max value."
),
)
Expected console output includes the generated code and an execution trace:
user_proxy (to assistant):
Plot sin(x) for x in [0, 2*pi] with 100 points. Save the figure to coding/sine.png and print the max value.
--------------------------------------------------------------------------------
assistant (to user_proxy):
```python
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0, 2*np.pi, 100)
y = np.sin(x)
plt.plot(x, y)
plt.savefig("coding/sine.png")
print("max:", y.max())
user_proxy (to assistant):
***** Suggested code ***** … ***** Code executed ***** max: 1.0
The file `coding/sine.png` now exists. The assistant received the stdout (`max: 1.0`) and can continue if asked.
## Inspecting the execution directory
AutoGen stores each script with a timestamp hash. List them:
```bash
ls coding/
# 20240101-120000_abc123.py sine.png
You can open sine.png to verify the plot. This artifact persistence is what makes the autogen code execution tutorial python approach usable for real data tasks—intermediate files survive across turns.
Multi-step iteration and error recovery
A core strength is the retry loop. Break the task intentionally to see recovery:
user_proxy.initiate_chat(
assistant,
message="Load coding/nonexistent.csv and print its shape.",
)
The assistant will propose code using pandas.read_csv. Execution fails:
FileNotFoundError: [Errno 2] No such file or directory: 'coding/nonexistent.csv'
Because human_input_mode="NEVER", the proxy feeds the error back to the assistant automatically. The assistant then either creates the file or apologizes with corrected code. This closed loop is the heart of the autogen code execution tutorial python pattern.
Streaming token usage and cost control
AutoGen returns a ChatResult with token counts per agent. Print them:
print(chat_result.cost)
# {'assistant': {'total_tokens': 542}, 'user_proxy': {'total_tokens': 0}}
If you route through a gateway, per-token metering appears on your invoice without extra code. For example, pointing the base_url at n4n.ai’s OpenAI-compatible endpoint gives automatic fallback when a provider is rate-limited and forwards cache-control hints, while AutoGen’s cost field still populates normally.
llm_config = {
"model": "openai/gpt-4o",
"base_url": "https://api.n4n.ai/v1",
"api_key": os.environ["N4N_API_KEY"],
"temperature": 0.2,
}
Swap that dict into the assistant and the rest of the tutorial runs unchanged.
Custom system prompts for domain tasks
For repetitive engineering work, encode policy in the system message. Example: force type hints and no top-level side effects.
assistant = AssistantAgent(
name="assistant",
llm_config=llm_config,
system_message=(
"You write Python functions with type hints. "
"Never run code at import time. "
"Return a function and a __main__ guard that demonstrates it."
),
)
Now ask:
user_proxy.initiate_chat(
assistant,
message="Write a function to compute moving average of a list with window size k.",
)
Generated code follows the constraint, making it importable in your own tests.
Security boundaries
Local execution is convenient but dangerous. Follow these rules:
- Run inside a container or dedicated VM when the prompt source is untrusted.
- Set
use_docker=True(requires Docker daemon) to sandbox filesystem and network. - Use
code_execution_config={"use_docker": {"image": "python:3.11-slim"}}to pin the runtime. - Filter allowed imports via a custom
execwrapper if needed.
Example with Docker:
user_proxy = UserProxyAgent(
name="user_proxy",
code_execution_config={
"work_dir": "coding",
"use_docker": True,
},
human_input_mode="NEVER",
)
AutoGen will mount work_dir and execute in the container, isolating host resources.
Wiring a fallback chain
AutoGen accepts a config_list for model fallback. If the primary model 429s, it tries the next.
config_list = [
{"model": "gpt-4o", "api_key": os.environ["OPENAI_API_KEY"]},
{"model": "gpt-3.5-turbo", "api_key": os.environ["OPENAI_API_KEY"]},
]
llm_config = {
"config_list": config_list,
"temperature": 0.2,
}
This pattern complements a gateway that already performs provider failover; choose one layer to avoid double fallback confusion.
End-to-end script
Combine the pieces into a single file run.py:
import os
from autogen import AssistantAgent, UserProxyAgent
llm_config = {
"model": "gpt-4o",
"api_key": os.environ["OPENAI_API_KEY"],
"temperature": 0.2,
}
assistant = AssistantAgent(
name="assistant",
llm_config=llm_config,
system_message="You are a Python expert. Write concise, correct code.",
)
user_proxy = UserProxyAgent(
name="user_proxy",
code_execution_config={"work_dir": "coding", "use_docker": False},
human_input_mode="NEVER",
)
user_proxy.initiate_chat(
assistant,
message="Compute the first 10 Fibonacci numbers and save them to coding/fib.json.",
)
import json
with open("coding/fib.json") as f:
print("Saved:", json.load(f))
Run it:
python run.py
Expected final line:
Saved: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
Where to go next
The autogen code execution tutorial python flow above is the minimal viable loop. From here, add retrieval-augmented context, restrict the agent to a fixed function registry, or push execution to a Kubernetes job for heavy workloads. The agent-to-executor boundary stays the same: generate, run, observe, repeat.