Open-source runtime for general-purpose AI agents in isolated sandboxes.
Project description
Sandstorm
Open-source runtime for general-purpose AI agents in isolated sandboxes.
CLI, API, Python client, and Slack with streaming, file uploads, and config-driven behavior.
Built on the Claude Agent SDK and E2B.
Sandstorm is for people who want real agent work, not a chat wrapper:
- Research Acme's competitors, crawl their sites and recent news, and write a one-page branded briefing PDF with sources
- Analyze uploaded transcripts or PDFs
- Triage incoming support tickets
- Run a security audit in a fresh sandbox
- Turn docs into a draft API spec
Terminal demo
$ pip install duvo-sandstorm
$ ds init research-brief
$ cd research-brief
$ ds "Research Acme's competitors, crawl their sites and recent news, and write a one-page branded briefing PDF with sources."
WEBFETCH competitor sites, product pages, and recent coverage
STREAM compared launches, pricing, positioning, and buyer signals
WRITE briefing.pdf
WRITE reports/sources.md
artifacts:
- briefing.pdf
- reports/sources.md
The point is not that an agent can answer a question. It starts from a runnable starter, gets a
fresh sandbox, can read uploads or crawl the web, writes artifacts like briefing.pdf, streams
its work, and tears itself down when the run is done.
60-second path
pip install duvo-sandstorm
ds init
cd general-assistant
ds add linear
ds "Compare Notion, Coda, and Slite for async product teams"
ds init scaffolds a runnable starter with sandstorm.json, a starter README, .env.example,
and any starter-specific assets. If provider settings are missing, the guided flow asks once and
writes .env for you.
Direct forms:
ds init --list
ds init research-brief
ds init security-audit my-audit
Install extras
Install the base package for the CLI and server:
pip install duvo-sandstorm
Add extras only when you need them:
pip install "duvo-sandstorm[client]" # Async Python client
pip install "duvo-sandstorm[slack]" # Slack bot support
pip install "duvo-sandstorm[telemetry]" # OpenTelemetry integration
Pick a starter
| Starter | Use it when you want to | Typical output | Aliases |
|---|---|---|---|
general-assistant |
Start with one flexible agent for mixed workflows | concise answer, plan, or artifact | - |
research-brief |
Research a topic, compare options, and support a decision | brief with findings, recommendations, and sources | competitive-analysis |
document-analyst |
Review transcripts, reports, PDFs, or decks | summary, risks, action items, open questions | - |
support-triage |
Triage support tickets or issue exports | prioritized queue with owners and next steps | issue-triage |
api-extractor |
Crawl docs and draft an API summary plus spec | endpoint summary and draft openapi.yaml |
docs-to-openapi |
security-audit |
Run a structured security review | vulnerability report with remediation steps | - |
Need CRM access, ticket systems, or internal APIs? Add custom tools to the sandbox.
Add toolpacks
Use ds add to install bundled MCP integrations into the current project:
ds add --list # Show all available toolpacks
ds add linear # Issue tracking via Linear
ds add notion # Knowledge base via Notion
ds add firecrawl # Web scraping via Firecrawl
ds add exa # AI-powered search via Exa
ds add github # GitHub repos, issues, and PRs
Each command updates sandstorm.json, writes the required API key to .env and .env.example,
and future CLI/API/Slack runs from that project expose the MCP server in the sandboxed agent
runtime.
If the project already has a different entry for that MCP server, ds add stops instead
of overwriting it. Re-run with --force to replace the existing config.
Why Sandstorm exists
Most agent projects break down in one of two ways:
- You wire the SDK yourself and end up rebuilding sandbox lifecycle, file uploads, streaming, config loading, and starter setup.
- You use an agent framework that is good at orchestration but weak at actually shipping a runnable agent product path.
Sandstorm is opinionated about the missing middle:
- starter to runnable project in one command
- fresh sandbox per request with teardown by default
- CLI, API, and Slack over the same runtime
- config-driven behavior through
sandstorm.json - built-in document tooling for PDF, DOCX, and PPTX workflows
Why not wire the SDK yourself?
| Capability | Sandstorm | Raw SDK + E2B | DIY runner |
|---|---|---|---|
| Fresh sandbox per request | Built in | Manual wiring | Manual wiring |
| Streaming API endpoint | Built in | Manual wiring | Custom work |
| File uploads | Built in | Manual wiring | Custom work |
sandstorm.json config layer |
Built in | No | Custom work |
| Slack bot integration | Built in | No | Custom work |
Starter scaffolding with ds init |
Built in | No | Custom work |
Docs
- Getting started
- Python client
- Configuration
- API reference
- Slack bot
- Deployment
- OpenRouter
- Advanced examples
Community
If Sandstorm saves you runner plumbing, please star the repo.
If you want a new starter, a provider integration, or a sharper deploy story, open an issue or start a discussion.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file duvo_sandstorm-0.8.1.tar.gz.
File metadata
- Download URL: duvo_sandstorm-0.8.1.tar.gz
- Upload date:
- Size: 470.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e8a75987092c22f7ad88a3e2735635e86eea2dab86415dbff4ffa72b0e2adbda
|
|
| MD5 |
91e7c8e72339fd0f887ae60b032f4aac
|
|
| BLAKE2b-256 |
ca546561099038dab8738de800714f95ff093ef9167c7fbf39dda038aef14764
|
Provenance
The following attestation bundles were made for duvo_sandstorm-0.8.1.tar.gz:
Publisher:
publish.yml on tomascupr/sandstorm
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
duvo_sandstorm-0.8.1.tar.gz -
Subject digest:
e8a75987092c22f7ad88a3e2735635e86eea2dab86415dbff4ffa72b0e2adbda - Sigstore transparency entry: 1088072696
- Sigstore integration time:
-
Permalink:
tomascupr/sandstorm@795a53b31b46b2fa6eba4ebcc1781be5cc501f5d -
Branch / Tag:
refs/tags/v0.8.1 - Owner: https://github.com/tomascupr
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@795a53b31b46b2fa6eba4ebcc1781be5cc501f5d -
Trigger Event:
release
-
Statement type:
File details
Details for the file duvo_sandstorm-0.8.1-py3-none-any.whl.
File metadata
- Download URL: duvo_sandstorm-0.8.1-py3-none-any.whl
- Upload date:
- Size: 102.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3dd9dd182e51af6ef9b918eb0bbe659739a1a17fcf3aec4b11cebf89d16a3586
|
|
| MD5 |
1d1eb58030981f8dabea26e7d5d69625
|
|
| BLAKE2b-256 |
c4430d84b2c484164578fdfc69819685957cf3dbc84df354c8d9a2806d0c78db
|
Provenance
The following attestation bundles were made for duvo_sandstorm-0.8.1-py3-none-any.whl:
Publisher:
publish.yml on tomascupr/sandstorm
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
duvo_sandstorm-0.8.1-py3-none-any.whl -
Subject digest:
3dd9dd182e51af6ef9b918eb0bbe659739a1a17fcf3aec4b11cebf89d16a3586 - Sigstore transparency entry: 1088072726
- Sigstore integration time:
-
Permalink:
tomascupr/sandstorm@795a53b31b46b2fa6eba4ebcc1781be5cc501f5d -
Branch / Tag:
refs/tags/v0.8.1 - Owner: https://github.com/tomascupr
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@795a53b31b46b2fa6eba4ebcc1781be5cc501f5d -
Trigger Event:
release
-
Statement type: