Skip to main content
Daytona runs code in isolated cloud sandboxes. A coding agent’s tools work in a sandbox checkout while its model loop runs in the Rebuno agent. Each tool call passes through policy and becomes a recorded step. The workspace is a resource: later dispatches reopen it, and forks create separate sandboxes from its checkpoints. It stops while a call waits for approval.

Register the workspace

The handler registers a sandbox with a checkpoint policy:
The example’s DaytonaResource implements three operations:
  • create(checkpoint_ref=None) creates a sandbox from the selected snapshot or a fresh checkout, and configures its Git branch.
  • open(binding) gets the sandbox ID recorded for this execution and starts the sandbox if it is stopped.
  • checkpoint(handle) creates a named Daytona snapshot of the sandbox.
The checkpoint policy is optional. Without it, dispatches and session turns still reopen the same sandbox, but forks start from a fresh checkout. With it, the SDK captures a baseline, then checkpoints after every fifth live tool call that declares a workspace change, and on completion. Rebuno stores the sandbox binding and snapshot names; Daytona stores the files. Snapshots are named rebuno-<id> and stay in the Daytona organization until deleted. Each new sandbox gets a unique Git branch, and shell commands push the current branch. Reopening a workspace preserves its branch. Daytona stops idle sandboxes and keeps their files, and open starts them again. Missing sandboxes or selected snapshots fail the execution.

Wrap the tools

shell and write_file declare workspace changes. read_file uses the default of none:
The model also uses shell to commit and push the branch. These tools use safe_to_retry, so an interrupted command can run again. See idempotency when adding commands with effects that must not repeat.

Keep credentials out of the sandbox

Cloning and pushing need a GitHub token. The driver stores it as a Daytona secret limited to github.com and mounts the secret into each sandbox as GITHUB_AUTH:
Inside the sandbox, GITHUB_AUTH holds a placeholder. Daytona replaces it with the secret’s value on requests to github.com, so git works as usual and nothing in the sandbox can read the token. The driver updates the secret when creating or opening a sandbox, so resumed workspaces use the token the worker currently holds. Opening the pull request is a separate tool that calls GitHub’s API from the agent:
The secret covers only github.com, so the sandbox can push a branch but cannot use that token to call the API. Protect the default branch with a GitHub ruleset that requires a pull request.

Stop while waiting

The handler stops the workspace when the model loop finishes or waits for approval:
pause() stops the sandbox. Files persist and running processes end. The check reads execution().suspension because a framework can catch Blocked inside its loop. After approval, the next dispatch replays up to the held call and the driver starts the same sandbox. A completion checkpoint briefly starts a stopped sandbox and stops it again after capture.

Sessions

The handler reads the previous completed turn with previous() and returns its conversation in Result.state:
Executions in the same session reuse the workspace and Git branch, so later pushes update the same pull request. See Sessions.

Fork the workspace

A fork creates a separate sandbox from the selected snapshot. At an uncovered point it uses the newest earlier checkpoint; copied tool results still replay through the requested event and may describe changes missing from that sandbox. See Fork coverage. Snapshots restore sandbox files; GitHub branches and pull requests persist.

Write the policy

Sandbox tools are allowed. Opening a pull request waits for approval.

Run it

examples/integrations/sandbox/daytona has the full agent, resource driver, policy, and dev kernel config. Set DAYTONA_API_KEY, REPO (the repository as owner/name), GITHUB_TOKEN, LLM_MODEL, LLM_BASE_URL, and LLM_API_KEY. The token needs read and write access to the repository’s contents and pull requests. Start the kernel and agent from that directory:
Create an execution:
The open_pr call appears in rebuno exec watch. See Approvals to approve it. Continue the same session with:
To see a re-dispatch, stop the agent after a few tool calls and start it again. The kernel dispatches the execution once its lease expires, two minutes by default. lease_timeout_seconds sets a shorter lease for the agent.