Skip to content

Add Sandboxie-backed LLM tool sandbox#356

Merged
ModerRAS merged 1 commit into
masterfrom
feature/llm-sandboxie-toolhost
May 28, 2026
Merged

Add Sandboxie-backed LLM tool sandbox#356
ModerRAS merged 1 commit into
masterfrom
feature/llm-sandboxie-toolhost

Conversation

@ModerRAS
Copy link
Copy Markdown
Owner

@ModerRAS ModerRAS commented May 27, 2026

Summary

  • add optional Sandboxie Plus per-chat portable box tool sandbox settings
  • route built-in file and shell tools through a sandboxed ToolHost when enabled
  • add SandboxToolHost mode, Redis IPC contracts, and docs for Sandboxie configuration

Validation

  • dotnet build TelegramSearchBot.sln --configuration Release
  • dotnet test TelegramSearchBot.sln --configuration Release --no-build

Summary by CodeRabbit

Release Notes

  • New Features

    • Added Sandboxie Plus integration to execute language model tools within an isolated sandbox environment.
    • Introduced configuration options for sandbox settings, including executable paths, import directories, access restrictions, and execution timeouts.
  • Documentation

    • Updated README with sandbox configuration examples and field descriptions.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 27, 2026

Warning

Review limit reached

@ModerRAS, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 15 minutes and 14 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3377a5fc-2643-413c-9b4e-e815ab5e000f

📥 Commits

Reviewing files that changed from the base of the PR and between 5262a2c and be4f850.

📒 Files selected for processing (14)
  • README.md
  • TelegramSearchBot.Common/Env.cs
  • TelegramSearchBot.Common/Model/AI/LlmAgentContracts.cs
  • TelegramSearchBot.Common/Model/ToolContext.cs
  • TelegramSearchBot.LLM/Service/AI/LLM/McpToolHelper.cs
  • TelegramSearchBot.LLM/Service/Tools/BashToolService.cs
  • TelegramSearchBot.LLM/Service/Tools/FileToolService.cs
  • TelegramSearchBot.LLMAgent/LLMAgentProgram.cs
  • TelegramSearchBot.LLMAgent/Service/SandboxToolConsumer.cs
  • TelegramSearchBot.Test/Service/AI/LLM/SandboxieToolHostServiceTests.cs
  • TelegramSearchBot/AppBootstrap/GeneralBootstrap.cs
  • TelegramSearchBot/AppBootstrap/SandboxToolHostBootstrap.cs
  • TelegramSearchBot/Properties/AssemblyInfo.cs
  • TelegramSearchBot/Service/AI/LLM/SandboxieToolHostService.cs
📝 Walkthrough

Walkthrough

This PR introduces sandboxed tool execution using Sandboxie Plus: tools like bash and file operations can now run inside OS-level isolated "portable boxes" per chat. Configuration, data contracts, authorization logic, box/process management, Redis-based task queueing, and startup integration are all implemented.

Changes

Sandboxie LLM Sandbox Infrastructure

Layer / File(s) Summary
Configuration and Data Contracts
README.md, TelegramSearchBot.Common/Env.cs, TelegramSearchBot.Common/Model/AI/LlmAgentContracts.cs, TelegramSearchBot.Common/Model/ToolContext.cs
Env.cs adds Sandboxie configuration properties (paths, prefixes, timeouts, access lists) with defaults and derivations from WorkDir; README.md documents these fields; new SandboxToolTask and SandboxToolResult contracts enable Redis-based task queueing; ToolContext extended with IsSandboxed and SandboxBoxName flags.
Tool Authorization Model
TelegramSearchBot.LLM/Service/AI/LLM/McpToolHelper.cs, TelegramSearchBot.LLM/Service/Tools/BashToolService.cs, TelegramSearchBot.LLM/Service/Tools/FileToolService.cs
McpToolHelper.RegisterProxyTools accepts new allowLocalOverride parameter to control local tool collision behavior; BashToolService.ExecuteCommand and all FileToolService operations (read, write, edit, search, list) now allow both admin users and sandboxed tool hosts via shared IsFileToolAllowed helper.
Sandbox Process and Box Management
TelegramSearchBot/Service/AI/LLM/SandboxieToolHostService.cs
New service provisions per-chat Sandboxie portable boxes with INI generation, ImportBox directive injection, process lifecycle tracking by PID, and Redis-based tool task polling; includes INI builder, path normalization, stable box-name hashing, and process liveness checks.
Sandbox Tool Execution and Consumer Loop
TelegramSearchBot.LLMAgent/Service/SandboxToolConsumer.cs, TelegramSearchBot.LLMAgent/LLMAgentProgram.cs, TelegramSearchBot/AppBootstrap/SandboxToolHostBootstrap.cs
SandboxToolConsumer runs a long-polling loop consuming SandboxToolTask from Redis, executes tools with sandboxed ToolContext, and writes results back with configured TTL; LLMAgentProgram adds SandboxToolHost execution mode with shared shutdown token, new RunSandboxToolHostAsync path, and DI registration; new SandboxToolHostBootstrap entry point.
Startup and Tool Registration
TelegramSearchBot/AppBootstrap/GeneralBootstrap.cs
RegisterSandboxieTools callback conditionally registers sandbox tools via SandboxieToolHostService.GetToolDefinitions(), parses internal context arguments (__chatId, __userId, __messageId), and forwards execution with allowLocalOverride: true.

