feat(tools): add BoxLite sandbox tools#6461
Conversation
Add BoxLiteExecTool, BoxLitePythonTool, and BoxLiteFileTool, mirroring the existing E2B and Daytona sandbox tools. BoxLite runs an OCI image inside a hardware-isolated micro-VM on the local host, so it needs no API key or cloud account -- a self-hosted option for agent-driven code execution. Registers the tools in crewai_tools, adds the `boxlite` optional dependency, and regenerates tool.specs.json. Claude-Session: https://claude.ai/code/session_01CifaVdyjdFaCpCqbtDduyY
📝 WalkthroughWalkthroughThis PR adds BoxLite sandbox tools to crewai-tools: BoxLiteExecTool, BoxLiteFileTool, and BoxLitePythonTool, backed by a shared BoxLiteBaseTool that manages micro-VM lifecycle (ephemeral or persistent). Includes new optional dependency, package exports, tool specs, and README documentation. ChangesBoxLite Sandbox Tool Integration
Sequence Diagram(s)sequenceDiagram
participant ComponentA
participant ComponentB
ComponentA->>ComponentB: observable interaction
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
lib/crewai-tools/src/crewai_tools/tools/boxlite_sandbox_tool/boxlite_file_tool.py (1)
117-122: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winFile operations can hang:
_shnever forwards a timeout.
BoxLiteExecToolandBoxLitePythonToolboth accept atimeout, but every file operation routes through_sh, which callsbox.execwithout one. A slow/stuck command (e.g.caton a huge file,findon a deep tree) can block the agent indefinitely with no way to bound it. Consider threading an optionaltimeoutthrough_shand the schema, mirroring the other two tools.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@lib/crewai-tools/src/crewai_tools/tools/boxlite_sandbox_tool/boxlite_file_tool.py` around lines 117 - 122, The file-operation path can hang because `_sh` does not pass any timeout through to `box.exec`, even though `BoxLiteExecTool` and `BoxLitePythonTool` already support one. Update `_sh` in `BoxLiteFileTool` to accept an optional timeout and forward it into `box.exec`, then thread that timeout through the relevant schema/argument plumbing so file commands are bounded consistently with the other BoxLite tools.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@lib/crewai-tools/src/crewai_tools/tools/boxlite_sandbox_tool/boxlite_file_tool.py`:
- Around line 165-168: The _list method in BoxliteFileTool uses a find
invocation with a leading -- that breaks on BusyBox-based OCI images, so update
the command construction in _list to use a portable form or a safe path-prefix
guard instead. Keep the existing path/depth behavior intact, but remove the
GNU-style -- handling so list continues to work across arbitrary OCI targets,
including Alpine/BusyBox images.
---
Nitpick comments:
In
`@lib/crewai-tools/src/crewai_tools/tools/boxlite_sandbox_tool/boxlite_file_tool.py`:
- Around line 117-122: The file-operation path can hang because `_sh` does not
pass any timeout through to `box.exec`, even though `BoxLiteExecTool` and
`BoxLitePythonTool` already support one. Update `_sh` in `BoxLiteFileTool` to
accept an optional timeout and forward it into `box.exec`, then thread that
timeout through the relevant schema/argument plumbing so file commands are
bounded consistently with the other BoxLite tools.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 16cf0484-6db6-4bfa-aaf5-38963dfbc3e1
📒 Files selected for processing (10)
lib/crewai-tools/pyproject.tomllib/crewai-tools/src/crewai_tools/__init__.pylib/crewai-tools/src/crewai_tools/tools/__init__.pylib/crewai-tools/src/crewai_tools/tools/boxlite_sandbox_tool/README.mdlib/crewai-tools/src/crewai_tools/tools/boxlite_sandbox_tool/__init__.pylib/crewai-tools/src/crewai_tools/tools/boxlite_sandbox_tool/boxlite_base_tool.pylib/crewai-tools/src/crewai_tools/tools/boxlite_sandbox_tool/boxlite_exec_tool.pylib/crewai-tools/src/crewai_tools/tools/boxlite_sandbox_tool/boxlite_file_tool.pylib/crewai-tools/src/crewai_tools/tools/boxlite_sandbox_tool/boxlite_python_tool.pylib/crewai-tools/tool.specs.json
| def _list(self, box: Any, path: str, *, depth: int) -> dict[str, Any]: | ||
| result = self._sh( | ||
| box, 'find -- "$1" -maxdepth "$2" -mindepth 1', path, str(depth) | ||
| ) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🌐 Web query:
Does BusyBox find support -- end of options before path argument
💡 Result:
BusyBox does not provide universal support for the "--" (end of options) delimiter across all its applets [1][2][3]. While BusyBox is a collection of many different utilities (applets), support for the "--" delimiter depends on how each individual applet is implemented [4][5]. Some BusyBox applets, such as getopt, explicitly document and support the "--" argument to signal the end of options [6]. However, other common utilities—most notably find—have been noted to lack support for this convention [1][3], often resulting in an error (e.g., "unrecognized: --") when used [3]. Because BusyBox prioritizes small code size, it often uses custom internal parsing logic (such as bb_getopt_ulflags) rather than standard library getopt routines [4][5]. Consequently, consistent behavior for "--" is not guaranteed across the entire BusyBox suite. If an applet you are using does not support the "--" delimiter, you may need to use alternative methods, such as prepending "./" to paths that begin with a dash [3].
Citations:
- 1: https://lists.busybox.net/pipermail/busybox/2018-December/086977.html
- 2: https://lists.busybox.net/pipermail/busybox/2018-December/086978.html
- 3: https://lists.uclibc.org/pipermail/busybox/2018-December/086978.html
- 4: https://lists.busybox.net/pipermail/busybox-cvs/2005-October/020917.html
- 5: https://lists.uclibc.org/pipermail/busybox/2006-February/052577.html
- 6: https://lists.busybox.net/pipermail/busybox-cvs/2012-November/033713.html
🏁 Script executed:
sed -n '130,190p' lib/crewai-tools/src/crewai_tools/tools/boxlite_sandbox_tool/boxlite_file_tool.pyRepository: crewAIInc/crewAI
Length of output: 2677
🏁 Script executed:
sed -n '1,140p' lib/crewai-tools/src/crewai_tools/tools/boxlite_sandbox_tool/boxlite_file_tool.py && printf '\n---\n' && rg -n "def _sh|_list\(" lib/crewai-tools/src/crewai_tools/tools/boxlite_sandbox_tool/boxlite_file_tool.py lib/crewai-tools/src/crewai_tools/tools/boxlite_sandbox_tool -nRepository: crewAIInc/crewAI
Length of output: 6727
🏁 Script executed:
rg -n "BoxLite|OCI image|busybox|alpine|find --" . -g '!**/.git/**'Repository: crewAIInc/crewAI
Length of output: 14668
Drop -- from find here to keep list working on BusyBox-based OCI images. BoxLite accepts arbitrary OCI references, so Alpine/BusyBox images are valid targets; find -- ... can fail there. Use a portable form or a path-prefix guard instead.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@lib/crewai-tools/src/crewai_tools/tools/boxlite_sandbox_tool/boxlite_file_tool.py`
around lines 165 - 168, The _list method in BoxliteFileTool uses a find
invocation with a leading -- that breaks on BusyBox-based OCI images, so update
the command construction in _list to use a portable form or a safe path-prefix
guard instead. Keep the existing path/depth behavior intact, but remove the
GNU-style -- handling so list continues to work across arbitrary OCI targets,
including Alpine/BusyBox images.
Summary
Adds a BoxLite sandbox toolkit —
BoxLiteExecTool,BoxLitePythonTool, andBoxLiteFileTool— mirroring the existing E2B and Daytona sandbox tools. BoxLite boots an OCI image inside a hardware-isolated micro-VM on the local host, so unlike E2B and Daytona it needs no API key or cloud account. It gives agents a self-hosted, VM-strength isolation boundary for running model-generated code.Tools
BoxLiteExecTool— run a shell command →{exit_code, stdout, stderr}BoxLitePythonTool— run Python (python3) →{exit_code, stdout, stderr}BoxLiteFileTool— read / write / append / list / delete / mkdir / info / existsAll three share
BoxLiteBaseTool's lifecycle — ephemeral (default; fresh box per call) or persistent (one cached box, removed at process exit) — matching the E2B/Daytona base.Notes
pip install "crewai-tools[boxlite]"(installsboxlite[sync])./dev/kvm).BoxLiteFileToolruns filesystem ops via the box shell (content transferred as base64), since BoxLite exposes command execution rather than a files API.Verification
ruff check/ruff formatclean;mypy(strict) passes.tool.specs.jsonregenerated to include the three tools.boxlite0.9.7, macOS/arm64): Python6*7 → 42, stderr + non-zero-exit capture, exec exit-code propagation, a file read/write/append/list/exists/delete round-trip, and a 256-byte binary round-trip — all pass.No tests are added, matching the existing E2B and Daytona sandbox tools (their execution needs live infra that CI can't provide).
https://claude.ai/code/session_01CifaVdyjdFaCpCqbtDduyY