LlamaIndex code interpreter tool in a secure sandbox
Turn Runtime's sandbox functions into LlamaIndex FunctionTools, and the agent's code runs in a microVM instead of on your server.
On Runtime the agent's code leaves your machine. LlamaIndex's
CodeInterpreterToolSpec calls subprocess.run on the host that runs the
agent, and its own source warns that "arbitrary code execution is possible on
the machine running this tool". Runtime's four tools send each command to a
Firecracker microVM with its own kernel, Ubuntu 24.04 and Python 3.12, which
starts in 351 ms at the median (24 September 2026) and costs $0.03125 an hour
for 2 vCPU and 4 GiB while the agent waits on the LLM. llama-index-core 0.14.25
was the current PyPI release on 25 September 2026.
The code tools LlamaIndex offers
| Tool | Package | Where code runs |
|---|---|---|
CodeInterpreterToolSpec |
llama-index-tools-code-interpreter 0.6.0 |
A python -c subprocess on your host |
| Azure code interpreter tool spec | llama-index-tools-azure-code-interpreter |
Azure Container Apps dynamic sessions |
Runtime sandbox_tools |
withruntime |
A Runtime microVM with a shell and files |
The first is a single function, code_interpreter(code), that runs Python with
"access to any libraries the user has installed", in its docstring's words.
Its class docstring says it "is not recommended to be used in a production
setting, and would require heavy sandboxing or virtual machines". The Runtime
tools are that virtual machine.
Swap the tool
Terminalpip install llama-index-core withruntimeThe agent from the framework guide:
Pythonfrom llama_index.core.agent.workflow import FunctionAgentfrom llama_index.core.tools import FunctionToolfrom withruntime import Sandboxfrom withruntime.tools import sandbox_toolsdef coder(llm, sbx: Sandbox) -> FunctionAgent: return FunctionAgent(tools=[FunctionTool.from_defaults(fn=f) for f in sandbox_tools(sbx)], llm=llm)FunctionTool.from_defaults reads each function's name, type hints and
docstring, so the LLM sees runtime_exec(command, cwd, timeout_seconds) with
its description. Any function-calling LLM class works, such as
llama_index.llms.openai.OpenAI.
Run the agent and watch its tool calls
LlamaIndex agents are workflows: agent.run(...) returns a handler that
streams events and can then be awaited for the answer.
Pythonfrom llama_index.core.agent.workflow import ToolCallResultfrom withruntime import Sandboxasync def answer(llm, question: str) -> str: with Sandbox.create( network={"internet": True, "allow": ["pypi.org", "*.pythonhosted.org"]}, timeout_seconds=900, on_lease_end="stop", ) as sbx: handler = coder(llm, sbx).run(user_msg=question) async for event in handler.stream_events(): if isinstance(event, ToolCallResult): print(event.tool_name, event.tool_kwargs) return str(await handler)coder is the function above. Printing each ToolCallResult gives you an
audit trail of every command the model ran in the sandbox. This loop was run on
25 September 2026 with llama-index-core 0.14.25 against a scripted OpenAI-style
endpoint, with streaming=False: the call to runtime_exec reached the sandbox and its output reached
the answer.
Retrieval plus computation
A common LlamaIndex agent answers from documents and then needs arithmetic the LLM should not do in its head. Give it a query engine tool and the sandbox tools together, and write the source data into the sandbox so the numbers come from a file, not from the prompt:
Pythonfrom llama_index.core.agent.workflow import FunctionAgentfrom llama_index.core.tools import FunctionTool, QueryEngineToolfrom withruntime import Sandboxfrom withruntime.tools import sandbox_toolsdef analyst(llm, query_engine, sbx: Sandbox, csv_text: str) -> FunctionAgent: sbx.files.write("/workspace/sales.csv", csv_text) docs = QueryEngineTool.from_defaults( query_engine, name="handbook", description="The company's sales handbook." ) code = [FunctionTool.from_defaults(fn=f) for f in sandbox_tools(sbx)] return FunctionAgent( tools=[docs, *code], llm=llm, system_prompt="Definitions come from the handbook. Compute figures with Python on sales.csv.", )Files the agent writes stay in /workspace for the life of the sandbox, so a
result saved in one step can be read back in the next, and your code can copy
any file out with sbx.files.read.
Guard rails
The sandbox limits what code can do; the key limits what the application can spend.
| Concern | Setting |
|---|---|
| Code reaching your network or the internet | network={"internet": False}, or an allow-list of hosts |
| A sandbox left running | timeout_seconds with on_lease_end="stop" |
| One expensive create | max_cost_micros refuses a first lease above your figure |
| A runaway loop of creates | A daily spending limit on the key; past it, spending_limit_reached |
| A token the code must use | A Runtime secret: the sandbox sees a placeholder, never the value |
| A monitoring dashboard | A read-only key that cannot create, run or spend |
Details are in security and egress control.
Which one to pick
CodeInterpreterToolSpec is fine for a notebook on your own laptop with code
you would run anyway. The Azure tool spec suits teams already on Azure that want
Python cells. Runtime suits a hosted agent that takes questions from users,
since a prompt injection then reaches a throwaway machine rather than your
server, and the agent gets a shell, pip and files instead of one Python call.
More: a data analysis agent, a code interpreter for chatbots and run untrusted LLM code. New accounts get 50 free sandbox hours, no card:
Terminalnpx withruntime sandbox run --trial -- python3 -c 'print(6 * 7)'Sources
- LlamaIndex: Tools,
FunctionTool.from_defaultsandagent.run(user_msg=...), read 25 September 2026 - llama-index-core on PyPI, version 0.14.25, read 25 September 2026
- llama-index-tools-code-interpreter on PyPI, version 0.6.0; the warnings quoted are from its source, read 25 September 2026
- llama-index-tools-azure-code-interpreter on PyPI, read 25 September 2026
Facts on this page were checked on 25 September 2026.