Skip to main content
Glama
gatordevin
by gatordevin

AVO — Operadores de Variación Agénticos

Una reproducción abierta de AVO: Agentic Variation Operators for Autonomous Evolutionary Search (Chen, Ye, Xu et al., NVIDIA, 2026), ejecutable en un portátil.

La búsqueda evolutiva clásica, y los sistemas aumentados con LLM que la siguieron, descomponen el operador de variación en un pipeline fijo:

Vary(P_t) = Generate(Sample(P_t))

El framework muestrea padres; el modelo produce un candidato a partir de ellos. AVO sustituye toda esa descomposición por una única ejecución de agente autónomo:

Vary(P_t) = Agent(P_t, K, f)

El agente ve el linaje completo P_t, una base de conocimiento de dominio K y la función de puntuación f — y decide por sí mismo qué leer, qué cambiar y cuándo medir. Deja de ser un generador de candidatos y se convierte en el operador de variación.

Este repositorio implementa ese framework, además de la maquinaria que lo rodea que describe el artículo: un linaje respaldado por git, un vector de puntuación con compuerta de corrección, la política de commit matches-or-improves, un supervisor que interviene ante el estancamiento y gráficas de trayectoria. Se incluyen dos objetivos de optimización.


La parte que importa: se ejecuta en la sesión que ya tienes

El driver por defecto no lanza un agente y no llama a una API. Entrega el prompt de variación a la sesión de Claude Code con la que ya estás hablando, y esa sesión hace el trabajo. No se cobra nada extra, no se necesita ANTHROPIC_API_KEY, y el agente que optimiza es un agente de codificación de propósito general real — que es exactamente lo que usó el artículo.

El modo desatendido (lanzar un agente por paso y dejarlo correr durante días, como el experimento de 7 días del artículo) también está disponible, y es opt-in precisamente porque consume cuota.

Related MCP server: AgentPrism Workflows

Instalación

git clone https://github.com/gatordevin/avo
cd avo
pip install -e ".[all]"     # or: pip install -e .  for the core only
avo doctor

En un sistema con Python gestionado externamente (Homebrew, la mayoría de las distribuciones Linux), usa un virtualenv — el flag --system-site-packages reutiliza un NumPy y Matplotlib que ya tienes:

python3 -m venv --system-site-packages .venv
.venv/bin/pip install -e ".[all]"
.venv/bin/avo doctor

Requisitos: Python 3.10+, git y un compilador de C si quieres el objetivo attention_c. numpy lo necesitan los objetivos incluidos, matplotlib para las gráficas. El framework central solo depende de PyYAML.

Inicio rápido — condúcelo desde el agente que ya tienes

Protocolo completo, incluido Codex y uso con CLI simple, en docs/DRIVING.md.

Claude Code

Registra el servidor MCP una vez, a nivel de usuario para que esté disponible en todas las carpetas:

claude mcp add avo -s user -- python3 -m avo.mcp_server
# from a virtualenv, point at its interpreter:
claude mcp add avo -s user -- /path/to/avo/.venv/bin/python -m avo.mcp_server

claude mcp list debería mostrar avo — ✔ Connected. Opcionalmente instala la skill incluida para que /avo funcione en cualquier sitio:

cp -r .claude/skills/avo ~/.claude/skills/avo

Luego, en una sesión de Claude Code en cualquier directorio:

Usa las herramientas de avo para evolucionar el objetivo game2048 durante 10 pasos. Llama a avo_start_run, luego haz un bucle: avo_next_step, haz el trabajo que pida, avo_evaluate hasta que estés satisfecho, y luego avo_submit. Si informa de un estancamiento, llama a avo_supervisor_brief, respóndele y archívalo con avo_record_supervisor.

Las once herramientas son el bucle completo:

herramienta

qué hace

avo_start_run

siembra x_0, lo puntúa, mide las líneas base, abre el linaje

avo_next_step

el prompt de variación: P_t, el índice de K, el contrato de f

avo_evaluate

ejecuta f sobre el árbol de trabajo — gratis, llámalo cuanto quieras

