feat: Add Max Mode Labels with Claude Opus 4 Support (#577)

* Apply patch

* Apply patch

* Apply patch

* Apply patch

* Apply patch

* Apply patch

* Apply patch

* Apply patch

* Apply patch

* Apply patch

* cr

---------

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
Co-authored-by: bracesproul <braceasproul@gmail.com>
This commit is contained in:
open-swe[bot] 2025-07-28 16:33:12 -07:00 • committed by GitHub
parent d61965ce6b
commit 2c774ee517
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 64 additions and 10 deletions

View file

@ -34,8 +34,9 @@ Open SWE is an open-source cloud-based coding agent built with [LangGraph](https
Open SWE can be used in multiple ways: Open SWE can be used in multiple ways:
- 🖥️ **From the UI**. You can create, manage and execute Open SWE tasks from the [web application](https://swe.langchain.com). See the ['From the UI' page](https://docs.langchain.com/labs/swe/usage/ui) in the docs for more information. - 🖥️ **From the UI**. You can create, manage and execute Open SWE tasks from the [web application](https://swe.langchain.com). See the ['From the UI' page](https://docs.langchain.com/labs/swe/usage/ui) in the docs for more information.
- 📝 **From GitHub**. You can start Open SWE tasks directly from GitHub issues simply by adding a label `open-swe`, or `open-swe-auto` (adding `-auto` will cause Open SWE to automatically accept the plan, requiring no intervention from you). See the ['From GitHub' page](https://docs.langchain.com/labs/swe/usage/github) in the docs for more information. - 📝 **From GitHub**. You can start Open SWE tasks directly from GitHub issues simply by adding a label `open-swe`, or `open-swe-auto` (adding `-auto` will cause Open SWE to automatically accept the plan, requiring no intervention from you). For enhanced performance on complex tasks, use `open-swe-max` or `open-swe-max-auto` labels which utilize Claude Opus 4 for both planning and programming. See the ['From GitHub' page](https://docs.langchain.com/labs/swe/usage/github) in the docs for more information.
# Documentation # Documentation
To get started using Open SWE locally, see the [documentation here](https://docs.langchain.com/labs/swe/). To get started using Open SWE locally, see the [documentation here](https://docs.langchain.com/labs/swe/).

View file

@ -13,7 +13,7 @@ Open SWE monitors GitHub issues for specific labels that trigger automated runs.
### Label Types ### Label Types
Open SWE supports two types of labels that control how the agent operates: Open SWE supports three types of labels that control how the agent operates:
**Manual Mode (`open-swe`)** **Manual Mode (`open-swe`)**
@ -27,10 +27,19 @@ Open SWE supports two types of labels that control how the agent operates:
- Provides faster turnaround for straightforward requests - Provides faster turnaround for straightforward requests
- Best for simple changes or when you trust the agent to proceed autonomously - Best for simple changes or when you trust the agent to proceed autonomously
**Max Mode (`open-swe-max` and `open-swe-max-auto`)**
- Uses Claude Opus 4 for both planning and programming tasks
- Provides enhanced performance and reasoning capabilities for complex problems
- `open-swe-max`: Requires manual plan approval with premium model performance
- `open-swe-max-auto`: Combines automatic execution with premium model capabilities
- Ideal for challenging tasks that benefit from the most advanced AI reasoning
<Note> <Note>
In development environments, the labels are `open-swe-dev` and In development environments, the labels are `open-swe-dev`,
`open-swe-auto-dev` respectively. The system automatically uses the `open-swe-auto-dev`, `open-swe-max-dev`, and `open-swe-max-auto-dev`
appropriate labels based on the `NODE_ENV` environment variable. respectively. The system automatically uses the appropriate labels based on
the `NODE_ENV` environment variable.
</Note> </Note>
## Automatic Run Creation ## Automatic Run Creation

View file

@ -18,6 +18,8 @@ import { HumanMessage } from "@langchain/core/messages";
import { import {
getOpenSWEAutoAcceptLabel, getOpenSWEAutoAcceptLabel,
getOpenSWELabel, getOpenSWELabel,
getOpenSWEMaxLabel,
getOpenSWEMaxAutoAcceptLabel,
} from "../../utils/github/label.js"; } from "../../utils/github/label.js";
import { ManagerGraphUpdate } from "@open-swe/shared/open-swe/manager/types"; import { ManagerGraphUpdate } from "@open-swe/shared/open-swe/manager/types";
import { RequestSource } from "../../constants.js"; import { RequestSource } from "../../constants.js";
@ -92,19 +94,31 @@ webhooks.on("issues.labeled", async ({ payload }) => {
if (!process.env.SECRETS_ENCRYPTION_KEY) { if (!process.env.SECRETS_ENCRYPTION_KEY) {
throw new Error("SECRETS_ENCRYPTION_KEY environment variable is required"); throw new Error("SECRETS_ENCRYPTION_KEY environment variable is required");
} }
const validOpenSWELabels = [getOpenSWELabel(), getOpenSWEAutoAcceptLabel()]; const validOpenSWELabels = [
getOpenSWELabel(),
getOpenSWEAutoAcceptLabel(),
getOpenSWEMaxLabel(),
getOpenSWEMaxAutoAcceptLabel(),
];
if ( if (
!payload.label?.name || !payload.label?.name ||
!validOpenSWELabels.some((l) => l === payload.label?.name) !validOpenSWELabels.some((l) => l === payload.label?.name)
) { ) {
return; return;
} }
const isAutoAcceptLabel = payload.label.name === getOpenSWEAutoAcceptLabel(); const isAutoAcceptLabel =
payload.label.name === getOpenSWEAutoAcceptLabel() ||
payload.label.name === getOpenSWEMaxAutoAcceptLabel();
const isMaxLabel =
payload.label.name === getOpenSWEMaxLabel() ||
payload.label.name === getOpenSWEMaxAutoAcceptLabel();
logger.info( logger.info(
`'${payload.label.name}' label added to issue #${payload.issue.number}`, `'${payload.label.name}' label added to issue #${payload.issue.number}`,
{ {
isAutoAcceptLabel, isAutoAcceptLabel,
isMaxLabel,
}, },
); );
@ -171,11 +185,21 @@ webhooks.on("issues.labeled", async ({ payload }) => {
}, },
autoAcceptPlan: isAutoAcceptLabel, autoAcceptPlan: isAutoAcceptLabel,
}; };
// Create config object with Claude Opus 4 model configuration for max labels
const config: Record<string, any> = {
recursion_limit: 400,
};
if (isMaxLabel) {
config.configurable = {
plannerModelName: "anthropic:claude-opus-4-0",
programmerModelName: "anthropic:claude-opus-4-0",
};
}
const run = await langGraphClient.runs.create(threadId, MANAGER_GRAPH_ID, { const run = await langGraphClient.runs.create(threadId, MANAGER_GRAPH_ID, {
input: runInput, input: runInput,
config: { config,
recursion_limit: 400,
},
ifNotExists: "create", ifNotExists: "create",
streamResumable: true, streamResumable: true,
streamMode: ["values", "messages-tuple", "custom"], streamMode: ["values", "messages-tuple", "custom"],

View file

@ -15,3 +15,23 @@ export function getOpenSWEAutoAcceptLabel():
? "open-swe-auto" ? "open-swe-auto"
: "open-swe-auto-dev"; : "open-swe-auto-dev";
} }
/**
* @returns "open-swe-max" or "open-swe-max-dev" based on the NODE_ENV.
*/
export function getOpenSWEMaxLabel(): "open-swe-max" | "open-swe-max-dev" {
return process.env.NODE_ENV === "production"
? "open-swe-max"
: "open-swe-max-dev";
}
/**
* @returns "open-swe-max-auto" or "open-swe-max-auto-dev" based on the NODE_ENV.
*/
export function getOpenSWEMaxAutoAcceptLabel():
| "open-swe-max-auto"
| "open-swe-max-auto-dev" {
return process.env.NODE_ENV === "production"
? "open-swe-max-auto"
: "open-swe-max-auto-dev";
}