This is Part 2 of Closing the execution gap β a series on building jhansi.io, a cloud sandbox for AI-generated code.
The first question I got after shipping persistent sandboxes was predictable:
"Great β but do I still have to pip install everything myself?"
Yes. You did. That was embarrassing.
If the pitch is "run AI-generated code with zero friction," making users manage deps manually is a contradiction. For regulated teams it's worse: every new package is a supply-chain review. Friction kills adoption.
So v0.3 fixes it.
Every sandbox starts as a clean container. Upload main.py
, hit run, and you get:
ModuleNotFoundError: No module named 'requests'
The naive fix is to install at exec time. But down from PyPI on every run is slow, expensive, and brittle. pandas
numpy
is a 40s cold start. Run that 100 times and your AI agent burns budget before it does anything useful.
The right fix: install once, persist forever.
jhansi.io gives every sandbox a persistent workspace β a folder that survives across runs. In v0.3, dependencies live there too.
/sandbox/deps
, run your code.$ curl -X POST .../sandboxes/sb_abc123/exec -d '{"filename": "main.py"}'
{
"output": "Installing requests==2.31.0...\n200\n"
}
$ curl -X POST .../sandboxes/sb_abc123/exec -d '{"filename": "main.py"}'
{
"output": "200\n"
}
That's the difference between "AI is too slow" and "AI is faster than a junior dev."
How do we know what to install? Both approaches, in the right order.
If you provide a manifest, we trust you. You know your deps better than any static analyser. If you don't, we fall back to auto-detection.
Priority for Python:
pyproject.toml
β pip install
requirements.txt
β pip install -r
pipreqs
scan
pipreqs
isn't just import requests
β requests
. It knows import cv2
means opencv-python
, import sklearn
means scikit-learn
. You don't have to remember.Using a manifest isn't just faster β it's auditable. Auditors can diff your pinned deps between runs. Auto-detect is for prototyping. More on auditability in Part 5.
AI doesn't just write Python. jhansi.io handles the four languages LLMs generate most:
| Language | Manifest detected | Install command | No manifest fallback |
|---|---|---|---|
| Python | |||
pyproject.toml , requirements.txt |
|||
pip install --target /sandbox/deps |
|||
pipreqs auto-detect |
|||
| Node | package.json |
||
npm install |
|||
| Run as-is | |||
| Go | go.mod |
||
go mod download |
|||
go mod init + go mod tidy |
|||
| Java | |||
pom.xml , build.gradle |
|||
| Maven or Gradle | Direct javac compile |
Each language keeps its own idioms. We don't impose a universal abstraction. Workspace-scoping means one sandbox's torch==2.1.0
can't poison another's torch==1.13
. No dependency hell across AI runs.
One decision worth documenting: we don't vet what gets installed.
Egress is restricted to official registries β PyPI, npm, Maven Central, proxy.golang.org
β and nothing else. No arbitrary domains. What you install from those registries is your responsibility.
The contract is simple:
jhansi.io guarantees isolation. You own your code.
This is the same model as AWS Lambda or Cloud Run. We contain the blast radius. We don't audit your imports.
SBOM per exec β a full list of every package installed, with versions and licenses β is on the roadmap. Today we contain. Tomorrow we curate.
Two things didn't make v0.3:
torch
is taking forever.ImportError
today. We should surface the unlisted import in the response. Coming soon.
Next in the series: pip install
safely now. But can you stop that package from exfiltrating your AWS credentials? What "hard-sandboxed" actually means, why Docker isn't enough, and the attacks most sandboxes miss.jhansi.io is open source (Apache 2.0) at github.com/jhansi-io. Follow the series on Dev.to, LinkedIn, and X.