Managing Sandboxes

Manage sandbox lifecycle in CodeCourier -- monitor status, send messages, kill sessions, and handle cleanup.

7 min read
sandboxesmanagelifecycle

Once a sandbox is running, CodeCourier provides tools to monitor its progress, interact with the AI agent, and manage the sandbox through its full lifecycle. This guide covers status tracking, messaging, termination, cleanup, and the soft-delete/restore system.

Sandbox Lifecycle States

Every sandbox in CodeCourier is in one of five states. These are stored in the status field of the sandbox record and determine what actions are available.

Creating

The sandbox has been requested but the E2B virtual machine is still being provisioned. During this phase, CodeCourier has created a database record and is waiting for E2B to return a sandbox ID. No interaction is possible yet.

Running

The sandbox is active. The AI agent is executing inside the VM and you can send messages, view streaming terminal output, and monitor progress. The active sandbox counter for the project is incremented when a sandbox enters this state.

Paused

The sandbox has been suspended. The VM state is preserved but the agent is not actively executing. Paused sandboxes can be resumed. This state is primarily used by E2B's pause/resume functionality for long-running environments.

Killed

The sandbox has been terminated. The E2B VM has been destroyed and all in-memory state is lost. Files committed to Git before termination are preserved in the remote repository. A sandbox transitions to killed when you manually stop it, when the timeout expires, or when a workflow step completes.

Error

The sandbox encountered a fatal error. The error field on the sandbox record contains the error message. Common causes include missing API keys, E2B provisioning failures, and unrecoverable agent crashes.

State Transitions

The dashboard shows real-time status updates powered by Convex reactive queries. When a sandbox transitions between states, the UI updates automatically. The active sandbox counter in your project overview reflects the number of sandboxes in the "running" state.

Monitoring Sandbox Activity

Streaming Terminal Output

When you open a running sandbox in the dashboard, you see a streaming terminal view that displays the AI agent's output in real time. This includes:

  • Text responses from the AI model.
  • Tool use indicators (file edits, command execution, searches).
  • Error messages and warnings.
  • Progress updates as the agent works through its task.

The terminal output is powered by the sandboxMessagestable. Each message has a role (user or assistant),content, and optional streamLog for the raw streaming data. Messages also carry a status field (streaming, completed, or error) to indicate whether the response is still being generated.

Sandbox Detail View

The sandbox detail page shows comprehensive information about the sandbox:

  • Status badge -- Visual indicator of the current lifecycle state.
  • Configuration -- Template, model, timeout, memory, and CPU settings.
  • Metadata -- Creation time, linked run or issue session, trigger run ID.
  • Git information -- Repository URL, branch name, and PR status (if a pull request was created).
  • Learning extraction status-- Whether learnings have been extracted from the sandbox's message history.

Sending Messages

For standalone sandboxes (not part of a workflow run), you can send follow-up messages to the AI agent while it is running. This is CodeCourier's interactive mode -- it works like a chat conversation where each message triggers the agent to perform additional work.

When you send a message:

  1. The message is stored in the sandboxMessages table with role user.
  2. A Trigger.dev task dispatches the message to the running E2B sandbox.
  3. The AI CLI receives the message and begins generating a response.
  4. The response streams back and is stored as a message with role assistant.

If the sandbox has already completed its initial task and the agent is idle, the follow-up message uses the CLI's --continueflag to resume the conversation context.

Workflow Sandboxes

You cannot send interactive messages to sandboxes that are part of a workflow run. Workflow sandboxes are managed by the orchestrator and receive their prompts from the pipeline step configuration.

Stopping and Killing Sandboxes

Manual Kill

You can stop a running sandbox at any time from the dashboard. When you kill a sandbox:

  1. CodeCourier sends a kill command to the AI CLI process inside the sandbox (e.g., pkill -9 -f '[c]laude' for Claude Code).
  2. Before destroying the VM, CodeCourier detects any Git repository in the sandbox and attempts a best-effort push of uncommitted changes.
  3. If a non-default branch with a remote is detected, a pull request is created automatically.
  4. The E2B sandbox is terminated and the status is updated to killed.

Automatic Timeout

Every sandbox has a configured timeout. When the timeout expires, E2B automatically destroys the VM. CodeCourier detects this and updates the sandbox status accordingly. The default timeout is 15 minutes for standalone sandboxes and varies for workflow steps based on the workflow configuration.

Pull Request Creation

When a sandbox finishes work (either by completing its task or being killed), CodeCourier can automatically create a GitHub pull request. The PR creation flow:

  1. Detect Git info from the sandbox: remote URL and current branch.
  2. Skip if the branch is main or master (no PR needed for default branches).
  3. Push any unpushed commits from the sandbox.
  4. Create a PR via the GitHub API using the configured GitHub token.
  5. Store the PR URL, number, and status on the sandbox record.

The PR status field tracks the pull request lifecycle:creating, created, failed,skipped, or merged.

Learning Extraction

After a sandbox completes, CodeCourier can extract learnings from the agent's message history. Learnings are patterns, preferences, gotchas, and architectural insights that the agent discovered during execution. These are stored in the learnings table and can be compiled into learning versions that are injected into future sandboxes.

The extraction status is tracked on the sandbox record:

  • pending -- Extraction has been queued.
  • running -- The extraction agent is processing messages.
  • completed -- Learnings have been extracted and stored.
  • skipped -- Extraction was not needed (e.g., no messages).
  • error -- Extraction failed. The error is in learningExtractionError.

Soft Delete and Restore

Sandboxes support soft deletion. When you delete a sandbox from the dashboard, the record is not physically removed from the database. Instead, a deletedAt timestamp is set. Soft-deleted sandboxes:

  • Are hidden from the default sandbox list.
  • Do not count toward active sandbox counters.
  • Can be restored at any time, which clears the deletedAt field.
  • Can be permanently deleted, which physically removes the database record.

This two-phase deletion pattern protects against accidental data loss. The project counters are adjusted during both soft-delete and restore operations.

Resource Management

Active Sandbox Tracking

CodeCourier maintains a denormalized counter of active sandboxes per project. This counter is incremented when a sandbox enters therunning state and decremented when it leaves. The counter is displayed in the project dashboard overview.

Usage Tracking

Every sandbox session generates usage records that track:

  • E2B compute -- Sandbox runtime in seconds, billed by E2B.
  • AI token usage -- Input and output tokens consumed by the AI model during the session.
  • Cost calculation -- Total USD cost based on the usage cost rates configured for each service.

Usage records are linked to the sandbox via the sandboxIdfield and can be viewed in the project's billing and usage section.

Sandbox status update (internal)
// How CodeCourier tracks sandbox state transitions
await ctx.runMutation(internal.sandboxes.updateStatus, {
  id: sandboxId,
  status: "killed",
});
// Active counter is automatically decremented
// when transitioning from "running" to any other state