advancedpracticalopenhandsswe-agentacidocker

OpenHands & SWE-Agent: Practical Guide

Agent-Computer Interface (ACI) concepts, OpenHands Docker sandbox, Agent Canvas, multi-task orchestration, and SWE-Agent's LM-centric GitHub Issue auto-fix.

OpenHands & SWE-Agent: Practical Guide

OpenHands (formerly OpenDevin, github.com/All-Hands-AI/OpenHands, 40K+ stars) and SWE-Agent (github.com/princeton-nlp/SWE-agent, 20K+ stars) represent two of the most mature open-source approaches to autonomous software engineering. Both grew out of the same research lineage at Princeton and share a foundational design philosophy: Agent-Computer Interface (ACI). This guide covers their architectures in practical detail — Docker sandboxes, LM-centric design, GitHub Issue auto-fix workflows, and how to run them in production loop patterns.

Agent-Computer Interface: The Shared Foundation

ACI is the design discipline of making computing environments legible to language models. Rather than training models to navigate raw terminal output, ACI researchers redesign the interface layer so that an LM can reason about system state efficiently.

The ACI Principle

┌──────────────────────────────────────────────────────────┐
│  Traditional Tool-Use                                    │
│                                                          │
│  LM ──► raw bash ──► unstructured stdout ──► parse ──► LM│
│         (inflexible)    (noisy, huge)    (fragile)       │
│                                                          │
├──────────────────────────────────────────────────────────┤
│  Agent-Computer Interface (ACI)                           │
│                                                          │
│  LM ──► structured actions ──► curated observations ◄─── LM│
│         (typed, bounded)     (filtered, summarized)     │
│                                                          │
└──────────────────────────────────────────────────────────┘

The key insight from the SWE-Agent paper (arXiv:2405.15793) is that the interface matters more than the model. SWE-Agent with GPT-4o and a well-designed ACI outperforms the same model with a raw bash interface by a significant margin on SWE-bench. ACI design choices include: command output truncation, error highlighting, file diff formatting, and structured action spaces that prevent the LM from issuing invalid commands.

ACI Design Decisions That Matter

Design ChoiceRaw Bash (Bad ACI)Good ACIImpact
Command outputFull 500-line stdoutTruncated + file path hints-15% token waste
Error signalsBuried in textExtracted and highlighted+8% fix rate
File editingsed / echo pipelinesDedicated edit_file action+12% accuracy
Navigationcd, ls, pwdStructured list_files, open_file+5% task completion
Observation formatRaw terminal escape codesClean Markdown with line numbers+10% LM comprehension

These percentages come from the SWE-Agent ablation study, where each ACI improvement was tested independently on the SWE-bench Verified subset.

OpenHands: The Full-Stack AI Engineer

OpenHands takes a broader approach than SWE-Agent. Instead of focusing solely on GitHub Issue resolution, it provides a complete development environment with an Agent Canvas (browser-based UI), Docker sandboxing, and multi-task orchestration.

Architecture Overview

┌─────────────────────────────────────────────────────────┐
│  Agent Canvas (Browser UI)                               │
│  ┌─────────────────────────────────────────────────┐    │
│  │  Code Editor  │  Terminal  │  Browser  │  Chat   │   │
│  └──────────┬────┴──────┬─────┴─────┬─────┴──────┘    │
│             │           │           │                   │
│  ───────────┼───────────┼───────────┼────────────────  │
│             ▼           ▼           ▼                   │
│  ┌─────────────────────────────────────────────────┐    │
│  │  Event Stream (Backend)                          │    │
│  │  Actions → Observations → Actions → ...          │    │
│  └──────────────────────┬──────────────────────────┘    │
│                         │                               │
│  ───────────────────────┼────────────────────────────── │
│                         ▼                               │
│  ┌─────────────────────────────────────────────────┐    │
│  │  Docker Sandbox (Runtime)                         │    │
│  │  - Full Ubuntu environment                       │    │
│  │  - Pre-installed language runtimes                │    │
│  │  - Network-isolated by default                    │    │
│  │  - Ephemeral: destroyed after session             │    │
│  └─────────────────────────────────────────────────┘    │
│                                                         │
│  ┌─────────────────────────────────────────────────┐    │
│  │  LLM Backend (Pluggable)                          │    │
│  │  Claude / GPT-4o / Gemini / Ollama (local)        │    │
│  └─────────────────────────────────────────────────┘    │
└─────────────────────────────────────────────────────────┘