avo_submit

cierra el paso: puntúa y luego hace commit o revierte según la política

avo_revert

abandona un experimento sin gastar el paso

avo_status / avo_lineage

dónde está la ejecución

avo_supervisor_brief / avo_record_supervisor

la intervención por estancamiento

avo_plot

renderiza la trayectoria

avo_list_targets

qué se puede evolucionar

Codex

Codex CLI habla MCP y lee AGENTS.md, así que ambas mitades funcionan:

codex mcp add avo -- python3 -m avo.mcp_server

AGENTS.md en la raíz del repositorio documenta el bucle y las reglas que mantienen honesta una ejecución; Codex lo recoge automáticamente al trabajar en este directorio.

Sin MCP

Cada herramienta tiene un gemelo CLI, así que un shell simple funciona igualmente bien — es la opción más portable y funciona con cualquier agente, o a mano:

avo start --target game2048          # seeds x0 and prints the first prompt
# ... edit runs/<id>/work/, run runs/<id>/avo-eval as often as you like ...
avo submit -m "expectimax depth 2 with a positional weight matrix"
avo prompt                           # the next step's prompt
avo status
avo plot -o trajectory.png

Ejecuciones trabajadas

Dos ejecuciones completas se incluyen con el repositorio, ambas dirigidas en modo sesión por una sesión de Claude Code, ambas con sus callejones sin salida.

attention_decode — superando el kernel del proveedor

examples/attention-decode-run/ evoluciona el paso de decode de la atención: un token de consulta contra una caché KV larga, el cálculo que un LLM ejecuta para cada token generado. Puntuado contra mx.fast.scaled_dot_product_attention — el propio kernel de Metal fusionado de Apple.

0.05 → 1.14× MLX en tres pasos. Este es el que el kernel evolucionado realmente supera a la implementación del proveedor, y la parte interesante es cómo:

  • El paso 1 fue implementación — flash-decoding con división llevó el kernel de 1.6 GB/s a 106 GB/s, alrededor del 95% del límite de streaming de la máquina. Eso alcanzó 0.95× MLX y agotó la palanca: no puedes leer bytes más rápido de lo que el controlador de memoria los entrega.

  • El paso 2 fue matemáticas. La compuerta del objetivo es un presupuesto de error de salida en lugar de igualdad exacta, así que la búsqueda pudo cambiar el cálculo. La medición mostró que el 99.9% de la masa del softmax está en ~11% de las claves, así que el kernel ahora puntúa cada clave pero lee V solo por encima de un umbral derivado para que la masa descartada esté demostrablemente por debajo del 0.3%. Eso cruzó 1.0, gastando el 2% del presupuesto de error.

La lección se generaliza: una vez que un kernel limitado por ancho de banda está en el techo, la única palanca restante es leer menos bytes, y eso es un cambio algorítmico.

Lee el informe completo →

attention_c — el propio dominio del artículo

examples/attention-c-run/ evoluciona un kernel de atención forward en C, alcanzando 2.2× una implementación directa de NumPy/BLAS y cerca del techo NEON. Nota el marco honesto: esa línea base no es una librería de atención afinada, y este kernel es más lento que el SDPA de CPU de torch y que MLX — las unidades de matriz AMX de Apple son inalcanzables desde C portable. El informe da la comparación completa.

Tres hallazgos de él merecen el clic:

  • El propio algoritmo del artículo era la respuesta equivocada aquí. Un kernel en mosaico estilo FlashAttention con softmax online en streaming midió peor, dos veces. A estos tamaños una cabeza completa cabe en L2, así que bloquear para localidad no compra nada mientras que el reescalado por bloque es trabajo puro añadido. El coste es aritmético, no de memoria.

  • -ffast-math rompe silenciosamente el exp rápido estándar, al cancelar algebraicamente el truco de redondeo de añadir-magia-constante del que depende. La compuerta de corrección lo detectó en una forma N=3; el número de throughput nunca lo habría hecho.

  • La ejecución forzó una corrección del objetivo. Puntuar GFLOP/s crudos en un portátil haciendo otras cosas no es una medición — el código idéntico varió 44–76 GFLOP/s en veinte minutos. eval.py ahora cronometra una referencia NumPy/BLAS en el mismo proceso, intercalada con el candidato, y puntúa la proporción.

