Callbacks let you run your own Python code every time the sandbox executes a command. You can use them to inspect what an agent is about to run, log results, or block commands you consider unsafe. This is useful when an LLM or agent is driving the sandbox and you want a final say before a command reaches the guest. A callback is a Python class that SmolVM calls at set points in a command’s lifecycle — before a command runs, after it finishes, or when it errors. You subclassDocumentation Index
Fetch the complete documentation index at: https://docs.celesto.ai/llms.txt
Use this file to discover all available pages before exploring further.
Callback, override only the hooks for the moments you care about, and pass instances to SmolVM(..., callbacks=[...]).
There are three hooks:
on_pre_run— runs before a command reaches the guest. This is the only hook that can block a command.on_post_run— runs after a command finishes successfully.on_run_error— runs when a command fails to execute.
ctx in the examples below. This is a run context — a single object that describes the command in flight: what was run, on which sandbox, and (afterwards) its result. You read from it to decide what to do. The run context section lists every field; for now, just know that ctx.command is the command string and ctx.vm_id is the sandbox ID.
When to use callbacks
- Block unsafe commands — Stop destructive commands like
rm -rf /before they reach the guest. - Audit and log — Record every command an agent runs, along with its exit code and output.
- Observe failures — Collect telemetry when a command errors out, without changing the rest of your code.
Block unsafe commands before they run
The pre-run hook is the only hook that can stop a command. Ifon_pre_run raises, the command is aborted and the exception is raised to the caller. Raise CommandBlockedError for an explicit, typed block.
run() call uses the same connection.
Log every command an agent runs
The post-run hook fires after a command completes. The context object carries the result, so you can log the exit code, stdout, and stderr.on_post_run and on_run_error are passive observers. If they raise, the exception is logged and swallowed so a buggy logger never breaks a command that already ran.
Attach callbacks to an existing sandbox
You can also attach callbacks to a sandbox you have already created.add_callback() returns the sandbox so calls can be chained.
Read command details from the run context
Every hook receives a singleRunContext object. Read from it to decide what to do.
| Field | Type | Available in | Description |
|---|---|---|---|
vm_id | str | all hooks | ID of the sandbox running the command. |
command | str | all hooks | The command string passed to run(). |
shell | str | all hooks | "login" or "raw" execution mode. |
timeout | int | all hooks | Per-command timeout in seconds. |
result | CommandResult | None | on_post_run | Exit code, stdout, and stderr. |
error | Exception | None | on_run_error | The transport error raised during the run. |
Scope and limitations
Callbacks fire around the synchronousSmolVM.run() method. They cover both the SSH and vsock transports, because the hooks run on the facade before any transport is selected.
This first release intentionally covers command hooks only. Lifecycle hooks (start, stop, snapshot), file-transfer hooks, and the async run() path are not wired up yet.