module RubyLLM::Sandbox
A sandbox runs commands RubyLLM did not write, such as the code a model sends to Chat#with_code_execution, and holds the whole policy for them: what they may read and write, which hosts they reach, where they start, and how long they run. Define one as an MXC::Sandbox class from the mxc gem:
class ReadOnlySandbox < MXC::Sandbox timeout 120 end class WorkspaceSandbox < MXC::Sandbox directory Rails.root.join("storage/workspace") writable Rails.root.join("storage/workspace") timeout 300 end RubyLLM.configure do |config| config.sandbox = "ReadOnlySandbox" end
A String names the class and is looked up whenever a chat needs it, so in Rails the classes live in app/sandboxes, autoload, and reload like the rest of the application.
A sandbox may be an MXC::Sandbox class or instance, or any other class or object whose instances answer two methods:
class RemoteSandbox def supported? true end def run(*command, timeout:, readable: [], writable: [], denied: [], directory: nil, env: {}, network: nil) # Runs +command+ and returns an object answering stdout, stderr, # exit_code, and timed_out? end end
run takes the command like Kernel#system: one String for the shell, or a program and its arguments. The keywords are what RubyLLM adds to the sandbox’s own policy for one run: readable and writable paths holding the run’s files, denied paths it must not see, even inside readable ones, the directory to start in when the sandbox has none of its own, and env, the environment the run’s languages and packages need. timeout is the sandbox’s own, or 120 seconds when it answers timeout with nil or not at all. network is nil for the sandbox’s own access; RubyLLM passes { allow: [...] } only to install declared packages from their registries. With a block, run may yield each line of output as it arrives, from standard output and standard error, like IO#each_line, and code execution reports the lines as progress; a sandbox may ignore the block. The result may also answer blocked, the hosts the network policy refused. A sandbox may answer reason, which RubyLLM adds to the error it raises when #supported? is false, and with_libraries_of, taking paths and returning a sandbox whose runs may load the libraries those files link, which RubyLLM calls with Ruby and its extensions. It may also answer readable, writable, network, directory, and timeout, which describe it to the model and to the person approving an escalation.
Constants
- BACKENDS
-
The values
Configuration#sandbox_backendaccepts. - DEFAULT_TIMEOUT
-
Seconds a run may take when the sandbox sets no timeout.