Responses API Patches function - align your prompting with the AI's internal instructions

Apply patch tool - OpenAI Responses API endpoint

understanding implementation inconsistencies

The function methods you are exposed to on the API and the documentation are different that the AI model’s internal understanding.

It is important to know what is provided in the function itself so that you can build a prompted product properly.

I’ll just leave this here…

functions
### Target channel: commentary

### Tool definitions
// In this environment, you can run <apply_patch_command> with functions.apply_patch to execute a diff/patch against a file, where <apply_patch_command> is a specially formatted apply patch command representing the diff you wish to execute. Don't prefix the command with bash -lc, just directly call functions.apply_patch with it. A valid <apply_patch_command> looks like: *** Begin Patch [YOUR_PATCH] *** End Patch
//
// Where [YOUR_PATCH] is the actual content of your patch, specified in the following V4A diff format. *** [ACTION] File: [path/to/file] → ACTION can be one of Add, Update, or Delete. For each snippet of code that needs to be changed, repeat the following: [context_before]
//
// [old_code] → Precede the old code with a minus sign.
// [new_code] → Precede the new, replacement code with a plus sign. [context_after] For instructions on [context_before] and [context_after]:
// Use the @@ operator to indicate the class or function to which the snippet to be changed belongs, and optionally provide 1-3 unchanged context lines above and below the snippet to be changed for disambiguation. For instance, we might have: @@ class BaseClass [2 lines of pre-context]
// [old_code]
// [new_code] [2 lines of post-context]
// For additional disambiguation, you can use multiple nested @@ statements to specify both class and function, to jump to the right context. For instance: @@ class BaseClass @@ def method(): [2 lines of pre-context]
// [old_code]
// [new_code] [2 lines of post-context] We do not use line numbers in this diff format, as the context is enough to uniquely identify code. File references can only be relative, never absolute.
// Do NOT attempt to use any other method to apply a patch in the container, as they will not work. Only use functions.apply_patch.
// IMPORTANT: This tool only accepts string inputs that obey the lark grammar start: begin_patch hunk+ end_patch
// begin_patch: "*** Begin Patch" LF
// end_patch: "*** End Patch" LF?
//
// hunk: add_hunk | delete_hunk | update_hunk
// add_hunk: "*** Add File: " filename LF add_line+
// delete_hunk: "*** Delete File: " filename LF
// update_hunk: "*** Update File: " filename LF change
//
// filename: /(.+)/
// add_line: "+" /(.*)/ LF -> line
//
// change: (change_context | change_line)+
// change_context: ("@@" | "@@ " /(.+)/) LF
// change_line: ("+" | "-" | " ") /(.*)/ LF
//
// %import common.LF. You must reason carefully about the input and make sure it obeys the grammar.
// IMPORTANT: Do NOT call this tool in parallel with other tools.
type apply_patch = (FREEFORM) => any;

or for readability..

functions
### Target channel: commentary

### Tool definitions
// In this environment, you can run <apply_patch_command> with functions.apply_patch to execute a diff/patch against a file, where <apply_patch_command> is a specially formatted apply patch command representing the diff you wish to execute. Don't prefix the command with bash -lc, just directly call functions.apply_patch with it. A valid <apply_patch_command> looks like: *** Begin Patch [YOUR_PATCH] *** End Patch
//
// Where [YOUR_PATCH] is the actual content of your patch, specified in the following V4A diff format. *** [ACTION] File: [path/to/file] → ACTION can be one of Add, Update, or Delete. For each snippet of code that needs to be changed, repeat the following: [context_before]
//
// [old_code] → Precede the old code with a minus sign.
// [new_code] → Precede the new, replacement code with a plus sign. [context_after] For instructions on [context_before] and [context_after]:
// Use the @@ operator to indicate the class or function to which the snippet to be changed belongs, and optionally provide 1-3 unchanged context lines above and below the snippet to be changed for disambiguation. For instance, we might have: @@ class BaseClass [2 lines of pre-context]
// [old_code]
// [new_code] [2 lines of post-context]
// For additional disambiguation, you can use multiple nested @@ statements to specify both class and function, to jump to the right context. For instance: @@ class BaseClass @@ def method(): [2 lines of pre-context]
// [old_code]
// [new_code] [2 lines of post-context] We do not use line numbers in this diff format, as the context is enough to uniquely identify code. File references can only be relative, never absolute.
// Do NOT attempt to use any other method to apply a patch in the container, as they will not work. Only use functions.apply_patch.
// IMPORTANT: This tool only accepts string inputs that obey the lark grammar start: begin_patch hunk+ end_patch
// begin_patch: "*** Begin Patch" LF
// end_patch: "*** End Patch" LF?
//
// hunk: add_hunk | delete_hunk | update_hunk
// add_hunk: "*** Add File: " filename LF add_line+
// delete_hunk: "*** Delete File: " filename LF
// update_hunk: "*** Update File: " filename LF change
//
// filename: /(.+)/
// add_line: "+" /(.*)/ LF -> line
//
// change: (change_context | change_line)+
// change_context: ("@@" | "@@ " /(.+)/) LF
// change_line: ("+" | "-" | " ") /(.*)/ LF
//
// %import common.LF.
// You must reason carefully about the input and make sure it obeys the grammar.
// IMPORTANT: Do NOT call this tool in parallel with other tools.
type apply_patch = (FREEFORM) => any;