Lee la introducción completa →

game2048 — evolucionando una política de juego

examples/game2048-run/ es una ejecución completa de 8 pasos del objetivo game2048, dirigida en modo sesión por una sesión de Claude Code. El directorio contiene la salida sin editar: la política evolucionada, las notas de trabajo del operador, la trayector completa, las herramientas de cribado que construyó y sus callejones sin salida.

876 → 43 826 — 50× la semilla, 14× la línea base más fuerte. Partidas que alcanzan 2048: 0% → 77%. Mejor ficha: 512 → 8192. Apple M5, un solo hilo, solo biblioteca estándar.

trayector de evolución

La mejora llega en saltos discretos separados por mesetas, coincidiendo con la Figura 5 del artículo. Las dos versiones planas son trabajo de throughput puro que compró el presupuesto que el siguiente paso gastó — el mismo papel que el cambio de rescale sin ramas v19→v20 del artículo.

La mayor ganancia individual (+50.5%) no fue una optimización. El benchmark puntuaba puntos de juego acumulados; la heurística solo medía lo sobrevivible que parecía un tablero, así que nada en la búsqueda sabía que fusionar dos 256s banca 512 puntos. Cuatro pasos de trabajo de throughput valieron +27% en conjunto; un paso de comprobar qué se estaba optimizando realmente valió +50%.

Lee la introducción completa →

Qué se incluye

game2048 — evoluciona una política de juego

Evoluciona agent.py hasta el jugador de 2048 más fuerte que puedas, bajo un presupuesto duro de tiempo de pensamiento. Puntuado como la media geométrica de la puntuación media de partida en cuatro bancos de doce semillas deterministas. Superar el presupuesto de 120 s puntúa cero, no "un poco menos" — así que la profundidad de búsqueda, el coste de la función de evaluación y la poda se intercambian entre sí, y ese intercambio es el problema.

Medido en un Apple M5:

política

puntuación

semilla x_0 (primer movimiento legal)

876

línea base aleatoria

1 076

línea base heurística de esquina

2 565

línea base codiciosa de un nivel

3 132

Los jugadores expectimax fuertes puntúan en las decenas de miles. La ejecución trabajada de arriba alcanzó 43 826.

attention_c — evoluciona un kernel, el propio dominio del artículo

Evoluciona un kernel de atención forward de precisión simple en C: O = softmax(QKᵀ/√D)V, causal y no causal, D = 64. Con compuerta de acuerdo con una referencia float64 en dieciocho formas — incluidas longitudes de secuencia primas y con desfase de uno, así que un kernel que maneja mal su cola falla en lugar de puntuar bien silenciosamente.

Puntuado como aceleración sobre una referencia NumPy/BLAS cronometrada en el mismo proceso, media geométrica de cuatro longitudes de secuencia × dos modos de enmascarado. 1.0 es paridad con la biblioteca. Puntuar una proporción en lugar de GFLOP/s crudos hace que el benchmark sea inmune a lo que sea que la máquina esté haciendo — el throughput absoluto en un portátil compartido se mueve más que la mayoría de las optimizaciones.

kernel

puntuación

semilla x_0 (ingenuo, materializa la matriz de puntuación N×N completa)

0.19×

línea base NumPy/BLAS — el "cuDNN" de esta configuración

1.00×

evolucionado en 3 pasos (informe)

2.11×

La base de conocimiento cubre la formulación de softmax online, el tiling y la selección del tamaño de bloque, la vectorización de CPU, el threading y cómo interrogar a la máquina host en lugar de asumir una ISA. Superar a BLAS necesita la mayoría de ellos.

Cómo funciona

El directorio de ejecución

