> ## Documentation Index
> Fetch the complete documentation index at: https://docs.declaw.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# code-interpreter — executing LLM-generated Python

> The code-interpreter template is a pre-provisioned Python runtime for arbitrary code an LLM decides to run — imports already installed, stdout/stderr captured, zero cold-install delay.

The `code-interpreter` template is the standard execution target when
your agent produces Python snippets and wants them run in isolation.
It ships the libraries LLMs commonly `import` — `numpy`, `pandas`,
`matplotlib`, `plotly`, `scipy`, `scikit-learn`, `Pillow`, `SymPy`, plus
`jupyter` and `ipython` — so a freshly-generated snippet doesn't stall
on `pip install` every time.

Think of it as the declaw-native backing for OpenAI's *code interpreter*
tool, Anthropic's *code execution* tool, and similar agent primitives:
**feed it a string of Python, get back stdout / stderr / exit code.**

## What you'll learn

* Picking `template="code-interpreter"` so the common scientific imports work cold
* Running several unrelated code snippets in the same sandbox, safely
* Letting the agent generate code and only having the SDK execute it

## Prerequisites

<Snippet file="snippets/env-setup.mdx" />

## Code

In the example below we skip calling a real LLM and just iterate over
three hand-written snippets — each one stands in for whatever your
agent decides to execute next.

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    import textwrap

    from declaw import Sandbox


    # Three snippets the "agent" wants to run. In a real pipeline these
    # come from the model's tool-use response; we hard-code them here so
    # the example has no LLM dependency.
    SNIPPETS = [
        # 1. Numeric: SymPy solves a small system.
        textwrap.dedent("""
            from sympy import symbols, solve
            x, y = symbols('x y')
            eqs = [x + 2*y - 5, 3*x - y - 4]
            print("solution:", solve(eqs, [x, y]))
        """),

        # 2. Data shaping: pandas rollup from an in-memory CSV string.
        textwrap.dedent("""
            import io, pandas as pd
            csv = "region,sales\\nNA,120\\nEU,80\\nAPAC,150\\nNA,60"
            df = pd.read_csv(io.StringIO(csv))
            print(df.groupby('region')['sales'].sum().to_dict())
        """),

        # 3. Rendering: matplotlib — renders to a file, no display needed.
        textwrap.dedent("""
            import matplotlib
            matplotlib.use("Agg")
            import matplotlib.pyplot as plt
            plt.figure()
            plt.plot([0, 1, 2, 3], [1, 4, 2, 8], marker='o')
            plt.title("agent-generated chart")
            plt.savefig("/tmp/chart.png", dpi=120)
            print("wrote /tmp/chart.png")
        """),
    ]


    def run_snippet(sbx: Sandbox, idx: int, code: str) -> None:
        # Every snippet is written to its own file so tracebacks point
        # at a real path, then executed with python3.
        path = f"/tmp/snip_{idx}.py"
        sbx.files.write(path, code)
        r = sbx.commands.run(f"python3 {path}", timeout=30)
        print(f"--- snippet {idx} (exit={r.exit_code}) ---")
        if r.stdout:
            print(r.stdout.rstrip())
        if r.stderr and r.exit_code != 0:
            print("stderr:", r.stderr.rstrip())


    def main() -> None:
        sbx = Sandbox.create(template="code-interpreter", timeout=180)
        try:
            for i, code in enumerate(SNIPPETS, start=1):
                run_snippet(sbx, i, code)

            # Artefacts produced by one snippet survive for the next —
            # the sandbox is persistent until you kill it.
            info = sbx.files.get_info("/tmp/chart.png")
            print(f"\nchart.png exists: {info.size} bytes")
        finally:
            sbx.kill()


    if __name__ == "__main__":
        main()
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    import "dotenv/config";
    import { Sandbox } from "@declaw/sdk";

    const SNIPPETS = [
      `from sympy import symbols, solve
    x, y = symbols('x y')
    eqs = [x + 2*y - 5, 3*x - y - 4]
    print("solution:", solve(eqs, [x, y]))
    `,
      `import io, pandas as pd
    csv = "region,sales\\nNA,120\\nEU,80\\nAPAC,150\\nNA,60"
    df = pd.read_csv(io.StringIO(csv))
    print(df.groupby('region')['sales'].sum().to_dict())
    `,
      `import matplotlib
    matplotlib.use("Agg")
    import matplotlib.pyplot as plt
    plt.figure()
    plt.plot([0, 1, 2, 3], [1, 4, 2, 8], marker='o')
    plt.title("agent-generated chart")
    plt.savefig("/tmp/chart.png", dpi=120)
    print("wrote /tmp/chart.png")
    `,
    ];

    async function runSnippet(sbx: Sandbox, idx: number, code: string) {
      const path = `/tmp/snip_${idx}.py`;
      await sbx.files.write(path, code);
      const r = await sbx.commands.run(`python3 ${path}`, { timeout: 30 });
      console.log(`--- snippet ${idx} (exit=${r.exitCode}) ---`);
      if (r.stdout) console.log(r.stdout.trimEnd());
      if (r.stderr && r.exitCode !== 0) console.log("stderr:", r.stderr.trimEnd());
    }

    async function main(): Promise<void> {
      const sbx = await Sandbox.create({ template: "code-interpreter", timeout: 180 });
      try {
        for (let i = 0; i < SNIPPETS.length; i++) {
          await runSnippet(sbx, i + 1, SNIPPETS[i]);
        }
        const info = await sbx.files.getInfo("/tmp/chart.png");
        console.log(`\nchart.png exists: ${info.size} bytes`);
      } finally {
        await sbx.kill();
      }
    }

    main().catch(console.error);
    ```
  </Tab>
</Tabs>

## Expected output

```
--- snippet 1 (exit=0) ---
solution: {x: 13/7, y: 11/7}
--- snippet 2 (exit=0) ---
{'APAC': 150, 'EU': 80, 'NA': 180}
--- snippet 3 (exit=0) ---
wrote /tmp/chart.png

chart.png exists: 31824 bytes
```

<Note>
  A real agent loop typically does three things per tool call: generate
  the snippet with the model, pass it here for execution, then feed the
  stdout / exit code back to the model. Keep the same sandbox alive
  across turns so files and installed packages persist — kill it only
  when the task finishes.
</Note>
