Nearly Python: Sandbox Restrictions
agex agents generate and execute code in a secure sandbox powered by sandtrap. The sandbox uses AST rewriting to compile agent code into restricted bytecode. By default this runs in-process, but can be configured for subprocess or kernel-level isolation (see Sandbox Isolation). The result looks and feels like Python — but with some important differences.
Imports: Registered or VFS-Resident
Agent-generated code may use import statements. These only succeed for:
1. Registered Modules: Libraries explicitly exposed via agent.module(...).
2. Workspace Modules: Python files the agent has created in the Virtual Filesystem (VFS).
Within registered modules, only whitelisted members are visible. For workspace modules, all members are available.
What Works
Most Python features work exactly as you'd expect:
- Basic operations: arithmetic, string manipulation, list/dict operations
- Control flow:
if/else,for/whileloops,match/case(Python 3.10+), function calls - Built-in functions:
print(),len(),range(),enumerate(),sorted(), etc. - Classes: full
classdefinitions with inheritance, methods, and dunders - Generators:
yieldandyield from - Closures: nested functions with
nonlocalandglobal - Exception handling:
try/except/finally/elsewith 50+ built-in exception types - Decorators: function and class decorators
- Comprehensions: list, dict, set, and generator comprehensions
What's Different
Three-Argument type()
Blocked: Dynamic class creation via type('Name', bases, dict) is rejected. Single-argument type(obj) works normally for inspection.
# ✅ Allowed: type inspection
t = type(42) # <class 'int'>
isinstance(42, t) # True
# ❌ Blocked: dynamic class creation
MyClass = type('MyClass', (object,), {'x': 1}) # TypeError
Format String Traversal
Blocked: .format() and .format_map() reject attribute and item traversal in field names. F-strings are unaffected (they go through proper AST validation).
# ✅ Allowed: simple positional/keyword formatting
"Hello {name}".format(name="World")
# ❌ Blocked: attribute traversal via format string
"{obj.__class__}".format(obj=x) # AttributeError
# ✅ Secure alternative: use f-strings
f"{obj.attr}"
Bare except: Clause
Rewritten: A bare except: is automatically rewritten to except Exception:. This prevents agent code from swallowing control exceptions (KeyboardInterrupt, sandbox timeout/cancellation signals, etc.).
Unavailable Names
The following names raise NameError:
- Control exceptions:
BaseException,KeyboardInterrupt,GeneratorExit,SystemExit - Dangerous builtins:
exec,eval,compile - Introspection:
globals()
locals() is available but returns a filtered copy (sandbox internals excluded). Python's built-in dir() and help() are available.
Wildcard Imports
Rejected: from module import * is blocked at parse time. Agents must import specific names.
Private Attribute Access
Blocked by default: Attributes starting with _ are not accessible on registered objects unless explicitly included in the registration's include pattern.
# ❌ Blocked by default
obj._internal_method()
obj.__dict__
# ✅ If explicitly included in registration
agent.cls(MyClass, include=["_special_method"])
Async Bridging
Agent-generated code always runs synchronously — no async/await syntax. However, async functions registered via @agent.fn are bridged transparently: agents call them like sync functions and the framework awaits the result automatically. See Task - Async Execution for details.
Versioned State Serialization
When using versioned state, agent variables are serialized between task executions. This has some implications for object identity, closures, and unpicklable objects. See State - Serialization Behavior for details.
Resource Limits
agex can enforce memory, file descriptor, and VFS size limits via sandtrap. See Agent - Resource Limits for configuration.
Sandbox Isolation
By default, agent code runs in-process. For crash protection or kernel-level security, set the isolation parameter. See Security - Sandbox Isolation and Agent - Sandbox Isolation.