runs/<run-id>/
  work/              the candidate x_t — a standalone git repo whose history IS the lineage
    .avo/scores.jsonl    every committed version's full score vector
  kb/                the knowledge base K, copied in so paths are stable
  avo-eval           f, as a zero-argument shim the agent can call at will
  NOTES.md           scratch space that survives across steps
  trajectory.jsonl   every step, accepted or rejected
  rejected/          the diff of each rejected candidate, kept for the record
  logs/              evaluator and agent logs

Hacer del linaje un repositorio git significa que el agente inspecciona P_t con herramientas que ya conoce — git log, git show v7:attention.c, git diff v6 v7 — en lugar de una API a medida. Cada versión aceptada es un commit etiquetado vN cuyo mensaje lleva el vector de puntuación.

La política de commit

Artículo §3.2: un candidato se confirma solo si pasa la compuerta de corrección y iguala o mejora la mejor puntuación confirmada hasta ahora. Cualquier otra cosa se revierte y su diff se archiva — sigue siendo parte de la trayector de búsqueda interna del agente, pero nunca entra en el linaje.

La corrección es una compuerta, no una dimensión. Un candidato que falla puntúa cero independientemente de lo que midiera (§3.1). En attention_c eso significa que un kernel que es 10× más rápido y numéricamente incorrecto vale exactamente lo mismo que uno que no compila.

El vector de puntuación

Modo desatendido

Para reproducir la configuración del artículo, donde el operador es un agente generado y nadie está mirando:

avo run --target attention_c --backend claude_cli --max-steps 40 --time 12h
avo run --resume runs/attention_c-20260321-091500 --time 24h

Backends: claude_cli (Claude Code sin interfaz, el análogo más cercano al agente del artículo), api (un bucle de agente autónomo en la API de Messages, para quienes solo tienen una clave de API), agent_sdk (en proceso mediante claude-agent-sdk) y mock (un comando de shell, para probar el mecanismo sin un modelo).

Esto gasta cuota o créditos en cada paso. El modo sesión no.


Añadir tu propio objetivo

Un objetivo es un directorio con un target.yaml, un programa semilla, una base de conocimiento y un evaluador. El evaluador es cualquier ejecutable en cualquier idioma; todo el contrato es un objeto JSON en la salida estándar:

{"correct": true,
 "metrics": {"config_a": 1520.3, "config_b": 1477.0},
 "error": null,
 "notes": "shown to the agent"}

correct es la puerta. metrics es el vector de puntuaciones. El escalar que se optimiza es su media geométrica a menos que proporciones un primary explícito.

name: my_target
description: One line, shown in `avo targets`.
seed: seed                 # copied to work/ as x_0
knowledge_base: kb         # copied to the run dir as K
entrypoint: kernel.c       # informational, used in prompts

evaluate:
  command: ["python3", "{target}/eval.py", "--workdir", "{workdir}"]
  timeout: 30m

baselines:                 # optional, measured once before evolution starts
  command: ["python3", "{target}/eval.py", "--baselines"]

score:
  direction: maximize

agent:
  goal: |
    What the agent is actually trying to do, and what the trade-offs are.

Consulta docs/TARGETS.md para el contrato completo y tests/fixtures/toy/ para un ejemplo mínimo funcional.

La base de conocimiento merece un esfuerzo real. Es la K en Agent(P_t, K, f), y la diferencia entre un agente que redescubre el particionado desde primeros principios en diez pasos y uno que llega en dos.


Qué es fiel y qué no

Fiel:

  • la formulación del operador Vary(P_t) = Agent(P_t, K, f) — un agente de codificación real con edición de archivos, acceso al shell y memoria persistente, sin modificaciones específicas de la tarea

  • evolución continua de un solo linaje con estado respaldado por git (§3.3)

  • la puerta de corrección y el vector de puntuación n-dimensional (§3.1)

  • la política de confirmación que iguala o mejora, con los intentos fallidos excluidos del linaje (§3.2)

  • la intervención del supervisor ante el estancamiento y los ciclos improductivos (§3.3)

  • agregación por media geométrica en las configuraciones de referencia y gráficos de trayectoria de las Figuras 5/6

