Cree un agente LLM que pueda escribir y ejecutar código

Es probablemente una de las capacidades más útiles que podemos brindarle a un agente de LLM.

Una vez que el agente puede escribir y ejecutar código, muchas tareas se vuelven posibles. Por ejemplo, el agente puede inspeccionar archivos o conjuntos de datos, escribir lógica de procesamiento de datos o producir artefactos para consumo posterior.

Eso abre la puerta a una gama mucho más amplia de aplicaciones agentes.

En esta publicación, crearemos un agente de codificación con OpenAI Agents SDK y Docker. Primero construiremos el modelo mental, luego analizaremos un pequeño estudio de caso en el que le pediremos al agente que analice un archivo CSV y devuelva un informe con gráficos.

Al final, también resumiremos los detalles prácticos que hacen que este patrón sea reutilizable.

1. Cómo funcionan los agentes ejecutores de código

Hay tres componentes importantes de un agente de ejecución de código: el modelo, el espacio de trabajo y el entorno de ejecución. Desembalémoslos uno por uno.

1.1 El modelo

Después de todo, un agente ejecutor de código es un agente LLM. Naturalmente, se necesita un LLM para impulsar al agente.

En este escenario específico, las tareas comunes del LLM serían inspeccionar los archivos disponibles, decidir qué tipo de análisis se necesita, escribir el código real, leer los resultados y continuar con iteraciones adicionales.

1.2 Espacio de trabajo

Este es el espacio donde trabaja el agente y es donde entran los archivos de entrada y salen los archivos de salida. El usuario puede cargar los archivos de datos (como CSV, PDF, una carpeta de documentos, etc.) en el espacio de trabajo, el agente puede trabajar en ellos y guardar los artefactos en él.

1.3 Entorno de ejecución

El agente LLM solo escribe el código y no lo ejecuta. Por eso necesitamos un entorno de ejecución donde el código generado realmente pueda ejecutarse.

Hay múltiples opciones disponibles. Por ejemplo, este entorno de ejecución de código puede ser uno alojado y administrado por la plataforma, o puede ser un entorno aislado que controlamos nosotros mismos localmente. Si lo controlamos nosotros mismos, Docker suele ser la forma predeterminada de empaquetar el tiempo de ejecución y aislar la ejecución.

1.4 Preocupación transversal: control

Luego, hay una cuestión práctica de diseño: el control.

En la capa del modelo, debemos decidir cómo construir las instrucciones del sistema del agente y qué artefactos debe producir el agente.

En la capa del espacio de trabajo, debemos pensar en qué archivos se almacenan en ella y qué artefactos de salida final deben recuperarse después de la ejecución.

En la capa del entorno de ejecución, debemos determinar qué dependencias deben estar disponibles y si se permite el acceso a la red o al shell.

1.5 SDK de agentes OpenAI

En el SDK de OpenAI Agents, un SandboxAgent implementa exactamente el patrón que comentamos anteriormente.

Para configurar el agente de ejecución de código con Agents SDK, primero debemos describir el espacio de trabajo con un manifiesto, que básicamente especifica qué archivos locales deben almacenarse en el espacio de trabajo. A continuación se muestra un ejemplo sencillo:

# pip install "openai-agents[docker]" desde pathlib import Ruta desde agentes.sandbox import LocalFile, Manifest manifest = Manifest( entradas={ "input/data.csv": LocalFile(src=Path("data/data.csv")), }, )

Esto dice: tome un archivo local y póngalo a disposición dentro del espacio de trabajo como input/data.csv.

Luego, especificamos el modelo del agente, las instrucciones y el manifiesto del espacio de trabajo:

de agentes.sandbox import SandboxAgent agente = SandboxAgent( nombre="agente de codificación", instrucciones="Inspeccione los archivos de entrada, escriba y ejecute código cuando sea útil y guarde los artefactos solicitados.", model="gpt-5.4", default_manifest=manifest,)

A continuación, debemos crear el entorno limitado de ejecución. Si usamos Docker:

# pip install "openai-agents[docker]" importar docker desde agentes.sandbox.sandboxes.docker importar DockerSandboxClient desde agentes.sandbox.sandboxes.docker importar DockerSandboxClientOptions docker_client = DockerSandboxClient(docker.from_env()) sandbox_options = DockerSandboxClientOptions(image="my-agent-sandbox:latest") sandbox_session = espera docker_client.create( manifiesto=manifest, opciones=sandbox_options,) espera sandbox_session.apply_manifest()

Aquí, el argumento de imagen de DockerSandboxClientOptions especifica la imagen de Docker utilizada por el sandbox. Ahí es donde podemos personalizar la imagen, por ejemplo, preinstalando las dependencias para que el agente pueda usarlas directamente durante la ejecución sin instalarlas sobre la marcha.

Finalmente conectamos el agente y la sesión sandbox en tiempo de ejecución:

de agentes import Runner, RunConfig de agentes.sandbox import SandboxRunConfig result = await Runner.run( agente, "Analizar input/data.csv y guardar un breve informe en output/report.md.", run_config=RunConfig( sandbox=SandboxRunConfig(session=sandbox_session), ), )