Sequence Diagram

sequenceDiagram
  participant Client as Tool Caller
  participant GeneralApp as GeneralBootstrap
  participant SandboxService as SandboxieToolHostService
  participant Redis as Redis
  participant ToolHost as SandboxToolHost Process
  participant Consumer as SandboxToolConsumer
  
  Client->>GeneralApp: call sandboxed tool (with __chatId, __userId, __messageId)
  GeneralApp->>SandboxService: ExecuteToolAsync(toolName, args, chatId, userId, messageId)
  SandboxService->>SandboxService: EnsureToolHostAsync(chatId) - build box, start process
  SandboxService->>Redis: enqueue SandboxToolTask
  SandboxService->>Redis: poll SandboxToolResult (with timeout)
  ToolHost->>Consumer: alive, waiting for tasks
  Consumer->>Redis: BRPOP SandboxToolQueue(chatId)
  Consumer->>Consumer: ExecuteToolAsync - build ToolContext(IsSandboxed=true, chatId, userId, messageId)
  Consumer->>Redis: write SandboxToolResult with TTL
  SandboxService->>Redis: receive result
  SandboxService->>Client: return tool output
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • ModerRAS/TelegramSearchBot#268: Both PRs modify LLMAgentProgram/McpToolHelper initialization and tool DI setup to ensure FileToolService (and related tool services) are registered for MCP/tool execution.
  • ModerRAS/TelegramSearchBot#269: Both PRs extend the existing "proxy tool"/tool-definition-over-Redis flow built around ProxyToolDefinition and McpToolHelper.RegisterProxyTools.
  • ModerRAS/TelegramSearchBot#349: Main PR's sandboxie LLM tool proxy wiring relies on the same proxy-tool routing/meta forwarding concept using __chatId/__userId/__messageId context keys for tool execution.

Poem

🐰 A sandbox so snug, so safe and so fine,
Tools execute sandboxed, each in its line,
Portable boxes per chat, with INI just right,
Redis queues tasks through the long coding night,
Box names hashed stable, processes tracked tight! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 5.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add Sandboxie-backed LLM tool sandbox' clearly and concisely summarizes the main change: introducing a Sandboxie-based sandbox for LLM tool execution. It is specific, relates directly to the core changes across multiple files, and accurately represents the primary objective of the pull request.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/llm-sandboxie-toolhost

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 27, 2026

PR Check Report

Summary

Test Results

Platform Status Details
Ubuntu Passed Tests passed, artifacts uploaded
Windows Passed Tests passed, artifacts uploaded

Code Quality

  • Code formatting check
  • Security vulnerability scan
  • Dependency analysis
  • Code coverage collection

Test Artifacts

  • Test results artifacts count: 2
  • Code coverage uploaded to Codecov

Links


This report is auto-generated by GitHub Actions

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (1)
TelegramSearchBot/Service/AI/LLM/SandboxieToolHostService.cs (1)

231-266: ⚖️ Poor tradeoff

PID tracking may be unreliable with Sandboxie Start.exe.

Sandboxie's Start.exe launches the target process inside the sandbox and may exit quickly or return a different PID than the actual sandboxed process. This means _toolHostProcesses stores the launcher PID, and IsProcessAlive may return false even when the sandboxed tool host is still running—causing unnecessary process restarts.

Consider tracking liveness via the Redis queue activity (e.g., heartbeat key) or using Sandboxie's management APIs/CLI to query active processes in the box.

🤖 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 `@TelegramSearchBot/Service/AI/LLM/SandboxieToolHostService.cs` around lines
231 - 266, StartToolHost currently stores the PID returned by Sandboxie
Start.exe into _toolHostProcesses and IsProcessAlive checks that PID, but
Sandboxie Start.exe often exits or returns a launcher PID rather than the
sandboxed tool PID; change the liveness strategy: stop relying on Process.Start
PID from StartToolHost and IsProcessAlive, and instead detect sandboxed tool
liveness via an external signal — e.g., have the sandboxed process push periodic
heartbeats to Redis (or a scheduler queue) and check that heartbeat key TTL in
place of IsProcessAlive, or query Sandboxie management/CLI to enumerate
processes in the named box (using instance.BoxName) to determine if the tool
host is running; update uses of _toolHostProcesses and IsProcessAlive to
reference the new heartbeat/box-query mechanism and remove dependence on the
Start.exe PID.
🤖 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 `@TelegramSearchBot.Common/Env.cs`:
- Line 75: Env currently assigns SandboxieToolTimeoutSeconds from config without
validation; ensure you validate its bounds in the Env loader (where
SandboxieToolTimeoutSeconds is set) by checking the value read from config
(e.g., config.SandboxieToolTimeoutSeconds) and handling zero/negative or
unreasonably large values: either clamp to a safe default minimum (e.g., >0) or
throw a descriptive exception/log and replace with a default constant. Apply the
same validation logic to the other occurrences noted (lines where
SandboxieToolTimeoutSeconds is assigned) so the Env class always stores a
validated, non-zero positive timeout.
- Around line 64-65: SandboxieStartExe and SandboxieIniPath are assigned
directly from config and don't guard against whitespace-only values; update the
Env initialization so these properties use the same null/whitespace fallback
logic as the nearby fields (e.g., call Trim() then check
string.IsNullOrWhiteSpace on config.SandboxieStartExe and
config.SandboxieIniPath) and assign the existing default when the trimmed value
is null/empty/whitespace; reference the SandboxieStartExe and SandboxieIniPath
assignments in Env.cs and apply the same pattern used for other config fields in
that file.