Docker Sandbox: The Isolation Layer

The Docker sandbox is OpenHands' most important architectural decision. Every agent session runs inside a fresh Docker container, which solves three critical problems for loop engineering:

  1. Safety — the agent cannot modify the host system. A misconfigured rm -rf / only destroys the ephemeral container.
  2. Reproducibility — each session starts from the same base image, making failures deterministic and debuggable.
  3. Multi-tenant isolation — multiple agents can run concurrently without interference.
# docker-compose.yaml — OpenHands with custom sandbox config
version: "3.8"
services:
  openhands:
    image: ghcr.io/all-hands-ai/openhands:latest
    ports:
      - "3000:3000"
    environment:
      - SANDBOX_USER_ID=1000
      - WORKSPACE_MOUNT_PATH=/path/to/your/repo
      - LLM_MODEL=claude-sonnet-4
      - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./workspace:/opt/workspace
    deploy:
      resources:
        limits:
          memory: 8G
          cpus: "4.0"

The Sandbox Runtime Image

OpenHands ships with openhands-sandbox (github.com/All-Hands-AI/openhands-sandbox), a Docker image pre-loaded with common development tools:

CategoryPre-installed Tools
LanguagesPython 3.11, Node.js 20, Rust, Go, Java 17
Package managerspip, npm, cargo, go modules, gradle
Build toolsgcc, g++, make, cmake
Version controlgit, gh (GitHub CLI)
BrowsersChromium (for web-based tasks)
Editorsvim, nano (for LM-initiated edits)

This pre-installation matters for loop efficiency. Without it, the agent would waste the first 3-5 loop iterations installing dependencies before doing any actual work.

Running OpenHands Locally

# Quick start with Docker (recommended)
docker run -it --rm \
  -p 3000:3000 \
  -e ANTHROPIC_API_KEY=$ANTHROPIC_API_KEY \
  -e LLM_MODEL=claude-sonnet-4 \
  ghcr.io/all-hands-ai/openhands:latest

# Open http://localhost:3000 in your browser
# The Agent Canvas provides a VS Code-like interface

For non-Docker setups, OpenHands also supports a headless mode suitable for CI/CD integration:

# Headless mode: run a task and exit
python -m openhands.core.main \
  --agent CodeActAgent \
  --model claude-sonnet-4 \
  --max-iterations 30 \
  --task "Fix the failing test in tests/test_auth.py"

Agent Canvas: The Human-AI Interaction Layer

The Agent Canvas is OpenHands' browser-based interface that lets you observe and steer the agent in real time. It is conceptually similar to Devin's interface but fully open-source.

Canvas Components

┌─────────────────────────────────────────────────────────┐
│  Agent Canvas                                           │
│                                                         │
│  ┌───────────────────────────────┐ ┌──────────────────┐ │
│  │  File Browser                 │ │  Agent Controls  │ │
│  │  ├── src/                      │ │  [Pause] [Stop]  │ │
│  │  │   ├── main.py               │ │  [Approve] [Deny]│ │
│  │  │   └── utils.py              │ │  Model: Sonnet 4 │ │
│  │  └── tests/                    │ │  Iteration: 12/30│ │
│  └───────────────────────────────┘ └──────────────────┘ │
│                                                         │
│  ┌───────────────────────────────────────────────────┐  │
│  │  Terminal (Agent Output)                            │  │
│  │  $ python -m pytest tests/test_auth.py             │  │
│  │  FAILED test_login_invalid_credentials              │  │
│  │  Agent: Opening src/auth.py to investigate...       │  │
│  └───────────────────────────────────────────────────┘  │
│                                                         │
│  ┌───────────────────────────────────────────────────┐  │
│  │  Chat (Human → Agent)                              │  │
│  │  > Make sure you also check the rate limiter       │  │
│  │  > The error only happens with expired tokens      │  │
│  └───────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────┘

The key interaction modes are:

ModeDescriptionWhen to Use
AutonomousAgent runs without human inputWell-scoped tasks with clear success criteria
SuggestAgent proposes actions, human approvesSafety-critical code changes
ChatHuman guides agent via natural languageExploratory debugging, vague requirements

