Open SWE: Build Your Own Internal Coding Agent in 10 Minutes

Today LangChain dropped Open SWE β€” an open-source framework that distills how elite engineering orgs (Stripe, Ramp, Coinbase) are building internal coding agents. This isn't a toy. These are production systems that spin up cloud sandboxes, read Linear issues, write code, and open PRs β€” all from a Slack mention.

Let me break it down and show you how to customize one.


The Big Idea

Three of the best engineering orgs in the world all independently built internal coding agents. And they all converged on the same architecture:

  • Isolated cloud sandboxes β€” every task gets its own Linux box, full permissions, zero blast radius to prod
  • Curated toolsets β€” Stripe has ~500 tools, but they're curated, not accumulated
  • Slack-first invocation β€” meet engineers where they already live
  • Rich context at startup β€” read the Linear issue/Slack thread before the agent starts working
  • Subagent orchestration β€” decompose complex work into child agents with isolated context

Open SWE packages all of that into an MIT-licensed, customizable framework built on LangGraph and Deep Agents.


10-Minute Tour

1. The Core Agent

The heart of Open SWE is a single create_deep_agent call:

from deepagents import create_deep_agent
from open_swe.tools import (
    http_request,
    fetch_url,
    commit_and_open_pr,
    linear_comment,
    slack_thread_reply,
)
from open_swe.middleware import (
    ToolErrorMiddleware,
    check_message_queue_before_model,
    open_pr_if_needed,
)

agent = create_deep_agent(
    model="anthropic:claude-opus-4-6",
    system_prompt=construct_system_prompt(repo_dir, agents_md_content),
    tools=[
        http_request,
        fetch_url,
        commit_and_open_pr,
        linear_comment,
        slack_thread_reply,
    ],
    backend=sandbox_backend,  # Modal, Daytona, Runloop, or LangSmith
    middleware=[
        ToolErrorMiddleware(),
        check_message_queue_before_model,
        open_pr_if_needed,
    ],
)

Deep Agents handles the plumbing: file-based memory to avoid context overflow, built-in write_todos for planning, and a task tool for spawning child agents. You focus on your org's specific tools and context.

2. Pick a Sandbox

Every task runs in an isolated cloud sandbox β€” clone the repo in, let the agent run, contain the blast radius. Open SWE supports four providers out of the box:

# Modal
from open_swe.sandboxes.modal import ModalSandboxBackend
sandbox_backend = ModalSandboxBackend()

# Daytona
from open_swe.sandboxes.daytona import DaytonaSandboxBackend
sandbox_backend = DaytonaSandboxBackend()

# LangSmith (great for debugging β€” full traces)
from open_swe.sandboxes.langsmith import LangSmithSandboxBackend
sandbox_backend = LangSmithSandboxBackend()

Each conversation thread gets a persistent sandbox β€” follow-up messages reuse it. Sandboxes auto-recreate if they die. Multiple tasks run in parallel, each isolated.

3. Add Your Own Tools

This is where you make it yours. Need to hit your internal deployment API? Integrate with your monitoring stack? Add a tool:

from langchain_core.tools import tool

@tool
def deploy_to_staging(branch: str, service: str) -> str:
    """Deploy a branch to the staging environment."""
    response = requests.post(
        "https://deploy.internal/api/staging",
        json={"branch": branch, "service": service},
        headers={"Authorization": f"Bearer {DEPLOY_TOKEN}"},
    )
    return f"Deployed {branch} to staging: {response.json()['url']}"

@tool
def run_integration_tests(service: str) -> str:
    """Run integration tests for a service and return results."""
    result = subprocess.run(
        ["pytest", f"tests/integration/{service}/", "-v", "--tb=short"],
        capture_output=True, text=True, cwd=REPO_DIR
    )
    return result.stdout + result.stderr

# Add to your agent
agent = create_deep_agent(
    ...
    tools=[
        *default_tools,
        deploy_to_staging,
        run_integration_tests,
    ],
)

Stripe's lesson: curate intentionally. More tools = more surface area for hallucinations and errors. Start small, add only what you need.