In `@TelegramSearchBot.LLM/Service/Tools/BashToolService.cs`:
- Around line 90-93: The class BashToolService and its [BuiltInTool] metadata
still claim "admin-only" despite the authorization in the toolContext check (see
BashToolService and the conditional that allows sandboxed hosts:
toolContext.UserId != Env.AdminId && !toolContext.IsSandboxed); update the class
summary/docstring and the [BuiltInTool] description to say that command
execution is allowed for admin users or sandboxed tool hosts (or similar
wording), so the tool metadata matches the actual authorization behavior. Ensure
any user-facing description strings or attributes associated with
BashToolService are updated consistently.

In `@TelegramSearchBot/AppBootstrap/GeneralBootstrap.cs`:
- Around line 273-295: RegisterSandboxieTools currently silently leaves
chatId/userId/messageId as 0 when parsing fails and calls
sandboxService.ExecuteToolAsync, which leads to opaque "missing ChatId" errors;
update the lambda passed to McpToolHelper.RegisterProxyTools (the async
(toolName, arguments) => { ... }) to validate that parsed __chatId (and
optionally __userId and __messageId) are > 0 before calling
SandboxieToolHostService.ExecuteToolAsync, and if validation fails return a
clear error result (e.g., an error/exception describing that required context
keys like "__chatId" are missing or invalid) so callers receive a descriptive
failure instead of the generic runtime error.

---

Nitpick comments:
In `@TelegramSearchBot/Service/AI/LLM/SandboxieToolHostService.cs`:
- Around line 231-266: StartToolHost currently stores the PID returned by
Sandboxie Start.exe into _toolHostProcesses and IsProcessAlive checks that PID,
but Sandboxie Start.exe often exits or returns a launcher PID rather than the
sandboxed tool PID; change the liveness strategy: stop relying on Process.Start
PID from StartToolHost and IsProcessAlive, and instead detect sandboxed tool
liveness via an external signal — e.g., have the sandboxed process push periodic
heartbeats to Redis (or a scheduler queue) and check that heartbeat key TTL in
place of IsProcessAlive, or query Sandboxie management/CLI to enumerate
processes in the named box (using instance.BoxName) to determine if the tool
host is running; update uses of _toolHostProcesses and IsProcessAlive to
reference the new heartbeat/box-query mechanism and remove dependence on the
Start.exe PID.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: a74625b0-f6fb-4ad3-9b03-b29608302b32

📥 Commits

Reviewing files that changed from the base of the PR and between 27b659a and 5262a2c.

📒 Files selected for processing (12)
  • README.md
  • TelegramSearchBot.Common/Env.cs
  • TelegramSearchBot.Common/Model/AI/LlmAgentContracts.cs
  • TelegramSearchBot.Common/Model/ToolContext.cs
  • TelegramSearchBot.LLM/Service/AI/LLM/McpToolHelper.cs
  • TelegramSearchBot.LLM/Service/Tools/BashToolService.cs
  • TelegramSearchBot.LLM/Service/Tools/FileToolService.cs
  • TelegramSearchBot.LLMAgent/LLMAgentProgram.cs
  • TelegramSearchBot.LLMAgent/Service/SandboxToolConsumer.cs
  • TelegramSearchBot/AppBootstrap/GeneralBootstrap.cs
  • TelegramSearchBot/AppBootstrap/SandboxToolHostBootstrap.cs
  • TelegramSearchBot/Service/AI/LLM/SandboxieToolHostService.cs

Comment thread TelegramSearchBot.Common/Env.cs Outdated
Comment thread TelegramSearchBot.Common/Env.cs Outdated
Comment thread TelegramSearchBot.LLM/Service/Tools/BashToolService.cs
Comment thread TelegramSearchBot/AppBootstrap/GeneralBootstrap.cs
@ModerRAS ModerRAS force-pushed the feature/llm-sandboxie-toolhost branch 7 times, most recently from 82e42d2 to 1e86fb4 Compare May 27, 2026 02:59
@ModerRAS ModerRAS force-pushed the feature/llm-sandboxie-toolhost branch from 1e86fb4 to be4f850 Compare May 27, 2026 03:14
@ModerRAS ModerRAS merged commit c260f31 into master May 28, 2026
7 of 8 checks passed
@ModerRAS ModerRAS deleted the feature/llm-sandboxie-toolhost branch May 28, 2026 01:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant