* fix(webhooks): fall back to vision model for Slack/Linear image threads Re-land upstream #1626 onto the modular webhook structure. When a Slack mention or Linear issue carries images but the resolved model is text-only, fall back to a vision-capable model instead of dropping the images. Re-points default_vision_model_pair at the fork's image-capable models (Opus 4.8 default, else any supports_images model) rather than upstream's openai:/anthropic: provider filter. Refs #80, upstream #1626 * fix(slack): persist trace_message_ts so web-handoff updates the trace reply Re-land upstream #1630 onto the modular structure. The first-mention store_slack_run_mapping call did not pass trace_message_ts, so it was never persisted (nothing to preserve from on first mention) and _notify_slack_web_handoff always skipped the trace-reply update on web handoff. Pass it through and cover it with a test. Refs #80, upstream #1630 * feat(slack): include channel context in Slack prompts Re-land upstream #1633 onto the modular structure. Fetch cached Slack channel metadata once per event (_get_slack_channel_context) and thread it through the docs-plz gate, repo resolution, and process_slack_mention so prompts carry the channel name and a clearly-marked untrusted channel description. Avoids duplicate conversations.info calls. Refs #80, upstream #1633 * feat(tools): add slack_start_new_thread breakout tool Re-land upstream #1638 onto the modular structure. Adds the slack_start_new_thread tool (posts a top-level Slack message and dispatches a fresh agent run for a broken-out task via the durable dispatch_agent_run contract), wires it into the agent tool list and tools/__init__, adds prompt guidance, and excludes it from plan mode so it can't bypass the approval flow. Tool imports only live modules. Refs #80, upstream #1638 * feat(plan): notify Slack on plan approval Re-land upstream #1632 onto the modular structure. When a plan is approved via the dashboard approve endpoint, post a thread reply to the originating Slack thread noting the comment count and approver, after the follow-up run is dispatched. Slack post failures never break approval. Adapted to the fork's approve_plan (no plan_markdown read). Refs #80, upstream #1632 * feat(plan): publish plans from sandbox files Re-land upstream #1635 onto the modular structure, completing the partially-ported change so dev is internally consistent. save_plan now takes a plan_file_path, reads the agent-authored Markdown file from /workspace/plans/ (validating extension/location/UTF-8/size) and publishes it, instead of taking a plan_markdown string. Removes write_file/edit_file from PLAN_MODE_EXCLUDED_TOOLS so the agent can author the plan file, updates enter_plan_mode/reject_plan guidance and the e2e fake LLM. Skips the #1610-only update_plan hunk (not on dev). Refs #80, upstream #1635 * fix(security): SSRF-harden server-side image fetch + stop logging raw image URLs INJ-01 (high): fetch_image_block used follow_redirects=True with no per-hop revalidation and discarded the resolved-IP pin, so an attacker-authored Slack/ Linear image URL could 302-redirect the fetch to an internal host / cloud metadata endpoint (blind SSRF), and DNS-rebinding could bypass the one-shot is_url_safe check. Route image fetches through the same per-hop resolve+pin+ revalidate loop the http_request tool uses, lifted into url_safety as the shared request_with_safe_redirects. Also strip the per-host Slack/Linear bearer token on redirect so it can't be replayed to a redirect target. SC-1 (low): linear.py logged full image URLs (which can carry signed tokens) at DEBUG; multimodal logged them at INFO on every fetch. Log host-only. Sink lived in multimodal.py (unchanged by the feature work) but PR #128 widened its reach by no longer dropping images for text-only models. Fixing on the base branch so #130/#129 inherit it on rebase. Adds fetch_image_block SSRF regression tests (redirect-to-internal blocked; auth stripped on redirect). |
||
|---|---|---|
| .githooks | ||
| .github | ||
| .security-review | ||
| .vscode | ||
| agent | ||
| deploy | ||
| docs | ||
| evals/reviewer | ||
| scripts | ||
| static | ||
| tests | ||
| ui | ||
| .codespellignore | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| .nvmrc | ||
| AGENTS.md | ||
| CLAUDE.md | ||
| CUSTOMIZATION.md | ||
| default_prompt.md | ||
| Dockerfile | ||
| INSTALLATION.md | ||
| langgraph.json | ||
| LICENSE | ||
| Makefile | ||
| package.json | ||
| pyproject.toml | ||
| README.md | ||
| SECURITY.md | ||
| uv.lock | ||
Open-source framework for building your org's internal coding agent.
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_add_reaction |
React to Slack messages |
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).
Optional observability tools (server-side): Admins can connect Datadog and LangSmith from team settings (Admin → Observability credentials). When connected, the agent gains Datadog tools (via Datadog's hosted MCP server, default toolsets=core) and read-only LangSmith tools (langsmith_get_trace, langsmith_list_runs). These run in the LangGraph server process using credentials encrypted at rest — the sandbox never holds Datadog or LangSmith keys. They are loaded only for runs triggered by an authorized user (admins, plus any emails in OBSERVABILITY_AUTHORIZED_EMAILS), so a prompt-injected run from an untrusted contributor cannot reach team observability data. Use scoped, read-oriented keys regardless: observability data (logs, traces) is attacker-influenced content that can carry prompt injection, and the agent has network egress — the same residual-risk class as web_search / fetch_url.
Optional Corridor guardrails (server-side MCP): Set CORRIDOR_API_TOKEN (or CORRIDOR_MCP_TOKEN / CORRIDOR_TOKEN) to load Corridor's hosted MCP server for each agent run. Open SWE exposes only Corridor's analyzePlan tool. CORRIDOR_MCP_URL defaults to https://app.corridor.dev/api/mcp; if set explicitly, Open SWE only accepts the same HTTPS host and /api/mcp path. Tokens are sent via Authorization: Bearer ... from the LangGraph server process and are never placed in the sandbox. A legacy ?token=... URL is accepted and normalized into the header form.
4. Context Engineering — AGENTS.md + Source Context
Open SWE gathers context from two sources:
AGENTS.md— If the repo contains anAGENTS.mdfile 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. Reference templates for stack-specific conventions (AWS, SAM, CDK, EC2) live indocs/repo-conventions/.- 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/namesyntax to specify which repo to work on. The agent replies in-thread with status updates and PR links. - Linear — Comment
@opensweon any issue. The agent reacts with 👀 to acknowledge, reads the full issue context, and posts results back as comments. - GitHub — Tag
@openswein 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.
Trigger tags (Sea Haven fork): a mention is a case-insensitive substring match on the comment body — @openswe, @open-swe, @openswe-dev, or @seahaven-openswe (the deployed App slug). GitHub won't linkify @seahaven-openswe (App [bot] accounts aren't user-mentionable), but the text still fires a run.
Engineering conventions & attribution (Sea Haven fork): the main agent's system prompt is tuned to the Sea Haven engineering handbook — branch names are feature|bug|hotfix/<kebab-desc> (optional resolvable <KEY>- prefix), PR bodies use ## Summary / Validation / Tests / Notes, and commit messages follow the handbook format (≤50-char imperative subject, why over what). The PR title rule is repo-aware: when the target repo enforces a conventional-commit title (an amannn/action-semantic-pull-request workflow, a commitlint config, or a documented requirement in AGENTS.md / CONTRIBUTING.md), the agent emits a conforming type(scope): … title that reads the action's allowed types/scopes — this lets it pass gates like this repo's own PR Title Lint and upstream langchain-ai/open-swe without manual retitling; otherwise it falls back to the Sea Haven imperative style with no type: prefix. PRs that resolve a GitHub issue auto-link it in the body (Closes #<n> for full fixes, Refs #<n>/Part of #<n> for partial work, Closes owner/repo#<n> cross-repo); because the Sea Haven flow targets dev rather than the default branch, the issue closes when dev is promoted, not at dev-merge. No agent/AI attribution is added to any artifact — no Co-authored-by bot trailer, no Made by [Open SWE] footer, no "generated by an agent" notes. Commits are currently authored as the triggering user (the upstream behavior, which keeps Vercel preview deploys resolvable); flipping authorship to the bot account is tracked separately in issue #11 pending the Vercel-resolvability decision.
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
@openswein a comment to kick off a task - Instant acknowledgement — acknowledges 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
- Web dashboard — a companion app (in
ui/) for GitHub login, per-user model/profile settings, team defaults, enabled-repo and review-style management, user mappings, and an Agents chat UI
Getting Started
- Installation Guide — local dev (backend + dashboard), 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
Deployment (Sea Haven fork)
This fork runs on a managed deployment: the backend (all three graphs + the
FastAPI webapp) runs on
LangGraph Cloud / Platform,
and the ui/ dashboard deploys to Vercel. Configuration
and secrets live in the LangGraph deployment config and Vercel environment
variables. Promotion from dev to prod (main) is handled by
.github/workflows/promote-to-main.yml.
See INSTALLATION.md § 10 "Production deployment" for the full backend + dashboard setup.
The earlier self-hosted AWS stack (CDK under
infra/, an ARM64 EC2 box + nginx behind the shared ALB, and thecd-infra/build-artifactsrelease pipelines) was decommissioned in favor of the managed deployment above.
License
MIT