What sandbox code can and cannot do
Check here before you give an agent a task, so you know whether its script can do it. Agent Sandboxes run Pydantic Monty, a Python interpreter that supports the parts of Python agents use to call functions and work with data. It does not support everything that Python does.
Sandbox code is good at calling your functions, looping, branching, and filtering, grouping, and reshaping data. For work that needs third-party packages, files, or a shell, use a container-based sandbox, or run that work in a function that the sandbox calls.
Supported: functions (including async def, closures, and default arguments), await and asyncio.gather, list, dict,
and set comprehensions, f-strings, try/except, match, dataclasses, and type hints.
Not supported, among others:
- Classes that inherit from other classes,
@property,@classmethod, and@staticmethod - Generators (
yield) and user-defined exception classes async with,async for, anddel- Keyword arguments to
asyncio.gather, such asreturn_exceptions=True. The type check does not catch this.
See Monty’s limitations for the full list. A model usually rewrites a script that uses an unsupported feature after it sees the error.
Available: asyncio, base64, bisect, collections, copy, csv, dataclasses, datetime, decimal, fnmatch, functools,
hashlib, itertools, json, math, random, re, time, typing, and some others.
Not available, among others: enum, logging, statistics, uuid, io, sqlite3, subprocess,
socket, and urllib.
No third-party packages can be installed. To give a script something a package does, such as parsing a PDF, write a function in your application that uses the package, and pass that function to the sandbox.
Sandbox code cannot open network connections, read environment variables, or read arbitrary server files. It can call functions and modules supplied by your application, and access directories that you explicitly expose. Hosted volume mounts can also expose files stored by Logfire.
The hosted service limits processing time for each run, memory and function calls for the session, and how often your organization starts sessions. Variables retained from earlier runs still count toward the memory limit.
| Limit | Value | What happens when code goes over it |
|---|---|---|
| Processing time per run | 50 milliseconds | MontyRuntimeError: TimeoutError: feed time limit exceeded |
| Session memory | 20 MiB | MontyRuntimeError: MemoryError: memory limit exceeded, or MemoryError: the worker exceeded its memory limit and was terminated for one large allocation. The session is lost in the second case. |
| Calls to your functions per session | 1,000 | The run that makes the next call fails. Check out a new session, or return more data from each call. |
| Session starts per organization | 300 every 5 minutes | checkout() is refused until older starts leave the 5-minute window. |
Time that the script spends waiting for your functions does not count toward the processing time. The calls can take longer than 50 milliseconds in total. But the Python work before, between, and after them still counts toward the processing limit. Do heavy computation in your own functions, or in your database query.
In practice, a script can hold a few thousand rows of tool results at a time. A test with 5,000 rows of four short fields stayed inside the limit. 20,000 rows did not.
Saved sessions and snapshots are kept for 7 days. They count toward your project’s snapshot storage limit.
Open Snapshots to see the plan allowance, the enforced limit if it differs, and the snapshot count.
The byte and snapshot-count limits apply separately to each project.
Unless your organization has a different limit, each project can hold 2 GiB of snapshots and 128 snapshots.
Pending uploads and objects awaiting cleanup also count until cleanup finishes.
Use checkout(ephemeral=True) for sessions that nothing will load again. See Persist, resume, and fork sessions.
Hosted volumes keep files between sessions. They are separate from Python snapshots. Restoring a snapshot does not roll back volume files.
The hosted runtime records sandbox sessions, code runs, and related activity in your project.
logfire.agent_sandboxes() sends the current trace context so hosted spans join your application’s trace.
It does not enable the separate, process-wide instrument_monty() integration for local Monty pools.
Client scrubbing does not redact the code and values sent to the hosted runtime. Check the source, inputs, and exposed host functions before you run untrusted code with sensitive data.
Session storage is separate from telemetry. Use ephemeral sessions to avoid saved interpreter state. Ephemeral sessions do not turn off hosted telemetry. Do not send data that your application must keep entirely on its own machines.
Your Logfire plan limits how many projects in your organization can have Agent Sandboxes enabled at once:
| Plan | Projects with Agent Sandboxes enabled | Concurrent sessions |
|---|---|---|
| Personal | 1 | 4 |
| Other plans | 3 | No plan limit |
To free a slot, disable Agent Sandboxes in another project.
Agent Sandboxes is billed per invocation. One invocation is one call to feed_run() or feed_start(), however many
times the script calls your functions. Every Logfire plan includes free invocations each month.
For prices, paid tiers, and the limits of each tier, see Agent Sandboxes pricing.
These are not documented yet:
- Running sandboxes in a self-hosted Logfire deployment
- Connecting sandboxes to Model Context Protocol (MCP) servers
- Run code from Python: run your first script.
- Add a code tool to any agent: tell the model these limits in the tool description.