This maps directly to the loop engineering concept of human-in-the-loop vs. autonomous loops. The Canvas lets you shift between modes mid-session — start autonomous, switch to suggest when the agent approaches a sensitive file, then return to autonomous once the change is verified.

Multi-Task Orchestration

OpenHands supports running multiple agent sessions in parallel, which is essential for production loop engineering workflows that need to process several issues simultaneously.

Parallel Task Execution

# parallel_tasks.py — Run 3 agents concurrently on different issues
from openhands.core.main import run_agent

tasks = [
    {
        "task": "Fix memory leak in the event listener cleanup (Issue #123)",
        "model": "claude-sonnet-4",
        "max_iterations": 25,
        "workspace": "/workspace/project-a"
    },
    {
        "task": "Add pagination to the /api/users endpoint (Issue #124)",
        "model": "claude-sonnet-4",
        "max_iterations": 20,
        "workspace": "/workspace/project-a"
    },
    {
        "task": "Update deprecated dependency webpack@4 to webpack@5 (Issue #125)",
        "model": "claude-haiku-4.5",  # Haiku for straightforward migration
        "max_iterations": 15,
        "workspace": "/workspace/project-a"
    },
]

# Each task gets its own Docker sandbox
results = await run_agent.parallel(tasks)

Cost Strategy for Multi-Task Loops

Task ComplexityModelMax IterationsEst. Cost per Task
Bug fix (multi-file)Claude Sonnet 425~$0.80
Feature additionClaude Sonnet 420~$0.60
Dependency migrationClaude Haiku 4.515~$0.05
Test writingClaude Haiku 4.510~$0.03

Running 10 tasks in parallel with this tiering costs roughly $5-8 total, compared to $25-50 if all tasks used Opus without iteration caps.

SWE-Agent: LM-Centric GitHub Issue Resolution

SWE-Agent (github.com/princeton-nlp/SWE-agent) takes a more focused approach: given a GitHub Issue URL, it produces a patch that resolves the issue. Its design is deliberately LM-centric — the language model is the sole decision-maker, and every other component exists to serve the model's reasoning loop.

The SWE-Agent Loop

┌───────────────────────────────────────────────────────────┐
│  SWE-Agent Execution Loop                                 │
│                                                           │
│  ┌──────────┐     ┌───────────────┐     ┌──────────────┐  │
│  │  GitHub   │────►│  Repository  │────►│  LM          │  │
│  │  Issue    │     │  Setup       │     │  Reasoning   │  │
│  │  (input)  │     │  (clone+env) │     │  (core)      │  │
│  └──────────┘     └───────────────┘     └──────┬───────┘  │
│                                                │           │
│                       ┌────────────────────────┘           │
│                       ▼                                    │
│  ┌──────────────────────────────────────────────────────┐  │
│  │  Action-Observation Loop                              │  │
│  │                                                      │  │
│  │  LM produces action ──► ACI executes ──► observation │  │
│  │       ▲                                        │     │  │
│  │       └────────────────────────────────────────┘     │  │
│  │                                                      │  │
│  │  Repeat until: patch produced OR max iterations hit   │  │
│  └──────────────────────────────────────────────────────┘  │
│                       │                                    │
│                       ▼                                    │
│  ┌──────────────────────────────────────────────────────┐  │
│  │  Patch Generation                                     │  │
│  │  git diff → formatted patch → submit to GitHub PR     │  │
│  └──────────────────────────────────────────────────────┘  │
└───────────────────────────────────────────────────────────┘

LM-Centric Design Philosophy

The term "LM-centric" comes directly from the SWE-Agent paper. It means the architecture is designed around the assumption that the LM is the bottleneck — every component should minimize the cognitive load on the model and maximize the signal-to-noise ratio of what it sees.

This contrasts with tool-centric designs (like early AutoGPT) where the LM is treated as a thin orchestration layer and the tools do the heavy lifting. SWE-Agent flips this: the tools are deliberately simple (file read, file edit, run command, search), and the LM does all the reasoning about which tools to use and what to do with the output.

The ACI Action Space

SWE-Agent defines a tightly scoped set of actions:

ActionArgumentsPurpose
open_filepath, line_rangeRead file contents (with line numbers)
edit_filepath, old, newPrecise string replacement
search_dirpattern, pathGrep for patterns across files
run_commandcommandExecute shell command (output truncated)
submit_patchSignal that the fix is complete

