Usa apply_patch con la API de Responses para que el modelo proponga crear, actualizar o eliminar archivos mediante diffs estructurados. Tu aplicación ejecuta cada operación y devuelve su resultado. Los ejemplos usan gpt-6-astra.
Cuándo usarla
Puedes usar apply_patch para las siguientes tareas.
- Refactorización de varios archivos. Cambia el nombre de símbolos, extrae funciones auxiliares o reorganiza módulos en varios archivos a la vez.
- Corrección de errores. Pídele al modelo que diagnostique los problemas y genere parches precisos.
- Generación de pruebas y documentación. Crea archivos de prueba, fixtures y documentación junto con los cambios de código.
- Migraciones y cambios mecánicos. Aplica actualizaciones repetitivas y estructuradas, como migraciones de API, anotaciones de tipos o correcciones de formato.
Si puedes describir por escrito tu repositorio y el cambio que buscas, apply_patch suele poder generar los diffs correspondientes.
Cómo usar la herramienta de parches con la API de Responses
En términos generales, estos son los pasos para usar apply_patch con la API de Responses:
- Llama a la API de Responses con la herramienta
apply_patch- Incluye información sobre los archivos disponibles (o un resumen) en
input, o dale al modelo herramientas para explorar tu sistema de archivos. - Habilita la herramienta con
tools=[{"type": "apply_patch"}].
- Incluye información sobre los archivos disponibles (o un resumen) en
- Deja que el modelo devuelva una o más operaciones de parche
- La salida de la respuesta incluye uno o más objetos
apply_patch_call. - Cada llamada describe una sola operación sobre un archivo: crearlo, actualizarlo o eliminarlo.
- La salida de la respuesta incluye uno o más objetos
- Aplica los parches en tu entorno
- Ejecuta un arnés de ejecución de parches o un script que se encargue de lo siguiente:
- Interpretar el diff de
operationpara cadaapply_patch_call. - Aplicar el parche a tu directorio de trabajo o repositorio.
- Registrar si cada parche se aplicó correctamente y guardar los registros o mensajes de error que se generen.
- Interpretar el diff de
- Ejecuta un arnés de ejecución de parches o un script que se encargue de lo siguiente:
- Comunica al modelo los resultados de los parches
- Vuelve a llamar a la API de Responses con
previous_response_ido vuelve a incluir los elementos de la conversación eninput. - Incluye un evento
apply_patch_call_outputpor cadacall_id, con el campostatusy una cadenaoutputopcional. - Mantén
tools=[{"type": "apply_patch"}]para que el modelo pueda seguir editando si es necesario.
- Vuelve a llamar a la API de Responses con
- Deja que el modelo continúe o explique los cambios
- El modelo puede generar más operaciones
apply_patch_callo - explicar en lenguaje natural qué cambió y por qué.
- El modelo puede generar más operaciones
Ejemplo: cambiar el nombre de una función con la herramienta de parches
Paso 1: pídele al modelo que planifique los cambios y genere los parches
import OpenAI from "openai";
// Application-owned helper; see "Implementing the patch harness" in the guide.
// This demo only applies exact updates to the two in-memory files below.
import { applyOperation } from "../../support/apply-patch.mjs";
const client = new OpenAI();
const files = {
"lib/fib.py": `def fib(n):
if n <= 1:
return n
return fib(n - 1) + fib(n - 2)
`,
"run.py": `from lib.fib import fib
print(fib(42))
`,
};
const fileContext = `The user has the following files:
<BEGIN_FILES>
${Object.entries(files)
.map(([path, content]) => `===== ${path}\n${content}`)
.join("\n")}
<END_FILES>
Help me rename the fib() function to fibonacci().`;
let response = await client.responses.create({
model: "gpt-6-astra",
input: fileContext,
tools: [{ type: "apply_patch" }],
});
let patchCalls = response.output.filter(
(item) => item.type === "apply_patch_call"
);Objeto apply_patch_call de ejemplo
{
"id": "apc_08f3d96c87a585390069118b594f7481a088b16cda7d9415fe",
"type": "apply_patch_call",
"status": "completed",
"call_id": "call_Rjsqzz96C5xzPb0jUWJFRTNW",
"operation": {
"type": "update_file",
"diff": "
@@
-def fib(n):
+def fibonacci(n):
if n <= 1:
return n
- return fib(n-1) + fib(n-2) + return fibonacci(n-1) + fibonacci(n-2),
",
"path": "lib/fib.py"
}
}Paso 2: aplica el parche y devuelve los resultados
for (let turn = 0; patchCalls.length > 0; turn++) {
if (turn === 8) throw new Error("Patch workflow exceeded eight tool turns.");
const results = patchCalls.map((call) => {
const { success, output } = applyOperation(files, call.operation);
return {
type: "apply_patch_call_output",
call_id: call.call_id,
status: success ? "completed" : "failed",
output,
};
});
response = await client.responses.create({
model: "gpt-6-astra",
previous_response_id: response.id,
input: results,
tools: [{ type: "apply_patch" }],
});
patchCalls = response.output.filter(
(item) => item.type === "apply_patch_call"
);
}
console.log(response.output_text);
for (const [path, content] of Object.entries(files)) {
process.stdout.write(`===== ${path}\n${content}`);
}Si un parche falla (por ejemplo, porque no se encuentra el archivo), establece status: "failed" e incluye una cadena output que ayude al modelo a recuperarse del error:
{
"type": "apply_patch_call_output",
"call_id": "call_cNWm41dB3RyQcLNOVTIPBWZU",
"status": "failed",
"output": "Could not apply patch to lib/foo.py — file not found on disk"
}Operaciones de la herramienta de parches
| Tipo de operación | Propósito | Datos de la operación |
|---|---|---|
create_file |
Crea un archivo en path. |
diff es un diff en formato V4A que representa todo el contenido del archivo. |
update_file |
Modifica un archivo existente en path. |
diff es un diff en formato V4A con adiciones, eliminaciones o reemplazos. |
delete_file |
Elimina el archivo ubicado en path. |
La operación no incluye diff y elimina el archivo por completo. |
Tu arnés de ejecución de parches se encarga de interpretar los diffs en formato V4A y aplicar los cambios. Para ver implementaciones de referencia, consulta el código del SDK de agentes para Python o del SDK de agentes para TypeScript.
Cómo implementar el arnés de ejecución de parches
Al usar la herramienta apply_patch, no necesitas proporcionar un esquema de entrada. El modelo sabe cómo construir objetos operation. Tu tarea consiste en lo siguiente:
- Extrae las operaciones de la respuesta
- Busca en la respuesta los elementos con
type: "apply_patch_call". - Para cada llamada, revisa
operation.type,operation.pathy, si está presente,diff.
- Busca en la respuesta los elementos con
- Ejecuta las operaciones sobre los archivos
- Para
create_fileyupdate_file, aplica el diff en formato V4A al sistema de archivos o al espacio de trabajo en memoria. - Para
delete_file, elimina el archivo ubicado enpath. - Registra si cada operación se completó correctamente y guarda los registros o mensajes de error que se generen.
- Para
- Devuelve los eventos
apply_patch_call_outputcorrespondientes- Para cada
call_id, genera exactamente un eventoapply_patch_call_outputcon el estado que corresponda:status: "completed"si la operación se completó correctamente.status: "failed"si se produjo un error (incluye una cadenaoutputbreve que explique el error en lenguaje claro).
- Para cada
Seguridad y robustez
- Validación de rutas: impide que se usen rutas para salir de los directorios permitidos y limita los cambios a esos directorios.
- Copias de seguridad: considera hacer una copia de seguridad de los archivos (o trabajar en una copia temporal) antes de aplicar los parches.
- Manejo de errores: cuando no puedas aplicar un parche, devuelve siempre el estado
failedcon una cadenaoutputque explique el error. - Atomicidad: decide si quieres aplicar los cambios con un criterio de “todo o nada” (revertirlos todos si falla algún parche) o gestionar el resultado de cada archivo por separado.
Cómo usar la herramienta de parches con el SDK de agentes
También puedes usar el SDK de agentes para trabajar con la herramienta de parches. Aún tendrás que implementar el arnés de ejecución que realiza las operaciones sobre los archivos, pero puedes usar la función applyDiff para procesar los diffs.
import {
mkdirSync,
realpathSync,
lstatSync,
readFileSync,
writeFileSync,
unlinkSync,
} from "node:fs";
import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
import { applyDiff, Agent, run, applyPatchTool } from "@openai/agents";
class WorkspaceEditor {
constructor(root = "workspace") {
mkdirSync(root, { recursive: true });
this.root = realpathSync(root);
}
path(name) {
const target = resolve(this.root, name);
const relativePath = relative(this.root, target);
if (
!relativePath ||
isAbsolute(relativePath) ||
relativePath === ".." ||
relativePath.startsWith(`..${sep}`)
) {
throw new Error("Patch paths must stay inside the workspace");
}
let current = this.root;
for (const part of relativePath.split(sep)) {
current = join(current, part);
if (lstatSync(current, { throwIfNoEntry: false })?.isSymbolicLink()) {
throw new Error("Patch paths must not traverse symbolic links");
}
}
return target;
}
async createFile(operation) {
const path = this.path(operation.path);
const content = applyDiff("", operation.diff, "create");
mkdirSync(dirname(path), { recursive: true });
writeFileSync(path, content, { encoding: "utf8", flag: "wx" });
return { status: "completed", output: `Created ${operation.path}` };
}
async updateFile(operation) {
const path = this.path(operation.path);
const content = applyDiff(readFileSync(path, "utf8"), operation.diff);
writeFileSync(path, content, "utf8");
return { status: "completed", output: `Updated ${operation.path}` };
}
async deleteFile(operation) {
unlinkSync(this.path(operation.path));
return { status: "completed", output: `Deleted ${operation.path}` };
}
}
const editor = new WorkspaceEditor();
const agent = new Agent({
name: "Patch Assistant",
model: "gpt-6-astra",
instructions:
"Use apply_patch to edit files in the workspace. Supply paths relative to that workspace.",
tools: [
applyPatchTool({
editor,
// could also be a function for you to determine if approval is needed
needsApproval: true,
onApproval: async (_ctx, _approvalItem) => {
// create your own approval logic
return { approve: true };
},
}),
],
});
const result = await run(
agent,
"Create tasks.md with a shopping checklist of 5 entries."
);
console.log(`\nFinal response:\n${result.finalOutput}`);En GitHub encontrarás ejemplos completos que puedes ejecutar.
Ejemplo de cómo usar la herramienta de parches con el SDK de agentes en TypeScript
Ejemplo de cómo usar la herramienta de parches con el SDK de agentes en Python
Cómo manejar errores comunes
Usa status: "failed" junto con un mensaje output claro para ayudar al modelo a recuperarse del error.
{
"type": "apply_patch_call_output",
"call_id": "call_abc",
"status": "failed",
"output": "Error: File not found at path 'lib/baz.py'"
}{
"type": "apply_patch_call_output",
"call_id": "call_abc",
"status": "failed",
"output": "Error: Invalid Context:\n@@ def fib(n):"
}A partir de estos mensajes de error, el modelo puede ajustar los siguientes diffs, por ejemplo, volviendo a leer un archivo incluido en tu prompt o simplificando un cambio.
Buenas prácticas
- Proporciona contexto claro sobre los archivos
- Cuando llames a la API de Responses, incluye una copia del contenido actual de tus archivos directamente en la solicitud (como en el ejemplo) o dale al modelo herramientas para explorar tu sistema de archivos (como la herramienta
shell).
- Cuando llames a la API de Responses, incluye una copia del contenido actual de tus archivos directamente en la solicitud (como en el ejemplo) o dale al modelo herramientas para explorar tu sistema de archivos (como la herramienta
- Considera combinar la herramienta de parches con la herramienta
shell- Con la herramienta
shell, el modelo puede explorar los directorios del sistema de archivos, leer archivos y buscar palabras clave con grep. Así, el agente puede localizar y editar archivos por su cuenta.
- Con la herramienta
- Pide diffs pequeños y específicos
- En las instrucciones del sistema, orienta al modelo para que haga cambios mínimos y puntuales en lugar de reescribir grandes partes del código.
- Verifica que los cambios se apliquen sin problemas
- Después de aplicar una serie de parches, ejecuta tus pruebas o linters e incluye los errores en el siguiente
inputpara que el modelo pueda corregirlos.
- Después de aplicar una serie de parches, ejecuta tus pruebas o linters e incluye los errores en el siguiente
Notas de uso
| Disponibilidad por API | Modelos compatibles |
|---|---|