No fiel, y deliberadamente:

  • El hardware. El artículo evoluciona kernels de atención en GPUs B200 contra cuDNN y FlashAttention-4. attention_c es el mismo problema en CPU contra NumPy/BLAS. Las optimizaciones se transfieren en especie (particionado, softmax en línea, vectorización, planificación), no en magnitud.

  • La escala. El artículo ejecutó 7 días, 40 versiones confirmadas, más de 500 direcciones exploradas. Una ejecución en modo sesión de 10 a 20 pasos es una demostración, no una réplica.

  • Estructura de población. Al igual que el artículo, esto implementa el caso de un solo linaje para aislar el operador. Los regímenes basados en archivos y en islas son compatibles con la formulación, pero no están implementados.


Estructura del repositorio

src/avo/
  types.py        Score, LineageEntry, the correctness gate, geomean
  config.py       target specs and run configuration
  lineage.py      P_t as git history
  scoring.py      f as an external process
  knowledge.py    K
  prompts.py      the variation and supervisor prompts — the whole framework/agent interface
  run.py          run state: seed, evaluate, commit policy, trajectory
  session.py      driver: the session you already have is the operator
  loop.py         driver: unattended, spawns an agent per step
  mcp_server.py   the same operations as MCP tools (no dependencies)
  cli.py          the same operations as subcommands
  plot.py         Figure 5/6
  agents/         backends for unattended mode
targets/
  game2048/       policy evolution under a time budget
  attention_c/    kernel evolution — the paper's domain, on a CPU
examples/
  attention-decode-run/  beats Apple's own fused kernel by changing the maths
  attention-c-run/       CPU kernel evolution, with an honest baseline caveat
  attention-metal-run/   GPU prefill — every CUDA instinct measured worse
  game2048-run/          policy evolution — 50x the seed
docs/
  PAPER_MAP.md    every section of the paper, and where it lives in the code
  TARGETS.md      the evaluator contract
  DRIVING.md      how to drive a run from Claude Code, Codex, or a shell
AGENTS.md         cross-agent instructions (read automatically by Codex)
.claude/skills/   the `/avo` skill for Claude Code

Cómo citar

Esta es una reproducción independiente. Cita la obra original:

@article{chen2026avo,
  title  = {AVO: Agentic Variation Operators for Autonomous Evolutionary Search},
  author = {Chen, Terry and Ye, Zhifan and Xu, Bing and Ye, Zihao and Liu, Timmy
            and Hassani, Ali and Chen, Tianqi and Kerr, Andrew and Wu, Haicheng
            and Xu, Yang and Chen, Yu-Jung and Chen, Hanfeng and Kane, Aditya
            and Krashinsky, Ronny and Liu, Ming-Yu and Grover, Vinod and Ceze, Luis
            and Bringmann, Roger and Tran, John and Liu, Wei and Xie, Fung
            and Lightstone, Michael and Shi, Humphrey},
  journal = {arXiv preprint arXiv:2603.24517},
  year    = {2026}
}

Licenciado bajo Apache-2.0. No está afiliado ni respaldado por NVIDIA.

A
license - permissive license
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI-powered code review and improvement, including analysis, refactoring suggestions, and automatic test generation, with an optional agentic loop for iterative refinement.
    MIT
  • A
    license
    B
    quality
    A
    maintenance
    Local-first Agent OS that wraps Claude Code, Codex CLI, and other coding agents in a replayable Seed → Ledger → Runtime contract, driven by an interview → seed → execute → evaluate → evolve workflow loop.
    34
    5,634
    MIT

View all related MCP servers

Related MCP Connectors

  • Adaptive plan/build/review cycles for AI coding assistants, persisted across sessions.

  • Cross-agent artifact workspace with provenance across Claude Code, Codex, Cursor, LangGraph.

  • Persistent cloud development environments that coding agents create, run and test software in.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/gatordevin/avo'

If you have feedback or need assistance with the MCP directory API, please join our Discord server