Crucial to note:

Apply Patch documentation will have you fulfill these function methods:

Operation Type Purpose
create_file Create a new file at path.
update_file Modify an existing file at path.
delete_file Remove a file at path.

However, you will note that the AI understands ACTION of:

Add File, Update File, or Delete File

Prompting the model, it is best to follow what is not documented: what the AI understands about the methods.

Secondly, you have “File references can only be relative, never absolute.” This is quite the opposite of my app’s capabilities, which has a workspace root that can never be escaped, and like code interpreter /mnt/data is a starting domain of /, that can be changed. A patch need not touch a file system at all: this can be a mechanism for updated user interface artifacts and canvas surfaces. What OpenAI provides is only from their own imagination, such as having a shell function for exploring and reading little chunks of files and amplifying the iteration count.

Then, another falter and waste of potential for optimization: this says right there that the function cannot be used with parallel tool calls. Makes sense, as that tool wrapper is for functions in the function space for JSON. However this could highly enhance the speed of a collective multi-file patch. So best, disable parallel tool calls by API parameter, as this waste of useless distraction and possible error is still defaulting to being placed in AI context even with only a non-supporting patch tool.

Finally, the function says “don’t use any other method to apply a patch”. That limits a developer’s growth potential for their own freeform custom functions that can do special things or a robust internal feature set. Again, language unknown and out of a developer’s control is sabotage.

V4A patch format. Documented by the AI’s own prompting, instead of "look at our Python.

Happy patching.

3 Likes

I also note and reflect on OpenAI’s documentation.

They give you a tool call response to place back, recommending a status and an output. However, their own messaging doesn’t align with what the AI model sent.

return {"status": "completed", "output": f"Created {operation.path}"}

Why not have codex itself give you some better guidance: it knows my code and my understanding and its own understanding of what is internally functions.apply_patch

Goal: the tool return must tell the model whether its patch matched the intended hunk application, so it can adjust behavior (e.g., refine context, split hunks) on failures or confirm success.

Return format (one per call_id):
{
“type”: “apply_patch_call_output”,
“call_id”: “…”,
“status”: “completed” | “failed”,
“output”: “short, structured summary”
}

Output should encode:

  1. Action in native patch terms: [Add] / [Update] / [Delete]
  2. Path
  3. Line counts and delta (for updates)
  4. Hunk count actually applied (for add/update)
  5. If failed, the reason (e.g., context mismatch) and optionally the first expected context line(s)

Examples:

Success (update):
[Update] /src/app.py (571 lines, +0, 2 hunks)

Success (add):
[Add] /projects/hello_world.py (1 lines, 1 hunk)

Failure (context mismatch):
Invalid Context: could not find expected block in file. Expected block (first lines): “def foo():”

Why this helps the model when you have programmatic info as “output” aligned with the internal apply patch method that was emitted to the tool recipient:

  • Confirms whether the tool interpreted its diff as intended (hunk count, line delta).
  • Ensures discovery and recovery from applied bad patch writing by the AI itself
  • Indicates whether the patch was applied in the right location (context match).
  • Gives immediate signal to retry with more context or smaller hunks if failed.

(in my code, new file is immediately surfaced in full, or starting code base vs updated depending on context window you want to eat up; the AI is never blind to what happened and the current state of code after every tool call.)