Después de la ejecución, el espacio de trabajo sandbox también se puede conservar como un archivo tar:

workspace_archive = espera sandbox_session.persist_workspace() espera sandbox_session.aclose()

Luego podemos extraer los archivos de salida que nos interesan (por ejemplo, informes, gráficos, tablas, etc.) y copiarlos nuevamente a la máquina host.

Por supuesto, existen otras formas de habilitar la ejecución de código en Agents SDK además del SandboxAgent mencionado anteriormente. Por ejemplo, puede adjuntar CodeInterpreterTool a un agente normal, lo que le permite ejecutar código en un entorno administrado por OpenAI. Esto resulta útil si no desea administrar usted mismo las imágenes de Docker y los tiempos de ejecución locales.

Si el flujo de trabajo está más orientado a la línea de comandos, el SDK también proporciona ejecución de shell a través de ShellTool. Con SandboxAgent, el shell se incluye de forma predeterminada como parte de sus capacidades de sandbox.

2. Estudio de caso: un agente que analiza un CSV

En este caso de estudio, crearemos un agente que pueda escribir código y realizar análisis de datos.

2.1 La configuración del estudio de caso

Aquí, consideramos una tarea de detección de anomalías de series temporales. Específicamente, le encargaremos al agente que investigue un conjunto de datos de energía de edificios cada hora e identifique eventos inusuales de uso de energía.

Creé un conjunto de datos sintéticos en CSV simple:

datos/energía_construcción.csv

con tres columnas:

marca de tiempo, energía_kwh, temperatura_exterior_c

Los datos de la serie temporal se visualizan a continuación:

Figura 1. Consumo de energía del edificio por hora y temperatura exterior utilizados como datos de entrada para el agente. (Imagen del autor)

Para completar la tarea, el agente debe inspeccionar el CSV, crear un comportamiento de referencia normal y comparar las observaciones con los patrones esperados.

Le pedimos al agente que guarde tres archivos de salida:

salida/anomalías.csv salida/energía_anomalías.png salida/anomaly_report.md

2.2 Preparar el tiempo de ejecución de Docker

Antes de configurar el agente, primero debemos preparar su entorno de ejecución de código. Aquí usamos un contenedor Docker.

Este contenedor servirá como la máquina temporal del agente, con un directorio de trabajo, un tiempo de ejecución de Python y un conjunto de bibliotecas que el agente puede usar para realizar análisis de datos. Tenga en cuenta que el agente solo ejecutará código dentro de ese contenedor, nuestra máquina host permanece fuera de la ejecución.

Para definir ese entorno, creamos un Dockerfile:

FROM python:3.12-slim ENV MPLBACKEND=Agg RUN pip install –no-cache-dir numpy scipy pandas matplotlib WORKDIR /espacio de trabajo

Tenga en cuenta que le damos al agente numpy, scipy, pandas y matplotlib. Esas bibliotecas deberían ser suficientes para la tarea actual. También configuramos MPLBACKEND=Agg, lo que permite a matplotlib guardar figuras sin necesidad de mostrarlas. Esto es especialmente útil aquí porque el código se ejecuta dentro de un contenedor no interactivo.

A continuación, podemos construir la imagen:

importar subproceso IMAGE_NAME = "energy-agent-sandbox:latest" subprocess.run(["docker", "build", "-t", IMAGE_NAME, "."], check=True)

Más adelante, cuando creamos la sesión sandbox, podemos pasar el nombre de esta imagen a DockerSandboxClientOptions. Así es como el sandbox sabe qué entorno de ejecución utilizar.

Para este estudio de caso, debe asegurarse de que Docker esté instalado y ejecutándose en su máquina. La razón es simple: más adelante, nuestro código Python le pedirá a Docker que cree la sesión de zona de pruebas, por lo que el proceso de Python debe poder comunicarse con el demonio de Docker.

En Windows o macOS, puede instalar Docker Desktop. En Linux, instale Docker Engine directamente desde el repositorio de paquetes oficial de Docker.

Puede comprobar si Docker está configurado correctamente ejecutando:

ventana acoplable –versión
docker ejecuta hola mundo

2.3 Definir y ejecutar el agente

Ahora definimos el agente real. Comenzamos con el manifiesto, que le dice al sandbox qué archivo local debería estar disponible dentro del espacio de trabajo:

desde pathlib import Ruta desde agentes.sandbox import LocalFile, Manifest manifest = Manifest( entradas={ "input/building_energy.csv": LocalFile(src=Path("data/building_energy.csv")), }, )

En el fragmento de código anterior, colocamos el archivo CSV local en el espacio de trabajo de la zona de pruebas como:

entrada/energía_construcción.csv

A continuación, definimos la instrucción del agente para definir su rol, resultado esperado, así como las bibliotecas a su disposición:

# Nota: Esta instrucción se repite con AI INSTRUCCIONES = """ Usted es un analista de datos práctico. Utilice el espacio de trabajo de la zona de pruebas para inspeccionar archivos, escribir y ejecutar código cuando sea útil y guardar artefactos claros. Mantenga las conclusiones basadas en evidencia computarizada. La zona de pruebas tiene Python con numpy, scipy, pandas y matplotlib disponibles. """.strip()