4. The AGENTS.md Pattern

Drop an AGENTS.md at your repo root. Open SWE reads it from the sandbox and injects it into every agent run β€” this is your repo-level rulebook:

# AGENTS.md

## Architecture
- This is a SvelteKit 5 app. Use runes ($state, $derived, $effect), not stores.
- Database queries go through src/lib/db.ts β€” never import drizzle directly in components.
- Always run `npm run typecheck` before committing.

## Testing
- Unit tests live in src/__tests__/. Use vitest.
- Run `npm test` before every PR. Zero tolerance for test failures.
- Integration tests in tests/integration/ require a running Neon branch.

## Conventions
- Components are PascalCase. Files are kebab-case.
- Prefer +page.server.ts for data loading. Use +page.ts only for client-side fetches.
- Commit format: feat(scope):, fix(scope):, chore(scope):

No extra config needed β€” just a file at the root of your repo. Every agent run respects your conventions automatically.

5. Middleware for Reliability

The middleware system is how Open SWE handles the "what if the LLM forgets to open a PR" problem β€” deterministic safety nets around the agentic loop:

from deepagents.middleware import Middleware
from open_swe.github import commit_and_push

class RequireTestsBeforePR(Middleware):
    """Ensure tests pass before the agent can open a PR."""
    
    async def after_tool_call(self, tool_name: str, result: str, context):
        if tool_name == "commit_and_open_pr":
            # Intercept PR creation β€” run tests first
            test_result = await context.sandbox.run("npm test")
            if test_result.exit_code != 0:
                raise ToolError(
                    f"Tests failed. Fix before opening PR:\n{test_result.stdout}"
                )
        return result

# open_pr_if_needed is a built-in safety net:
# if the agent finishes without opening a PR, middleware does it automatically
agent = create_deep_agent(
    ...
    middleware=[
        ToolErrorMiddleware(),
        RequireTestsBeforePR(),       # your custom gate
        check_message_queue_before_model,
        open_pr_if_needed,            # built-in backstop
    ],
)

The separation matters: agentic (model-driven) + deterministic (middleware-driven). The model handles the creative work; middleware handles the critical steps that must happen.


How Invocation Works

Trigger it from where you already work:

Slack:

@openswe repo:myorg/myapp fix the race condition in the payment processor

Linear:

@openswe please implement this

β†’ Agent reads the full issue, reacts πŸ‘€, writes code, opens a PR, comments with the link.

GitHub PR:

@openswe address the review feedback on lines 45-67

β†’ Agent pushes fixes to the same branch.

Each invocation creates a deterministic thread ID β€” follow-up messages route to the same running agent.


How It Compares

Open SWEStripe MinionsRamp InspectCoinbase Cloudbot
HarnessDeep Agents/LangGraphForked (Goose)Composed (OpenCode)Built from scratch
SandboxModal, Daytona, RunloopAWS EC2 devboxesModal containersIn-house
Tools~15, curated~500, curatedOpenCode SDKMCPs + Skills
InvocationSlack, Linear, GitHubSlack + buttonsSlack + web + ChromeSlack-native
ValidationPrompt + PR safety net3-layer + retryVisual DOM verificationAgent councils

The core patterns are identical. The differences are org-specific integrations β€” exactly what you'd customize Open SWE for.


Why This Matters

A year ago, building a coding agent that could actually ship production code required significant infrastructure work. Now the patterns are proven, the open-source tooling exists, and the entry cost is a weekend project.

The AGENTS.md pattern is particularly underrated β€” it's the simplest form of "context engineering." Drop a file in your repo, encode your conventions, and every agent run automatically respects them. No extra config, no special integration.

I'm going to wire this up to my own projects. The idea of mentioning @openswe on a Linear issue and getting a draft PR back is exactly the workflow I want.


Get Started

git clone https://github.com/langchain-ai/open-swe
cd open-swe
# Follow INSTALLATION.md β€” GitHub App, sandbox provider, Slack/Linear setup

Tags

aiagentslangchaincoding-agentsopen-source