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 Choice | Raw Bash (Bad ACI) | Good ACI | Impact |
|---|---|---|---|
| Command output | Full 500-line stdout | Truncated + file path hints | -15% token waste |
| Error signals | Buried in text | Extracted and highlighted | +8% fix rate |
| File editing | sed / echo pipelines | Dedicated edit_file action | +12% accuracy |
| Navigation | cd, ls, pwd | Structured list_files, open_file | +5% task completion |
| Observation format | Raw terminal escape codes | Clean 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:
- Safety — the agent cannot modify the host system. A misconfigured
rm -rf /only destroys the ephemeral container. - Reproducibility — each session starts from the same base image, making failures deterministic and debuggable.
- 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:
| Category | Pre-installed Tools |
|---|---|
| Languages | Python 3.11, Node.js 20, Rust, Go, Java 17 |
| Package managers | pip, npm, cargo, go modules, gradle |
| Build tools | gcc, g++, make, cmake |
| Version control | git, gh (GitHub CLI) |
| Browsers | Chromium (for web-based tasks) |
| Editors | vim, 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:
| Mode | Description | When to Use |
|---|---|---|
| Autonomous | Agent runs without human input | Well-scoped tasks with clear success criteria |
| Suggest | Agent proposes actions, human approves | Safety-critical code changes |
| Chat | Human guides agent via natural language | Exploratory 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 Complexity | Model | Max Iterations | Est. Cost per Task |
|---|---|---|---|
| Bug fix (multi-file) | Claude Sonnet 4 | 25 | ~$0.80 |
| Feature addition | Claude Sonnet 4 | 20 | ~$0.60 |
| Dependency migration | Claude Haiku 4.5 | 15 | ~$0.05 |
| Test writing | Claude Haiku 4.5 | 10 | ~$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:
| Action | Arguments | Purpose |
|---|---|---|
open_file | path, line_range | Read file contents (with line numbers) |
edit_file | path, old, new | Precise string replacement |
search_dir | pattern, path | Grep for patterns across files |
run_command | command | Execute shell command (output truncated) |
submit_patch | — | Signal 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
| Dimension | OpenHands | SWE-Agent |
|---|---|---|
| Scope | Full development environment | GitHub Issue → Patch only |
| Interface | Browser-based Agent Canvas | CLI + headless |
| Isolation | Docker sandbox (mandatory) | Docker sandbox (optional) |
| Multi-task | Native parallel execution | Single-task per invocation |
| LM model | Pluggable (Claude, GPT, Gemini, local) | Pluggable (Claude, GPT, Gemini, local) |
| Customization | Python API + config | YAML ACI config |
| Best for | Exploratory development, multi-step features | Reproducible issue resolution at scale |
| GitHub stars | 40K+ | 20K+ |
| License | MIT | MIT |
| Maintainer | All-Hands-AI | Princeton 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
-
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.
-
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. -
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.
-
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.difffiles 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)
| System | Model | Resolved (%) | Avg. Cost per Issue |
|---|---|---|---|
| SWE-Agent | GPT-4o | 18.3% | ~$1.20 |
| SWE-Agent | Claude Sonnet 4 | 22.1% | ~$0.90 |
| OpenHands (CodeAct) | Claude Sonnet 4 | 16.8% | ~$1.50 |
| OpenHands (CodeAct) | Claude Opus 4 | 19.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:
| Pattern | Likely Cause | Fix |
|---|---|---|
| Agent reads the same file 5+ times | Confused about project structure | Add architecture notes to ACI config |
| Agent installs wrong dependency | Misread the error message | Add dependency hints to system prompt |
| Agent hits iteration cap without patch | Issue is too complex or ambiguous | Escalate to human or use OpenHands |
| Agent makes edit, doesn't run tests | Missing test instruction | Add "always run tests" to ACI hints |
Related Resources
- 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