From bb76c1f52a7ec851b9e8835215b22cd361ab31e9 Mon Sep 17 00:00:00 2001 From: enyst Date: Mon, 24 Nov 2025 18:27:02 +0000 Subject: [PATCH 1/6] docs(sdk): document GPT-5.1 ApplyPatch example Co-authored-by: openhands --- sdk/guides/agent-apply-patch-gpt5-1.mdx | 153 ++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 sdk/guides/agent-apply-patch-gpt5-1.mdx diff --git a/sdk/guides/agent-apply-patch-gpt5-1.mdx b/sdk/guides/agent-apply-patch-gpt5-1.mdx new file mode 100644 index 00000000..fa79700c --- /dev/null +++ b/sdk/guides/agent-apply-patch-gpt5-1.mdx @@ -0,0 +1,153 @@ +--- +title: ApplyPatch with GPT-5.1 +description: Use the GPT-5.1 apply_patch tool format to perform rich multi-file edits via the ApplyPatch tool. +--- + + +This example is available on GitHub: [examples/01_standalone_sdk/28_apply_patch_with_gpt5_1.py](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/28_apply_patch_with_gpt5_1.py) + + +This guide shows how to use the `ApplyPatch` tool with GPT-5.1 models using the `apply_patch` text format introduced in the OpenAI cookbook. The tool lets the model propose unified patches that can: + +- Create new files +- Apply multi-hunk edits to a single file +- Touch multiple files in a single patch +- Mix add / update / delete operations safely + +The SDK wires this up as a normal tool, so you can run it inside an `Agent` and `Conversation` like any other tool. + +## Example + +```python icon="python" expandable examples/01_standalone_sdk/28_apply_patch_with_gpt5_1.py +"""Example: Using ApplyPatch tool with GPT-5.1 models via direct OpenAI API. + +This demonstrates adding the ApplyPatch tool to the agent and guiding the +model through a richer sequence of file operations using 'apply_patch' text: + +- Create multiple files (FACTS.txt, NOTES.md) +- Apply multi-hunk edits to a single file +- Apply a single patch that touches multiple files +- Mix add / update / delete operations in one patch + +Notes: +- Works with any GPT-5.1 family model (names start with "gpt-5.1"). +- Uses direct OpenAI API through LiteLLM's LLM wrapper with no base_url. +- Requires OPENAI_API_KEY in the environment (or LLM_API_KEY fallback). +""" + +from __future__ import annotations + +import os + +from pydantic import SecretStr + +from openhands.sdk import LLM, Agent, Conversation, get_logger +from openhands.sdk.tool import Tool +from openhands.tools.apply_patch import ApplyPatchTool +from openhands.tools.task_tracker import TaskTrackerTool + +# from openhands.tools.preset.default import register_default_tools +from openhands.tools.terminal import TerminalTool + + +logger = get_logger(__name__) + +api_key = os.getenv("OPENAI_API_KEY") or os.getenv("LLM_API_KEY") +assert api_key, "Set OPENAI_API_KEY (or LLM_API_KEY) in your environment." + +# Choose a GPT-5.1 model; mini is cost-effective for examples +default_model = "openai/gpt-5.1-codex-mini" +model = os.getenv("LLM_MODEL", default_model) +assert model.startswith("openai/gpt-5.1"), "Model must be an openai gpt-5.1 variant" + +llm = LLM( + model=model, + api_key=SecretStr(api_key), + native_tool_calling=True, # enable native tool calling (Responses API) + reasoning_summary=None, # avoid OpenAI org verification requirement + log_completions=True, # enable telemetry to log input/output payloads +) + +# Explicitly register tool classes so Tool(name=...) can resolve +# They self-register into the global registry on import +_ = (TerminalTool, TaskTrackerTool, ApplyPatchTool) + +agent = Agent( + llm=llm, + tools=[ + Tool(name="terminal"), + Tool(name="task_tracker"), + Tool(name="apply_patch"), + ], + system_prompt_kwargs={"cli_mode": True}, +) + +conversation = Conversation(agent=agent, workspace=os.getcwd()) + +# Compose instructions guiding the model to exercise richer ApplyPatch behavior. +prompt = ( + "You have access to an apply_patch tool that edits files using unified patches. " + "Use it to perform the following sequence of operations in as few patches as " + "reasonable, while keeping each patch valid and focused:\n\n" + "1) Create two files:\n" + " - FACTS.txt containing exactly two lines:\n" + " OpenHands SDK integrates tools.\n" + " ApplyPatch can edit multiple files.\n" + " - NOTES.md containing exactly three lines:\n" + " # Notes\n" + " - Initial point A\n" + " - Initial point B\n\n" + "2) Apply a multi-hunk update to NOTES.md in a single *** Update File block:\n" + " - Change the text 'Initial point A' to 'Updated point A'.\n" + " - Append a new bullet '- Added via multi-hunk patch.' after " + "'Initial point B'.\n\n" + "3) Apply a single patch that updates BOTH FACTS.txt and NOTES.md at once:\n" + " - In FACTS.txt, append a third line: 'Multi-file patches are supported.'.\n" + " - In NOTES.md, append a final line: 'Summary: multi-file patch applied.'.\n\n" + "4) Finally, use one more patch that mixes operations across files:\n" + " - Add a TEMP.txt file containing a single line: 'Temporary file'.\n" + " - Append a line 'Cleanup step ran.' to FACTS.txt.\n" + " - Delete TEMP.txt.\n\n" + "Important rules:\n" + "- Only call the tool using the apply_patch text format between " + "'*** Begin Patch' and '*** End Patch'.\n" + "- Use '*** Add File', '*** Update File', and '*** Delete File' sections as " + "described in the GPT-5.1 apply_patch guide.\n" + "- When updating a file, include enough context lines so the patch can be " + "applied even if whitespace varies slightly.\n" +) + +conversation.send_message(prompt) +conversation.run() + +print("Conversation finished.") +print(f"EXAMPLE_COST: {llm.metrics.accumulated_cost}") +``` + +```bash Running the Example +export OPENAI_API_KEY="your-openai-api-key" +# or: export LLM_API_KEY="your-openai-api-key" +cd agent-sdk +uv run python examples/01_standalone_sdk/28_apply_patch_with_gpt5_1.py +``` + +## How It Works + +The example wires the `ApplyPatch` tool into an `Agent` alongside `terminal` and `task_tracker`, then guides a GPT-5.1 model through a sequence of increasingly complex patch operations: + +1. **Create files**: The model uses `*** Add File` blocks to create `FACTS.txt` and `NOTES.md` with precise contents. +2. **Multi-hunk update**: A single `*** Update File` block performs multiple edits in `NOTES.md`, demonstrating multi-hunk patches. +3. **Multi-file patch**: One patch updates both `FACTS.txt` and `NOTES.md` together, showing how a single patch can touch multiple files. +4. **Mixed operations**: The final patch adds `TEMP.txt`, appends to `FACTS.txt`, and then deletes `TEMP.txt`, exercising add/update/delete in one go. + +All edits are proposed in the GPT-5.1 `apply_patch` text format and executed by the `ApplyPatch` tool inside the workspace. + +## When to Use ApplyPatch with GPT-5.1 + +Prefer `apply_patch` with GPT-5.1 models when: + +- You want the model to propose structured, reviewable patches instead of raw file contents +- You need safer multi-file edits and want to avoid brittle position-based editing +- You’re relying on OpenAI’s recommended apply_patch prompting style for their GPT-5.x codex models + +For non-GPT-5 models, the default preset continues to use the `file_editor` tool. GPT-5 models use `apply_patch` by default via the SDK’s model-aware preset mapping. From 8867a213ae55fbb07bb0245383a7eb7880965b37 Mon Sep 17 00:00:00 2001 From: enyst Date: Tue, 25 Nov 2025 11:12:54 +0000 Subject: [PATCH 2/6] docs(sdk): add ApplyPatch GPT-5.1 guide to navigation Co-authored-by: openhands --- docs.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs.json b/docs.json index 50a4121a..1ca404eb 100644 --- a/docs.json +++ b/docs.json @@ -214,7 +214,8 @@ "sdk/guides/agent-browser-use", "sdk/guides/agent-custom", "sdk/guides/convo-custom-visualizer", - "sdk/guides/agent-stuck-detector" + "sdk/guides/agent-stuck-detector", + "sdk/guides/agent-apply-patch-gpt5-1" ] }, { @@ -475,4 +476,4 @@ "destination": "/overview/introduction" } ] -} \ No newline at end of file +} From bc8f15cd08e7dbcd15c0380389f73eca8a31c55a Mon Sep 17 00:00:00 2001 From: enyst Date: Sun, 30 Nov 2025 14:08:47 +0000 Subject: [PATCH 3/6] docs(sdk): sync GPT-5.1 ApplyPatch example and remove GitHub source note - Sync code block from agent-sdk PR #1166 (feat/apply-patch-tool-gpt5-1) - Drop GitHub availability note per request; example lives in docs only Co-authored-by: openhands --- sdk/guides/agent-apply-patch-gpt5-1.mdx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sdk/guides/agent-apply-patch-gpt5-1.mdx b/sdk/guides/agent-apply-patch-gpt5-1.mdx index fa79700c..e29e115b 100644 --- a/sdk/guides/agent-apply-patch-gpt5-1.mdx +++ b/sdk/guides/agent-apply-patch-gpt5-1.mdx @@ -3,9 +3,6 @@ title: ApplyPatch with GPT-5.1 description: Use the GPT-5.1 apply_patch tool format to perform rich multi-file edits via the ApplyPatch tool. --- - -This example is available on GitHub: [examples/01_standalone_sdk/28_apply_patch_with_gpt5_1.py](https://github.com/OpenHands/software-agent-sdk/blob/main/examples/01_standalone_sdk/28_apply_patch_with_gpt5_1.py) - This guide shows how to use the `ApplyPatch` tool with GPT-5.1 models using the `apply_patch` text format introduced in the OpenAI cookbook. The tool lets the model propose unified patches that can: @@ -63,7 +60,6 @@ assert model.startswith("openai/gpt-5.1"), "Model must be an openai gpt-5.1 vari llm = LLM( model=model, api_key=SecretStr(api_key), - native_tool_calling=True, # enable native tool calling (Responses API) reasoning_summary=None, # avoid OpenAI org verification requirement log_completions=True, # enable telemetry to log input/output payloads ) From ef20ed47207a39cf18aa7feee6d6be57d03cf0e1 Mon Sep 17 00:00:00 2001 From: Engel Nyst Date: Sun, 30 Nov 2025 16:08:08 +0100 Subject: [PATCH 4/6] Update sdk/guides/agent-apply-patch-gpt5-1.mdx --- sdk/guides/agent-apply-patch-gpt5-1.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/guides/agent-apply-patch-gpt5-1.mdx b/sdk/guides/agent-apply-patch-gpt5-1.mdx index e29e115b..f892db26 100644 --- a/sdk/guides/agent-apply-patch-gpt5-1.mdx +++ b/sdk/guides/agent-apply-patch-gpt5-1.mdx @@ -15,7 +15,7 @@ The SDK wires this up as a normal tool, so you can run it inside an `Agent` and ## Example -```python icon="python" expandable examples/01_standalone_sdk/28_apply_patch_with_gpt5_1.py +```python icon="python" expandable """Example: Using ApplyPatch tool with GPT-5.1 models via direct OpenAI API. This demonstrates adding the ApplyPatch tool to the agent and guiding the From 09cdef9a4817ebfc48ce3d4dfaedb2a34cd0c598 Mon Sep 17 00:00:00 2001 From: Engel Nyst Date: Sun, 30 Nov 2025 16:08:53 +0100 Subject: [PATCH 5/6] Update sdk/guides/agent-apply-patch-gpt5-1.mdx --- sdk/guides/agent-apply-patch-gpt5-1.mdx | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/sdk/guides/agent-apply-patch-gpt5-1.mdx b/sdk/guides/agent-apply-patch-gpt5-1.mdx index f892db26..c324a7e2 100644 --- a/sdk/guides/agent-apply-patch-gpt5-1.mdx +++ b/sdk/guides/agent-apply-patch-gpt5-1.mdx @@ -137,13 +137,3 @@ The example wires the `ApplyPatch` tool into an `Agent` alongside `terminal` and 4. **Mixed operations**: The final patch adds `TEMP.txt`, appends to `FACTS.txt`, and then deletes `TEMP.txt`, exercising add/update/delete in one go. All edits are proposed in the GPT-5.1 `apply_patch` text format and executed by the `ApplyPatch` tool inside the workspace. - -## When to Use ApplyPatch with GPT-5.1 - -Prefer `apply_patch` with GPT-5.1 models when: - -- You want the model to propose structured, reviewable patches instead of raw file contents -- You need safer multi-file edits and want to avoid brittle position-based editing -- You’re relying on OpenAI’s recommended apply_patch prompting style for their GPT-5.x codex models - -For non-GPT-5 models, the default preset continues to use the `file_editor` tool. GPT-5 models use `apply_patch` by default via the SDK’s model-aware preset mapping. From c580af25017457050cbc4b671e85859baa53a5d9 Mon Sep 17 00:00:00 2001 From: Engel Nyst Date: Sun, 30 Nov 2025 16:12:13 +0100 Subject: [PATCH 6/6] Update sdk/guides/agent-apply-patch-gpt5-1.mdx --- sdk/guides/agent-apply-patch-gpt5-1.mdx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sdk/guides/agent-apply-patch-gpt5-1.mdx b/sdk/guides/agent-apply-patch-gpt5-1.mdx index c324a7e2..e93abae6 100644 --- a/sdk/guides/agent-apply-patch-gpt5-1.mdx +++ b/sdk/guides/agent-apply-patch-gpt5-1.mdx @@ -120,11 +120,10 @@ print("Conversation finished.") print(f"EXAMPLE_COST: {llm.metrics.accumulated_cost}") ``` -```bash Running the Example +```bash Running the Script export OPENAI_API_KEY="your-openai-api-key" # or: export LLM_API_KEY="your-openai-api-key" -cd agent-sdk -uv run python examples/01_standalone_sdk/28_apply_patch_with_gpt5_1.py +uv run python apply_patch_with_gpt5_1.py ``` ## How It Works