For the complete documentation index, see llms.txt. Markdown versions of documentation pages are available by appending .md to the page URL.
Navegación principal
Theme

Aplicación de parches

Permite que los modelos propongan diffs estructurados que tu integración aplica.

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:

  1. 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"}].
  2. 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.
  3. 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 operation para cada apply_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.
  4. Comunica al modelo los resultados de los parches
    • Vuelve a llamar a la API de Responses con previous_response_id o vuelve a incluir los elementos de la conversación en input.
    • Incluye un evento apply_patch_call_output por cada call_id, con el campo status y una cadena output opcional.
    • Mantén tools=[{"type": "apply_patch"}] para que el modelo pueda seguir editando si es necesario.
  5. Deja que el modelo continúe o explique los cambios
    • El modelo puede generar más operaciones apply_patch_call o
    • explicar en lenguaje natural qué cambió y por qué.

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

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

Ejemplo de un objeto apply_patch_call
{
    "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

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:

Informa de una llamada fallida a apply_patch
{
  "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:

  1. Extrae las operaciones de la respuesta
    • Busca en la respuesta los elementos con type: "apply_patch_call".
    • Para cada llamada, revisa operation.type, operation.path y, si está presente, diff.
  2. Ejecuta las operaciones sobre los archivos
    • Para create_file y update_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 en path.
    • Registra si cada operación se completó correctamente y guarda los registros o mensajes de error que se generen.
  3. Devuelve los eventos apply_patch_call_output correspondientes
    • Para cada call_id, genera exactamente un evento apply_patch_call_output con el estado que corresponda:
      • status: "completed" si la operación se completó correctamente.
      • status: "failed" si se produjo un error (incluye una cadena output breve que explique el error en lenguaje claro).

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 failed con una cadena output que 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.

Usa la herramienta de parches con el SDK de agentes
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 la herramienta de parches en TypeScript

Ejemplo de cómo usar la herramienta de parches con el SDK de agentes en TypeScript

Ejemplo de la herramienta de parches en Python

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.

Error: no se encontró el archivo
{
  "type": "apply_patch_call_output",
  "call_id": "call_abc",
  "status": "failed",
  "output": "Error: File not found at path 'lib/baz.py'"
}

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).
  • 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.
  • 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 input para que el modelo pueda corregirlos.

Notas de uso