Skip to main content
This is an optional extension of the Running Agents on Sandboxes tutorial. Complete the main tutorial first.

Overview

Instead of shutting down the devbox after pushing a branch and recreating a fresh environment every time you get feedback, you can use Runloop’s suspend and resume functionality to preserve the devbox’s disk state. This allows you to respond to code review comments and make incremental changes without losing your in-progress work.
1

Push branch and create a pull request

Push your branch to the remote repository and create a pull request for review.
# Create a named shell and navigate to the project directory
shell = devbox.shell("workflow-shell")
await shell.exec("cd ~/sample-todo-nextjs")

# Push the branch to the remote repository
await shell.exec(f"git push -u origin {branch_name}")
print(f"Pushed branch: {branch_name}")

# Note: You'll need to create the PR manually via GitHub UI or API.
# For this example, we'll assume you create it and get the PR number.
# In a more automated workflow, you could use the GitHub CLI (`gh pr create`)
# to open the PR and capture the PR number programmatically.
pr_number = 123  # Replace with your actual PR number
2

Suspend the devbox

Suspend the devbox to save the disk state while stopping compute costs. The devbox can be resumed later to continue working.
# Suspend the devbox to preserve disk state
await devbox.suspend()
print(f"Devbox {devbox.id} suspended successfully")
3

Wait for PR comment and process feedback

Wait for a comment on your pull request. When a comment is received, call a function to resume the devbox and process the feedback. In a production workflow, you would typically use GitHub webhooks (or at least a more robust polling loop) to detect when a comment is added; for simplicity, this example checks for comments manually in a loop.
import os
import time
from github import Github  # Requires PyGithub library

# Initialize GitHub client
g = Github(os.environ["GH_TOKEN"])
repo = g.get_repo("runloopai/sample-todo-nextjs")
pr = repo.get_pull(pr_number)

# Poll for new comments (in production, use webhooks instead)
print("Waiting for PR comment...")
last_comment_id = None
while True:
    comments = pr.get_issue_comments()
    if comments.totalCount > 0:
        latest_comment = list(comments)[-1]
        if last_comment_id != latest_comment.id:
            print(f"New comment: {latest_comment.body}")
            feedback = latest_comment.body
            # Process the feedback by resuming devbox and making changes
            await process_feedback(devbox, feedback)
            break
    time.sleep(10)  # Check every 10 seconds
For production use, prefer GitHub webhooks together with a GitHub App to receive PR comment events and trigger your workflow, instead of relying on a long-running polling loop as shown here.
4

Define the feedback processing function

Define the function that resumes the devbox and processes the PR feedback. This function handles resuming the devbox, recreating the shell, making changes based on feedback, and pushing updates.
async def process_feedback(devbox, feedback: str):
    # Resume the devbox
    await devbox.resume()
    await devbox.await_running()
    print(f"Devbox {devbox.id} resumed and ready")
    
    # Recreate the named shell to continue working
    shell = devbox.shell("workflow-shell")
    await shell.exec("cd ~/sample-todo-nextjs")
    
    # Continue working based on PR feedback
    # For example, if the feedback was to adjust the blue accent color
    result = await shell.exec(
        f'claude -p "Based on the PR feedback: {feedback}"'
    )
    
    print(f"Updated based on feedback")
    print(f"Result: {await result.stdout()}")
    
    # Stage and commit the new changes
    await shell.exec("git add .")
    await shell.exec(
        f'git commit -m "Address PR feedback: {feedback[:50]}"'
    )
    
    # Push the updates
    await shell.exec("git push")
    print("Updates pushed to PR")
You can repeat the suspend/resume cycle as many times as needed to iterate on PR feedback. The devbox preserves all your work between sessions, making it easy to pick up where you left off.

Next Steps