Finalmente, creamos el SandboxAgent:

de agentes.sandbox import SandboxAgent agente = SandboxAgent( nombre="Analista de anomalías energéticas", instrucciones=INSTRUCCIONES, modelo="gpt-5.4", default_manifest=manifest,)

Para ejecutar el agente, utilizamos el siguiente mensaje:

PROMPT = """ Tengo una exportación de consumo de energía por hora para un edificio en input/building_energy.csv. Las columnas son marca de tiempo, energía_kwh y outdoor_temp_c. outdoor_temp_c está en grados Celsius. Investigue el archivo y busque eventos anormales en el uso de energía. Ignore las pequeñas fluctuaciones que parecen ruido de funcionamiento normal. Utilice el código en el entorno de pruebas para realizar el análisis y luego guarde estos archivos: – salida/anomalías.csv – salida/energy_anomalies.png – salida/anomaly_report.md En el informe, explique su método brevemente y brinde explicaciones plausibles basadas únicamente en las marcas de tiempo, los valores de energía y la temperatura exterior. Utilice texto ASCII simple como grados C en lugar del símbolo de grados """.strip().

Tenga en cuenta que en el mensaje anterior, especificamos explícitamente los archivos que esperamos. A continuación, creamos una sesión de Docker Sandbox a partir de la imagen que creamos anteriormente:

importar Docker desde agentes.sandbox.sandboxes.docker importar DockerSandboxClient desde agentes.sandbox.sandboxes.docker importar DockerSandboxClientOptions docker_client = DockerSandboxClient(docker.from_env()) sandbox_options = DockerSandboxClientOptions(image=IMAGE_NAME) sandbox_session = await docker_client.create( manifest=manifest, opciones=sandbox_options,) esperan sandbox_session.apply_manifest()

Luego, podemos ejecutar el agente:

desde agentes import Runner, RunConfig desde agentes.sandbox import SandboxRunConfig resultado = await Runner.run( agente, PROMPT, max_turns=25, run_config=RunConfig( sandbox=SandboxRunConfig(session=sandbox_session), ), )

2.4 Inspeccionar los resultados

Después de la ejecución, el agente creó los tres archivos que solicitamos.
Para devolverlos a nuestra carpeta de proyecto local, debemos conservar el espacio de trabajo de la zona de pruebas y extraer los archivos esperados:

desde pathlib import Ruta workspace_archive = await sandbox_session.persist_workspace() OUTPUTS_DIR = Ruta("salidas")shutil.rmtree(OUTPUTS_DIR, ignore_errors=True) OUTPUTS_DIR.mkdir(parents=True, exist_ok=True) con tarfile.open(fileobj=workspace_archive, mode="r:*") como tar: para nombre de archivo en ["anomalies.csv", "energy_anomalies.png", "anomaly_report.md"]: fuente = tar.extractfile(f"output/{filename}") (OUTPUTS_DIR / filename).write_bytes(source.read()) await sandbox_session.aclose()

Ahora podemos ver que existen los siguientes archivos en la carpeta local de salidas/:

anomalías.csv energía_anomalías.png anomalía_report.md

El agente encontró un evento anormal claro, como se muestra en el archivo energy_anomalies.png:

Figura 2. El agente identificó correctamente el evento anormal. (Imagen del autor)

Podemos inspeccionar más a fondo cómo el agente llegó a esta conclusión:

para el elemento en result.new_items: print(tipo(elemento).__nombre__, elemento)

En mi ejecución, puedo ver aproximadamente que el agente primero inspeccionó el espacio de trabajo y cargó el CSV con pandas. Luego verificó el recuento de filas, los nombres de las columnas, los tipos de datos y los valores faltantes.

Después de eso, escribió y ejecutó un script de detección de anomalías con numpy y pandas. El script primero construyó una línea de base horaria esperada, seguida por el cálculo de residuos y puntuaciones z sólidas.

Finalmente, el agente generó el gráfico solicitado, guardó el CSV y generó un informe de rebajas. Incluso validó los resultados para concluir el trabajo.

Ahora tenemos un agente ejecutor de código en funcionamiento.

3. Cosas prácticas a tener en cuenta

Como hemos visto en el estudio de caso anterior, hay algunos detalles que debemos considerar al crear el agente ejecutor de código:

Comience con las instrucciones del agente, sea explícito acerca de su rol, su tarea y el resultado esperado; Decida qué archivos deben ingresar al espacio de trabajo. Este es el conjunto de archivos en los que trabajará el agente; Decida qué tiempo de ejecución puede utilizar el agente, incluidas las bibliotecas necesarias; Indique explícitamente los nombres y ubicaciones de los archivos de salida. Esto facilita la posterior extracción y copia y pegado.

Una vez que esas piezas estén claras, podrá reutilizar el mismo patrón para muchos otros flujos de trabajo agentes.

Entonces, ¿qué construirías a continuación con esta capacidad?