An Open-Source Asynchronous Coding Agent
Find a file
Johannes du Plessis 378b95266e
feat: implement reviewer findings, publish_review, and watch mode (#1253)
* feat: implement reviewer findings, publish_review, and watch mode

Build out the reviewer agent end-to-end against the design in
REVIEWER_DESIGN.md:

- Findings as first-class state on the reviewer thread metadata
  (`agent/reviewer_findings.py`): Finding TypedDict with start_line/end_line
  ranges, suggestion text for ```suggestion blocks, github_review_comment_id
  for cross-run reconciliation, diff_hunk for UI rendering. Thread-level
  metadata gets `kind=reviewer`, `pr`, `last_reviewed_sha`, `watch` so a
  future frontend can list reviewer threads via the langgraph SDK.
- Diff utilities (`agent/reviewer_diff.py`): parse_unified_diff,
  compute_diff_line_set for in-diff validation, extract_diff_hunk for
  caching the hunk on a Finding, compute_diff_in_sandbox for SHA-to-SHA
  diffs against the prepped repo.
- Tools: `add_finding` (validates against the diff line set so out-of-diff
  ranges fail at creation, not at GitHub-publish), `update_finding`,
  `list_findings`, `publish_review`. The reviewer agent's tool list is
  swapped from `[]` (direct shell `gh api` calls) to these four.
- Publish path (`agent/reviewer_publish.py` + `agent/tools/publish_review.py`):
  one POST /reviews call with body + inline comments + ```suggestion blocks,
  per-comment IDs stored back on findings, GraphQL `resolveReviewThread`
  fired for findings transitioning open->resolved on a re-review.
- Reviewer graph: deterministic clone-or-fetch + checkout in the factory
  before the agent's first model call (warm- and cold-path symmetric);
  computed diff and in-diff line set passed via runnable config; system
  prompt rewritten for the single-evolving-findings model, severity ladder,
  in-diff-only discipline, and watch-mode reconciliation flow.
- Watch mode in webapp.py: `push` event + `pull_request` closed/reopened
  added to supported events. New `process_github_push_event` resolves the
  open PR for the pushed branch, gates on the reviewer thread's `watch`
  flag, builds a re-review configurable, and triggers a run on the same
  canonical thread. `process_github_pr_close` toggles watch on
  closed/reopened. `set_reviewer_thread_metadata` is called on first
  review to install `kind=reviewer` + PR identity + watch=True.
- Eval harness: target.py now extracts `add_finding` calls (mapped to the
  legacy {file, line, body, severity} shape the judge expects) and passes
  the right configurable so the prep step has base/head SHAs.
- Tests: new unit suites for findings helpers, diff parsing, finding tools,
  publish rendering + GraphQL resolve, and watch-mode webhook handlers
  (push triggers re-review only when watching, idempotent on unchanged
  head SHA, PR close disables watch). Updated existing reviewer-webhook
  tests to mock `set_reviewer_thread_metadata`.
- REVIEWER_EVAL_PLAN.md removed per user request; folded relevant context
  into REVIEWER_DESIGN.md.

* fix(reviewer): correct git diff flags, scope, dedup, and review-comments URL

Address PR #1253 review findings:

- compute_diff_in_sandbox dropped the invalid `--no-prefix=false` flag
  (`option no-prefix takes no value` — every prep run was failing
  silently and the agent saw an empty diff).
- compute_diff_in_sandbox grew a `merge_base` flag. First-review path
  now uses three-dot `base...head` (the merge-base diff GitHub renders
  on Files-changed) so we don't pick up changes that landed on the base
  branch after the PR diverged. Re-review delta keeps two-dot
  `last_reviewed_sha..head` since that's exactly the new commits.
- publish_review skips findings that already carry
  `github_review_comment_id`. Without this, watched re-reviews
  re-posted every previously surfaced finding, and only the most-recent
  duplicate's id would later resolve when the issue got addressed.
- fetch_review_comments URL now includes `{pull_number}` —
  `/repos/{owner}/{repo}/pulls/{pr_number}/reviews/{review_id}/comments`
  is the canonical endpoint; the old form 404s, so comment ids were
  never stored and watch-mode resolution couldn't run.

Three new tests cover: three-dot vs two-dot wiring, no `--no-prefix`
flag in the executed command, and that publish_review does not re-post
findings whose `github_review_comment_id` is set.

* fix(reviewer): default publish cap from 15 to 4

A clean PR with one critical issue padded out by three lower-severity
findings is fine; fifteen is review spam. The agent can override per
call when a PR genuinely warrants more.
2026-05-07 14:48:43 -07:00
.github chore(deps): bump astral-sh/setup-uv in the minor-and-patch group (#1232) 2026-05-01 18:00:53 -07:00
.vscode Brace/07 16/fixes (#431) 2025-07-16 13:17:35 -07:00
agent feat: implement reviewer findings, publish_review, and watch mode (#1253) 2026-05-07 14:48:43 -07:00
evals/reviewer feat: implement reviewer findings, publish_review, and watch mode (#1253) 2026-05-07 14:48:43 -07:00
scripts feat: move github workflows to gh cli (#1238) 2026-05-04 18:03:53 -07:00
static fix: Add back logo to readme (#1068) 2026-03-17 10:41:41 -07:00
tests feat: implement reviewer findings, publish_review, and watch mode (#1253) 2026-05-07 14:48:43 -07:00
.codespellignore init commit 2025-05-21 14:47:56 -07:00
.dockerignore feat: move github workflows to gh cli (#1238) 2026-05-04 18:03:53 -07:00
.gitignore feat(open-swe): Default to GPT-5.5 medium reasoning (#1224) 2026-04-28 15:03:21 -07:00
AGENTS.md feat: move github workflows to gh cli (#1238) 2026-05-04 18:03:53 -07:00
CLAUDE.md feat: move github workflows to gh cli (#1238) 2026-05-04 18:03:53 -07:00
CUSTOMIZATION.md feat: move github workflows to gh cli (#1238) 2026-05-04 18:03:53 -07:00
default_prompt.md feat: add configurable default prompt file for org-level agent instructions [close OPE-36] (#1187) 2026-04-15 15:18:14 -07:00
Dockerfile feat: move github workflows to gh cli (#1238) 2026-05-04 18:03:53 -07:00
INSTALLATION.md feat: move github workflows to gh cli (#1238) 2026-05-04 18:03:53 -07:00
langgraph.json feat: add reviewer graph + eval target wiring (#1241) 2026-05-06 10:15:58 -07:00
LICENSE feat: Monorepo (#22) 2025-05-26 13:02:51 -07:00
Makefile feat: add reviewer graph + eval target wiring (#1241) 2026-05-06 10:15:58 -07:00
pyproject.toml chore: bump deepagents to 0.5.7 (#1240) 2026-05-05 12:02:08 -07:00
README.md feat: move github workflows to gh cli (#1238) 2026-05-04 18:03:53 -07:00
REVIEWER_DESIGN.md feat: implement reviewer findings, publish_review, and watch mode (#1253) 2026-05-07 14:48:43 -07:00
SECURITY.md fix: Security stuff (#441) 2025-07-17 12:19:20 -07:00
uv.lock chore: bump deepagents to 0.5.7 (#1240) 2026-05-05 12:02:08 -07:00

Open-source framework for building your org's internal coding agent.

License GitHub Stars Built on LangGraph Built on Deep Agents Twitter / X

Elite engineering orgs like Stripe, Ramp, and Coinbase are building their own internal coding agents — Slackbots, CLIs, and web apps that meet engineers where they already work. These agents are connected to internal systems with the right context, permissioning, and safety boundaries to operate with minimal human oversight.

Open SWE is the open-source version of this pattern. Built on LangGraph and Deep Agents, it gives you the same architecture those companies built internally: cloud sandboxes, Slack and Linear invocation, subagent orchestration, and automatic PR creation — ready to customize for your own codebase and workflows.

Note

💬 Read the announcement blog post here


Architecture

Open SWE makes the same core architectural decisions as the best internal coding agents. Here's how it maps to the patterns described in this overview of Stripe's Minions, Ramp's Inspect, and Coinbase's Cloudbot:

1. Agent Harness — Composed on Deep Agents

Rather than forking an existing agent or building from scratch, Open SWE composes on the Deep Agents framework — similar to how Ramp built on top of OpenCode. This gives you an upgrade path (pull in upstream improvements) while letting you customize the orchestration, tools, and middleware for your org.

create_deep_agent(
    model="openai:gpt-5.5",
    system_prompt=construct_system_prompt(...),
    tools=[http_request, fetch_url, linear_comment, slack_thread_reply],
    backend=sandbox_backend,
    middleware=[ToolErrorMiddleware(), check_message_queue_before_model, ...],
)

2. Sandbox — Isolated Cloud Environments

Every task runs in its own isolated cloud sandbox — a remote Linux environment with full shell access. The repo is cloned in, the agent gets full permissions, and the blast radius of any mistake is fully contained. No production access, no confirmation prompts.

Open SWE supports multiple sandbox providers out of the box — Modal, Daytona, Runloop, and LangSmith — and you can plug in your own. See the Customization Guide for details.

This follows the principle all three companies converge on: isolate first, then give full permissions inside the boundary.

  • Each thread gets a persistent sandbox (reused across follow-up messages)
  • Sandboxes auto-recreate if they become unreachable
  • Multiple tasks run in parallel — each in its own sandbox, no queuing

3. Tools — Curated, Not Accumulated

Stripe's key insight: tool curation matters more than tool quantity. Open SWE follows this principle with a small, focused toolset:

Tool Purpose
execute Shell commands in the sandbox
fetch_url Fetch web pages as markdown
http_request API calls (GET, POST, etc.)
linear_comment Post updates to Linear tickets
slack_thread_reply Reply in Slack threads

GitHub operations are performed with GH_TOKEN=dummy gh inside the sandbox, backed by the LangSmith proxy. Plus the built-in Deep Agents tools: read_file, write_file, edit_file, ls, glob, grep, write_todos, and task (subagent spawning).

4. Context Engineering — AGENTS.md + Source Context

Open SWE gathers context from two sources:

  • AGENTS.md — If the repo contains an AGENTS.md file at the root, it's read from the sandbox and injected into the system prompt. This is your repo-level equivalent of Stripe's rule files: encoding conventions, testing requirements, and architectural decisions that every agent run should follow.
  • Source context — The full Linear issue (title, description, comments) or Slack thread history is assembled and passed to the agent, so it starts with rich context rather than discovering everything through tool calls.

5. Orchestration — Subagents + Middleware

Open SWE's orchestration has two layers:

Subagents: The Deep Agents framework natively supports spawning child agents via the task tool. The main agent can fan out independent subtasks to isolated subagents — each with its own middleware stack, todo list, and file operations. This is similar to Ramp's child sessions for parallel work.

Middleware: Deterministic middleware hooks run around the agent loop:

  • check_message_queue_before_model — Injects follow-up messages (Linear comments or Slack messages that arrive mid-run) before the next model call. You can message the agent while it's working and it'll pick up your input at its next step.
  • notify_step_limit_reached — After-agent hook that posts a Slack reply when the agent hits the model-call limit, so users get a clear signal instead of silence.
  • ToolErrorMiddleware — Catches and handles tool errors gracefully.

6. Invocation — Slack, Linear, and GitHub

All three companies in the article converge on Slack as the primary invocation surface. Open SWE does the same:

  • Slack — Mention the bot in any thread. Supports repo:owner/name syntax to specify which repo to work on. The agent replies in-thread with status updates and PR links.
  • Linear — Comment @openswe on any issue. The agent reads the full issue context, reacts with 👀 to acknowledge, and posts results back as comments.
  • GitHub — Tag @openswe in PR comments on agent-created PRs to have it address review feedback and push fixes to the same branch.

Each invocation creates a deterministic thread ID, so follow-up messages on the same issue or thread route to the same running agent.

7. Validation — Prompt-Driven

The agent is instructed to run linters, formatters, and tests before committing, and is responsible end-to-end for committing, pushing, opening/updating the draft PR, and replying in the source channel. This is an area where you can extend Open SWE for your org: add deterministic CI checks, visual verification, or review gates as additional middleware. See the Customization Guide for how.


Comparison

Decision Open SWE Stripe (Minions) Ramp (Inspect) Coinbase (Cloudbot)
Harness Composed (Deep Agents/LangGraph) Forked (Goose) Composed (OpenCode) Built from scratch
Sandbox Pluggable (Modal, Daytona, Runloop, etc.) AWS EC2 devboxes (pre-warmed) Modal containers (pre-warmed) In-house
Tools ~15, curated ~500, curated per-agent OpenCode SDK + extensions MCPs + custom Skills
Context AGENTS.md + issue/thread Rule files + pre-hydration OpenCode built-in Linear-first + MCPs
Orchestration Subagents + middleware Blueprints (deterministic + agentic) Sessions + child sessions Three modes
Invocation Slack, Linear, GitHub Slack + embedded buttons Slack + web + Chrome extension Slack-native
Validation Prompt-driven 3-layer (local + CI + 1 retry) Visual DOM verification Agent councils + auto-merge

Features

  • Trigger from Linear, Slack, or GitHub — mention @openswe in a comment to kick off a task
  • Instant acknowledgement — reacts with 👀 the moment it picks up your message
  • Message it while it's running — send follow-up messages mid-task and it'll pick them up before its next step
  • Run multiple tasks in parallel — each task runs in its own isolated cloud sandbox
  • GitHub OAuth built-in — authenticates with your GitHub account automatically
  • Opens PRs automatically — commits changes and opens a draft PR when done, linked back to your ticket
  • Subagent support — the agent can spawn child agents for parallel subtasks

Getting Started

  • Installation Guide — GitHub App creation, LangSmith, Linear/Slack/GitHub triggers, and production deployment
  • Customization Guide — swap the sandbox, model, tools, triggers, system prompt, and middleware for your org

License

MIT