Notice the deliberate omission of create_file, delete_file, and move_file. SWE-Agent forces edits through edit_file which requires the model to specify exact old/new string pairs. This constraint prevents the model from accidentally destroying files and makes each edit auditable.

Running SWE-Agent on a Real Issue

# Install SWE-Agent
pip install swe-agent

# Run on a specific GitHub issue
sweagent run \
  --repo "django/django" \
  --issue "https://github.com/django/django/issues/12345" \
  --model "claude-sonnet-4" \
  --max-iterations 20 \
  --output-dir ./swe-output

# The output contains:
# swe-output/
# ├── trajectory.json      # Full action-observation log
# ├── patch.diff           # The generated fix
# └── report.json          # Metadata (cost, iterations, status)

Customizing the ACI for Your Project

SWE-Agent's ACI is configurable via YAML, which is critical for loop engineering because different projects have different structure and conventions:

# config/my_project_aci.yml
agent:
  action_space:
    - name: open_file
      description: "Read file contents with line numbers"
      params:
        - name: path
          type: string
          required: true
        - name: offset
          type: integer
          default: 0
        - name: limit
          type: integer
          default: 200
      observation_template: |
        File: {path} (lines {offset}-{offset+limit})
        {content}

    - name: edit_file
      description: "Replace exact text in a file"
      params:
        - name: path
          type: string
          required: true
        - name: old_string
          type: string
          required: true
        - name: new_string
          type: string
          required: true
      # Custom hint injected into LM context
      hint: |
        Use edit_file for surgical changes. For large rewrites,
        consider multiple small edits rather than one massive replacement.

    - name: run_pytest
      description: "Run pytest on specific test files"
      params:
        - name: target
          type: string
          required: true
      output_filter: "pytest"  # Only show pytest output, suppress noise

  system_prompt: |
    You are fixing an issue in {repo_name}.
    The project uses {testing_framework} and follows {code_style}.
    Always run tests after making changes.

OpenHands vs. SWE-Agent: When to Use Which

Both tools share ACI roots but serve different purposes. The choice depends on your loop engineering workflow.

Comparison Table

DimensionOpenHandsSWE-Agent
ScopeFull development environmentGitHub Issue → Patch only
InterfaceBrowser-based Agent CanvasCLI + headless
IsolationDocker sandbox (mandatory)Docker sandbox (optional)
Multi-taskNative parallel executionSingle-task per invocation
LM modelPluggable (Claude, GPT, Gemini, local)Pluggable (Claude, GPT, Gemini, local)
CustomizationPython API + configYAML ACI config
Best forExploratory development, multi-step featuresReproducible issue resolution at scale
GitHub stars40K+20K+
LicenseMITMIT
MaintainerAll-Hands-AIPrinceton NLP

Decision Flowchart

Do you have a specific GitHub Issue to fix?
├─ YES
│   Is the fix bounded (single file or small diff)?
│   ├─ YES → Use SWE-Agent (faster, cheaper, focused)
│   └─ NO  → Use OpenHands (full env, multi-file exploration)
│
└─ NO (open-ended task)
    Do you need a browser UI to monitor progress?
    ├─ YES → Use OpenHands with Agent Canvas
    └─ NO  → Use OpenHands headless mode

Integrating into Loop Engineering Workflows

Both tools fit naturally into the loop engineering framework. Here is a practical pattern for an overnight autonomous loop that triages and fixes GitHub issues.

Overnight Issue Resolution Pipeline

# overnight-loop.yaml
pipeline:
  name: "github-issue-auto-fix"
  schedule: "0 2 * * 1-5"  # Weekdays at 2 AM
  
  steps:
    - name: "fetch-issues"
      action: gh issue list --label "bug" --state open --limit 10
      output: "issues.json"

    - name: "classify"
      model: "claude-haiku-4.5"
      prompt: |
        Classify each issue by complexity:
        - "simple": single-file fix, clear reproduction
        - "medium": multi-file, needs investigation
        - "complex": architectural change, high risk
      output: "classified_issues.json"

    - name: "fix-simple"
      tool: "swe-agent"
      model: "claude-sonnet-4"
      max_iterations: 20
      filter: "classified_issues.json | where complexity == 'simple'"
      
    - name: "fix-medium"
      tool: "openhands"
      model: "claude-sonnet-4"
      max_iterations: 30
      filter: "classified_issues.json | where complexity == 'medium'"

    - name: "escalate-complex"
      action: gh issue add-comment --body "Requires human review"
      filter: "classified_issues.json | where complexity == 'complex'"

  safety:
    max_budget: "$15.00"
    require_human_review_for: ["delete", "migration", "auth"]
    auto_pr_limit: 5

