How to Build a Data Analysis Agent with E2B and an LLM

October 6, 2026

A code-execution agent is only as good as the loop around it. E2B gives that loop a safe place to run, and the interesting part is feeding errors back to the model so it can self-correct. Here’s a compact data-analysis agent you can adapt.

Direct answer: Build the loop by letting the LLM write Python, running it in an E2B sandbox, appending stdout or tracebacks to the conversation, and repeating until the model stops emitting code — usually 2–4 turns for a CSV question.

What does the loop actually do?

  1. Upload the CSV into the sandbox once: sbx.files.write("/data/sales.csv", open("sales.csv","rb").read()).
  2. Ask the LLM to write code that answers the question and print results.
  3. Execute with sbx.run_code(code).
  4. Append the stdout and any error to the message history.
  5. Loop while the model keeps emitting code blocks.

How do I feed errors back so it self-corrects?

The trick is to send the real traceback, not a cleaned-up message. Models fix KeyError: 'revenue' far faster than “the code failed.” Include the last 20 lines of stderr and the offending line. Cap retries at three — past that the model usually thrashes.

for turn in range(3):
    code = extract_code(llm(messages))
    result = sbx.run_code(code)
    messages.append({"role":"user","content":
        result.logs.stdout + result.error.traceback if result.error else result.logs.stdout})
    if not result.error and "final" in result.logs.stdout: break

How do I get charts out of the sandbox?

Have the code save a PNG to disk, then pull the bytes: png = sbx.files.read("/chart.png"). Return it as base64 to your front end. Matplotlib works out of the box; for interactive charts, install plotly and write an HTML file instead.

How do I keep runs cheap and fast?

Reuse one sandbox across an entire conversation rather than creating one per turn — that keeps the loaded dataframe in memory and avoids re-uploading the CSV. Set an explicit timeout with Sandbox.create(timeout=600) so a stuck cell doesn’t burn compute. The bigger cost is LLM tokens from verbose outputs, so truncate dataframe prints to the first 50 rows.

What breaks in practice?

Two things bite most people. First, the model assumes libraries that aren’t installed — pin a base template with pandas, numpy, and matplotlib preinstalled to save a round trip. Second, non-deterministic outputs make debugging painful; log every code block and its result so you can replay a failed run.

Is this production-ready?

For internal tools and demos, yes. For customer-facing apps, add a per-user spend cap and a sandbox lifecycle policy — an agent stuck in a loop can quietly rack up sandbox-seconds. E2B’s metering is fine-grained, but your cost controls are your job.

Key Takeaways

  • Reuse one sandbox per conversation to keep data in memory.
  • Feed full tracebacks back to the LLM; cap self-correction at 3 turns.
  • Preinstall pandas, numpy, matplotlib in a base template to avoid install round-trips.
  • Pull chart images with sbx.files.read and return them as base64.
  • Add spend caps before shipping to customers — loops burn compute fast.
Tags: