TL;DR: Mi agente IA tenía un fichero de instrucciones de 246 líneas para gestionar issues en Linear. 150 de esas líneas eran workarounds: UUIDs hardcodeados, fallbacks a curl, notas de «la CLI no soporta X». No las reescribí — construí una herramienta que las hizo innecesarias. Ahora esas 150 líneas son cero.
¿Alguna vez has escrito un documento de instrucciones tan largo que su propia longitud demuestra que algo está mal?
No me refiero a documentación legítima. Me refiero a esos ficheros que empiezan diciendo «usa la herramienta X» y luego dedican el 80% del texto a explicar cuándo la herramienta X no funciona y qué hacer en su lugar. Instrucciones que son, en realidad, una lista de disculpas por la herramienta que deberían haber construido.
Yo tenía uno de esos. Y era vergonzoso.
Anatomía de 150 líneas de basura
El contexto: trabajo con un agente IA (Claude Code) que gestiona mis issues en Linear. Para que el agente supiera cómo hacerlo, tenía un skill — un fichero de instrucciones que el agente lee cuando necesita crear, listar o actualizar issues.
El fichero tenía 246 líneas. De esas, unas 100 eran documentación legítima: qué comandos existen, qué teams hay, qué labels usar. Razonable.
Las otras 150 eran basura defensiva. Tres categorías:
~30 líneas de UUIDs hardcodeados. La CLI que usaba no soportaba --project. Así que el skill incluía 17 UUIDs (5 teams + 12 projects) en una tabla XML. El agente tenía que buscar el UUID correcto y construir una mutación GraphQL a mano para asignar un proyecto. Una operación que debería ser --project Tokamak requería memorizar un UUID de 36 caracteres.
~25 líneas de fallbacks a curl. La CLI no tenía búsqueda. Ni filtrado por proyecto. Ni asignación de proyecto en create. Tres operaciones básicas, tres bloques de curl con queries GraphQL incrustadas, escaping de comillas, y cabeceras de autenticación. Cada uno era una bomba de relojería esperando a que el agente se comiera una comilla.
~15 líneas de «NO soporta X». Cinco avisos de «la CLI NO soporta» y dos de «OBLIGATORIO» (–sort y –no-pager en cada list). Fíjate bien: estaba documentando las carencias de la herramienta dentro de las instrucciones de uso de la herramienta. Es como si el manual de un coche dedicara tres páginas a explicar que el limpiaparabrisas solo funciona si primero le das un golpe al salpicadero.
~80 líneas de contexto defensivo. Una sección entera titulada «cuándo usar la API en vez de la CLI». Tablas de mapeo directorio→UUID. Heurísticas para elegir labels. Reglas sobre qué hacer cuando la CLI se cuelga. Material que solo existía porque la herramienta era incapaz.
El cartel de «cuidado, escalón»
Cuando una herramienta tiene una interfaz incómoda, la reacción natural es documentar los workarounds. Escribes instrucciones. Pones avisos. Creas una sección de «errores comunes». Y cuanto más detallada es la documentación, más te convences de que el problema está resuelto.
Pero no lo está. Has puesto un cartel de «cuidado, escalón» en vez de arreglar el escalón.
Y cuando el usuario de esas instrucciones es un LLM, el problema se multiplica. Un humano lee «NO soporta –project» y se acuerda (más o menos). Un LLM lo lee, lo procesa, y tres turnos de conversación después usa --project de todas formas. No es que sea tonto — es que optimiza para completar la tarea, y --project es el camino lógico para asignar un proyecto. La prohibición es ruido en un mar de señales.
Ya escribí sobre esto en otro post: las instrucciones verbosas a un LLM son el equivalente exacto de poner carteles. El LLM no los ignora por rebeldía. Los ignora porque su función es encontrar el camino más directo, y «no uses –project, en su lugar busca el UUID en esta tabla y luego haz un curl con esta query GraphQL» no es un camino directo — es una ñapa.
La solución no era un skill mejor
Podría haber reescrito el skill con mejores instrucciones. Más claras. Con ejemplos. Con diagramas. Podría haber subido de 246 a 400 líneas y cubrir cada caso borde.
Habría sido como ampliar el cartel.
Lo que hice fue construir lql — una CLI en Rust diseñada específicamente para que un agente IA (o un humano, pero sobre todo un agente) pudiera interactuar con Linear sin necesitar un manual de supervivencia.
La filosofía de diseño era una sola frase: el camino incorrecto no debe estar prohibido, debe ser imposible.
Para entendernos: no prohíbes --status en la documentación — haces que funcione. No documentas que --project no existe en create — haces que exista. No mantienes una tabla de UUIDs — resuelves nombres automáticamente. No ofreces fallbacks a curl — no hay nada que no pueda hacer la herramienta. No pones «OBLIGATORIO: –sort» — pones un default sensato.
Lo que desapareció
Aquí está el inventario de lo que eliminé:
| Basura defensiva | Líneas eliminadas | Motivo de eliminación |
|---|---|---|
| UUIDs hardcodeados (17 IDs) | ~30 | lql resuelve nombres automáticamente |
Fallbacks a curl + GraphQL |
~25 | lql tiene search, project, relate nativos |
| Notas «NO soporta X» (5) | ~15 | Todo lo que el agente espera, existe |
| Flags «OBLIGATORIOS» (2) | ~5 | Defaults sensatos, no flags obligatorios |
| Sección «cuándo usar API vs CLI» | ~15 | No hay «vs» — lql puede con todo |
| Tabla de mapeo contexto→UUID (XML) | ~20 | Auto-detección desde config TOML |
| Heurísticas y reglas defensivas | ~40 | La herramienta es tolerante, sobran |
| Total | ~150 |
Lo que queda es documentación legítima: qué comandos existen, qué teams hay, qué labels usar. Cero workarounds. Cero disculpas.
Por qué funciona (la parte interesante)
La reducción de líneas es vistosa, pero no es lo importante. Lo importante es por qué las líneas sobraban.
Cada línea de workaround en el skill antiguo existía porque la herramienta subyacente era frágil e intolerante. Frágil porque fallaba ante inputs razonables (--status en vez de --state). Intolerante porque rechazaba sin alternativa (--project no existe, apáñatelas).
Cuando sustituyes una herramienta frágil por una tolerante, las instrucciones se simplifican automáticamente. No tienes que reescribir el manual — el manual se reescribe solo porque ya no hay nada que advertir.
Es el mismo principio que explica por qué el manual de un iPhone tiene 10 páginas y el de una impresora tiene 200. No es que Apple escriba mejor documentación. Es que el iPhone no necesita que le expliques cómo cargar papel, alinear cabezales, o limpiar el tambor.
Una herramienta tolerante genera documentación corta. Una herramienta frágil genera manuales de supervivencia.
Y cuando el usuario es un LLM, esto importa el doble. Cada línea de instrucciones es una línea que puede malinterpretar, olvidar o contradecir. Un skill con 150 líneas de workarounds le da 150 oportunidades de seguir un workaround mal. Uno con cero workarounds le da… cero oportunidades de equivocarse.
El patrón general
Esto no es exclusivo de CLIs ni de Linear. El patrón es universal:
- Tienes una herramienta con interfaz incómoda
- Escribes instrucciones detalladas para compensar
- Las instrucciones se convierten en un manual de supervivencia
- Alguien (humano o LLM) ignora parte del manual
- Las cosas se rompen
- Añades más instrucciones
- Vuelve al paso 4
La salida del bucle no es escribir instrucciones mejores. Es arreglar la herramienta.
Si tu CLAUDE.md tiene más de 20 líneas dedicadas a explicar cómo no usar algo, ese algo necesita ser reescrito. Si tu skill tiene una sección de «errores comunes y cómo evitarlos», esos errores deberían ser imposibles, no documentados.
Cada cartel de «cuidado, escalón» es una confesión de que no arreglaste el escalón.
Tu turno
La próxima vez que te descubras escribiendo instrucciones verbosas para compensar una herramienta incómoda — ya sea un CLAUDE.md, un README, o un wiki interno — para un momento y pregúntate:
- ¿Estoy documentando cómo usar la herramienta, o cómo sobrevivir a la herramienta?
- ¿Cuántas líneas desaparecerían si la herramienta aceptara los inputs que el usuario naturalmente le daría?
- ¿Estoy poniendo un cartel o arreglando el escalón?
Si más del 30% de tus instrucciones son workarounds, la herramienta está rota. No el usuario. No la documentación. La herramienta.
Arregla el escalón.
Serie: Adversarial Programming
- Anterior: Adversarial programming: cuando tu copiloto IA inventa APIs
- Primero: El camino incorrecto no debe estar prohibido, debe ser imposible
Read this article in English.