Key Loop Engineering Patterns

  1. Classification before execution — Always route tasks to the right tool and model before starting work. A Haiku classification pass costs pennies and prevents wasted Sonnet/Opus compute on tasks that don't need it.

  2. Iteration caps as cost controls — Both OpenHands and SWE-Agent support max_iterations. Set this based on task complexity. A simple bug fix should not need more than 20 iterations.

  3. Observation budgeting — SWE-Agent's ACI truncates command output to prevent context overflow. Configure this per project: a Python project might need 50 lines of traceback, while a TypeScript project needs less because errors are typically shorter.

  4. Patch review before merge — Neither tool should auto-merge. The loop should generate PRs that a human reviews. OpenHands has a built-in approval mode for this; SWE-Agent produces patch.diff files that you can review with any standard code review tool.

Performance on SWE-bench

SWE-bench (github.com/princeton-nlp/SWE-bench) is the standard benchmark for evaluating issue resolution agents. It consists of 2,294 real GitHub issues from 12 popular Python repositories.

Benchmark Results (SWE-bench Verified Subset)

SystemModelResolved (%)Avg. Cost per Issue
SWE-AgentGPT-4o18.3%~$1.20
SWE-AgentClaude Sonnet 422.1%~$0.90
OpenHands (CodeAct)Claude Sonnet 416.8%~$1.50
OpenHands (CodeAct)Claude Opus 419.4%~$4.50
Human baseline~30%

Claude Sonnet 4 achieves the best cost-efficiency ratio on SWE-Agent, while Opus 4 provides higher absolute resolution at a steeper cost. The human baseline of ~30% is useful context: these tools are approaching human-level performance on well-scoped issues, though they still struggle with ambiguous reports and cross-repository dependencies.

Practical Tips and Common Pitfalls

What Works

  • Specific issue titles and reproduction steps — SWE-Agent performs dramatically better when the issue includes a code snippet, error message, or reproduction script. Issues titled "it's broken" consistently fail.
  • Repository context in the system prompt — Adding 3-5 lines about the project's architecture and testing conventions to the ACI config improves resolution rates by 5-8 percentage points.
  • Starting from a clean environment — Both tools work best when the sandbox starts fresh. Don't pre-install project dependencies; let the agent install them as part of its reasoning.

What Does Not Work

  • Ambiguous issues — If a human engineer would need to ask clarifying questions, the agent will too (and will hallucinate answers instead of asking).
  • Large monorepos — SWE-Agent struggles with repositories where the relevant code spans more than 5 directories. OpenHandles handles this better due to its broader action space.
  • Issues requiring new dependencies — Both tools are conservative about adding new packages. If the fix requires pip install new-package, the agent often fails to recognize this need.

Debugging Failed Agent Sessions

Both tools produce trajectory logs that are invaluable for debugging:

# SWE-Agent trajectory analysis
python -c "
import json
with open('swe-output/trajectory.json') as f:
    traj = json.load(f)
for step in traj['steps']:
    if step['action'] == 'run_command' and 'error' in step['observation']:
        print(f'Iteration {step[\"iteration\"]}: {step[\"action_args\"]}')
        print(f'  Error: {step[\"observation\"][:200]}')
"

Look for these common failure patterns in trajectories:

PatternLikely CauseFix
Agent reads the same file 5+ timesConfused about project structureAdd architecture notes to ACI config
Agent installs wrong dependencyMisread the error messageAdd dependency hints to system prompt
Agent hits iteration cap without patchIssue is too complex or ambiguousEscalate to human or use OpenHands
Agent makes edit, doesn't run testsMissing test instructionAdd "always run tests" to ACI hints
  • Interface theory: See the Agent-Computer Interface article for the full ACI design framework
  • Commercial comparison: The Devin Architecture article compares these open-source tools against Cognition's commercial agent
  • Model selection: Apply the model tiering strategies from the Claude Models Guide to optimize costs
  • Loop fundamentals: Review What is Loop Engineering for the foundational concepts behind autonomous agent loops