cursos:sdd:08-skills-agentes
Diferencias
Muestra las diferencias entre dos versiones de la página.
| Ambos lados, revisión anteriorRevisión previaPróxima revisión | Revisión previa | ||
| cursos:sdd:08-skills-agentes [2026/11/05 22:22] – borrado - editor externo (Fecha desconocida) 127.0.0.1 | cursos:sdd:08-skills-agentes [2026/11/06 08:37] (actual) – Renumerar el curso: Estructura de un skill pasa al 10 y los temas siguientes suben un número claude | ||
|---|---|---|---|
| Línea 1: | Línea 1: | ||
| + | ====== 8. Skills y agentes ====== | ||
| + | |||
| + | Las //skills// y los agentes son los dos ficheros markdown con instrucciones, | ||
| + | |||
| + | Más información: | ||
| + | |||
| + | * [[https:// | ||
| + | * [[https:// | ||
| + | * [[https:// | ||
| + | |||
| + | ---- | ||
| + | |||
| + | ===== 1. Qué es una skill ===== | ||
| + | |||
| + | Una //skill// es un fichero '' | ||
| + | |||
| + | Se carga **dentro de tu conversación**: | ||
| + | |||
| + | ===== 2. Agente principal y subagentes ===== | ||
| + | |||
| + | Un agente es un fichero con las instrucciones para **hacer un trabajo cerrado y devolver un resultado**. En OpenCode, Plan y Build son los agentes // | ||
| + | |||
| + | El subagente **empieza con el contexto vacío**: solo tiene su fichero y el prompt que le escribe el principal. Al terminar, al principal solo le vuelve su respuesta. | ||
| + | |||
| + | ===== 3. Dónde se guardan ===== | ||
| + | |||
| + | En OpenCode, dentro de '' | ||
| + | |||
| + | <sxh text; | ||
| + | .opencode | ||
| + | ├── skills | ||
| + | │ | ||
| + | │ | ||
| + | │ | ||
| + | │ | ||
| + | │ | ||
| + | └── agents | ||
| + | ├── revisor-tests.md | ||
| + | └── verificador-spec.md | ||
| + | </ | ||
| + | |||
| + | * **Cada //skill// va en su propia carpeta**, con el nombre de la //skill//, y dentro el fichero se llama siempre '' | ||
| + | * **Todos los agentes van en una única carpeta**, '' | ||
| + | |||
| + | <note warning> | ||
| + | |||
| + | ---- | ||
| + | |||
| + | ===== 4. El frontmatter ===== | ||
| + | |||
| + | Los dos ficheros empiezan con una **cabecera en YAML entre dos líneas '' | ||
| + | |||
| + | <sxh yaml; | ||
| + | --- | ||
| + | name: servicios | ||
| + | description: | ||
| + | errores de negocio). Usar al escribir, revisar o probar una clase *Service. | ||
| + | --- | ||
| + | </ | ||
| + | |||
| + | <sxh yaml; | ||
| + | --- | ||
| + | description: | ||
| + | Usar después de escribir o cambiar los tests de una clase *Service, antes del commit. | ||
| + | mode: subagent | ||
| + | permission: | ||
| + | edit: deny | ||
| + | --- | ||
| + | </ | ||
| + | |||
| + | En la //skill//: | ||
| + | |||
| + | * '' | ||
| + | * '' | ||
| + | |||
| + | En el agente no hay '' | ||
| + | |||
| + | * '' | ||
| + | * '' | ||
| + | * '' | ||
| + | |||
| + | ==== La descripción ==== | ||
| + | |||
| + | **La '' | ||
| + | |||
| + | Tiene que decir **qué hace y cuándo usarlo**, con las palabras con las que se pedirá la tarea: | ||
| + | |||
| + | <sxh yaml> | ||
| + | # ✅ qué cubre, cuándo usarla y con qué palabras se pide | ||
| + | description: | ||
| + | errores de negocio). Usar al escribir, revisar o probar una clase *Service. | ||
| + | |||
| + | # ❌ no dice cuándo: no se carga nunca | ||
| + | description: | ||
| + | |||
| + | # ❌ cuenta el proceso, que va en el cuerpo, y no dice cuándo | ||
| + | description: | ||
| + | </ | ||
| + | |||
| + | ---- | ||
| + | |||
| + | ===== 5. Skill o agente ===== | ||
| + | |||
| + | ^ ^ Skill ^ Agente ^ | ||
| + | | Dónde trabaja | En tu conversación | En un contexto nuevo, vacío | | ||
| + | | Qué ve | Todo lo que habéis hablado | Solo su fichero y el prompt que le pasan | | ||
| + | | Qué queda en tu contexto | Todo lo que lee y hace | Solo su respuesta | | ||
| + | | Para qué | Saber cómo se hace algo en el proyecto o seguir un procedimiento contigo | Encargar un trabajo y recibir un resultado | | ||
| + | |||
| + | Como ya hemos visto en ambos casos hay unas instrucciones que son lo que llevan en su fichero. | ||
| + | |||
| + | <note tip> | ||
| + | La única diferencia real entre skill y agente es que el agente lanza un nuevo " | ||
| + | </ | ||
| + | |||
| + | Y ahora viene lo más interesante: | ||
| + | |||
| + | <sxh text; | ||
| + | .opencode | ||
| + | ├── skills | ||
| + | │ | ||
| + | │ | ||
| + | │ | ||
| + | │ | ||
| + | └── agents | ||
| + | ├── repository-jpa.md | ||
| + | └── generar-tests.md | ||
| + | </ | ||
| + | |||
| + | **Ejemplo 1: cómo se hace un '' | ||
| + | |||
| + | <sxh yaml; | ||
| + | --- | ||
| + | name: repository-jpa | ||
| + | description: | ||
| + | o modificar una interfaz *Repository. | ||
| + | --- | ||
| + | |||
| + | # Repositorios JPA | ||
| + | |||
| + | - La interfaz extiende `JpaRepository< | ||
| + | - Los métodos derivados se llaman `findBy...`; | ||
| + | se escribe con `@Query` en JPQL. Nunca SQL nativo. | ||
| + | - Las búsquedas que pueden devolver muchas filas reciben `Pageable` y devuelven `Page< | ||
| + | - Las consultas usan `JOIN FETCH` para las relaciones que se van a leer. | ||
| + | </ | ||
| + | |||
| + | <sxh yaml; | ||
| + | --- | ||
| + | description: | ||
| + | o modificar una interfaz *Repository. | ||
| + | mode: subagent | ||
| + | --- | ||
| + | |||
| + | # Repositorios JPA | ||
| + | |||
| + | - La interfaz extiende `JpaRepository< | ||
| + | - Los métodos derivados se llaman `findBy...`; | ||
| + | se escribe con `@Query` en JPQL. Nunca SQL nativo. | ||
| + | - Las búsquedas que pueden devolver muchas filas reciben `Pageable` y devuelven `Page< | ||
| + | - Las consultas usan `JOIN FETCH` para las relaciones que se van a leer. | ||
| + | </ | ||
| + | |||
| + | **Ejemplo 2: generar los tests de una clase.** El fichero dice **cómo hacer un trabajo cerrado** del que interesa el resultado: el test terminado y si pasa. Otra vez el mismo cuerpo en los dos: | ||
| + | |||
| + | <sxh yaml; | ||
| + | --- | ||
| + | name: generar-tests | ||
| + | description: | ||
| + | y la deja pasando. Usar cuando se pida crear los tests de una clase. | ||
| + | --- | ||
| + | |||
| + | # Generar tests | ||
| + | |||
| + | 1. Lee la clase y apunta sus métodos públicos. | ||
| + | 2. Escribe `< | ||
| + | al menos un test por método público y uno por cada `ErrorDeNegocio` que lance. | ||
| + | 3. Ejecuta `mvn test -Dtest=< | ||
| + | 4. Si algún test falla, corrígelo y vuelve a ejecutar hasta que pasen todos. | ||
| + | 5. Termina diciendo el fichero creado, cuántos tests tiene y si pasan. | ||
| + | </ | ||
| + | |||
| + | <sxh yaml; | ||
| + | --- | ||
| + | description: | ||
| + | y la deja pasando. Usar cuando se pida crear los tests de una clase. | ||
| + | mode: subagent | ||
| + | --- | ||
| + | |||
| + | # Generar tests | ||
| + | |||
| + | 1. Lee la clase y apunta sus métodos públicos. | ||
| + | 2. Escribe `< | ||
| + | al menos un test por método público y uno por cada `ErrorDeNegocio` que lance. | ||
| + | 3. Ejecuta `mvn test -Dtest=< | ||
| + | 4. Si algún test falla, corrígelo y vuelve a ejecutar hasta que pasen todos. | ||
| + | 5. Termina diciendo el fichero creado, cuántos tests tiene y si pasan. | ||
| + | </ | ||
| + | |||
| + | El cuerpo del fichero es el **prompt** que se carga, igual en la //skill// que en el agente: en la //skill// se añade a tu conversación y en el agente va a un contexto nuevo. Lo que escribes tú para que arranque también es lo mismo en los dos casos: para el ejemplo 1, «Crea el repository de '' | ||
| + | |||
| + | ==== Ejemplo 1 como skill ==== | ||
| + | |||
| + | Es lo que debería ser. El fichero se carga en tu conversación y el agente principal escribe '' | ||
| + | |||
| + | ==== Ejemplo 1 como agente ==== | ||
| + | |||
| + | No pasa absolutamente nada. El principal lanza el agente, que arranca con el contexto vacío y lee su fichero. Y en ese fichero **no se le dice que haga nada**: son cuatro reglas sobre cómo son los repositorios, | ||
| + | |||
| + | En el mejor de los casos, el agente devuelve las reglas en su respuesta y el principal las usa: has pagado un proceso aparte para traer al contexto el mismo texto que la //skill// habría puesto directamente. En el peor, cada vez que el principal necesite saber cómo va un repository tendrá que lanzarlo otra vez para que vuelva a leer el mismo fichero. Conocimiento en un agente es conocimiento que nadie conserva. | ||
| + | |||
| + | ==== Ejemplo 2 como agente ==== | ||
| + | |||
| + | Es lo que debería ser. El principal lanza el agente con «Genera los tests de '' | ||
| + | |||
| + | ==== Ejemplo 2 como skill ==== | ||
| + | |||
| + | El trabajo también se hace, y se hace igual de bien: el principal carga el fichero y hace lo mismo que haría el agente. La diferencia es **dónde se queda todo eso**: la clase leída, el test escrito, la salida de '' | ||
| + | |||
| + | |||
| + | ==== Resumen ==== | ||
| + | |||
| + | ^ ^ Como skill ^ Como agente ^ | ||
| + | | Ejemplo 1: cómo se hace un repository JPA | ✓ Las reglas se quedan y valen para el resto de la conversación | No hay nada que hacer: el fichero son reglas, no una tarea. Como mucho las recita, y mueren con él | | ||
| + | | Ejemplo 2: generar los tests de una clase | Funciona, pero los ficheros leídos, las salidas de '' | ||
| + | |||
| + | ==== Un caso especial ==== | ||
| + | |||
| + | ¿Y si lanzas como //skill// algo que debería ser agente, el generador de tests, **nada más empezar la conversación**, | ||
| + | |||
| + | Piensa qué tienes: un contexto vacío al que se le añade el fichero y tu mensaje, trabaja, y lo que haya acumulado desaparece al cerrar porque nadie sigue hablando ahí. **Es exactamente un agente**, con la diferencia de que el resultado se lo has dado tú al principal en vez de leerlo él. La //skill// no ha llenado nada que vayas a pagar después. Así que la pregunta de fondo no es «¿esto es una skill o un agente?», sino «**¿voy a seguir trabajando en esta conversación con lo que quede en el contexto? | ||
| + | |||
| + | ---- | ||
| + | |||
| + | ===== 6. El SKILL.md ===== | ||
| + | |||
| + | Una //skill// **no lleva entradas ni salida**: trabaja dentro de tu conversación, | ||
| + | |||
| + | <sxh markdown; | ||
| + | --- | ||
| + | name: servicios | ||
| + | description: | ||
| + | errores de negocio). Usar al escribir, revisar o probar una clase *Service. | ||
| + | --- | ||
| + | |||
| + | # servicios | ||
| + | |||
| + | Reglas de las clases `*Service` del servidor. | ||
| + | |||
| + | ## Convenciones | ||
| + | |||
| + | - Un servicio por agregado: `PedidoService`, | ||
| + | - Valida al entrar y lanza `ErrorDeNegocio` con el código del requisito de `specs/`. | ||
| + | - No devuelve entidades: devuelve DTOs. | ||
| + | |||
| + | ## Ejemplos | ||
| + | |||
| + | - ✅ `throw new ErrorDeNegocio(" | ||
| + | - ❌ `throw new IllegalStateException(" | ||
| + | </ | ||
| + | |||
| + | Cómo se organiza por dentro una //skill// grande está en [[cursos: | ||
| + | |||
| + | ---- | ||
| + | |||
| + | ===== 7. El fichero del agente ===== | ||
| + | |||
| + | Un agente sí necesita entradas y salida, porque **no ve tu conversación** y **lo que devuelve lo lee otro agente**. Así que su cuerpo lleva **siempre** estas tres secciones, en este orden: | ||
| + | |||
| + | * **''## | ||
| + | * **''## | ||
| + | * **''## | ||
| + | |||
| + | <sxh markdown; | ||
| + | --- | ||
| + | description: | ||
| + | Usar después de escribir o cambiar los tests de una clase *Service, antes del commit. | ||
| + | mode: subagent | ||
| + | permission: | ||
| + | edit: deny | ||
| + | --- | ||
| + | |||
| + | # Revisor de tests | ||
| + | |||
| + | Revisas los tests de una clase. No arreglas nada: solo dices qué está mal. | ||
| + | |||
| + | ## Entradas | ||
| + | |||
| + | Te llegan en el prompt: | ||
| + | - `clase`: ruta de la clase que se prueba. | ||
| + | - `test`: ruta de su clase de test. | ||
| + | |||
| + | ## Proceso | ||
| + | |||
| + | 1. Lee `clase` y apunta sus métodos públicos. | ||
| + | 2. Lee `test` y busca al menos un test por cada método público. | ||
| + | 3. Comprueba que cada test tiene aserciones y que no copia valores del código | ||
| + | de producción (el IVA escrito a mano en vez de leerlo). | ||
| + | 4. En la duda, cuéntalo como problema. | ||
| + | |||
| + | ## Salida | ||
| + | |||
| + | La primera línea es exactamente `PASS` o `FAIL`. Con `PASS` no se escribe nada más. | ||
| + | Con `FAIL`, debajo, una línea por problema con el formato `fichero: | ||
| + | - `fichero`: ruta relativa a la raíz del proyecto. | ||
| + | - `inicio-fin`: | ||
| + | - `descripcion`: | ||
| + | </ | ||
| + | |||
| + | <note important> | ||
| + | |||
| + | ==== La salida: PASS o FAIL ==== | ||
| + | |||
| + | El agente termina con **una sola palabra en la primera línea**: '' | ||
| + | |||
| + | Con '' | ||
| + | |||
| + | <sxh markdown> | ||
| + | FAIL | ||
| + | src/ | ||
| + | src/ | ||
| + | src/ | ||
| + | </ | ||
| + | |||
| + | <sxh markdown> | ||
| + | PASS | ||
| + | </ | ||
| + | |||
| + | ---- | ||
| + | |||
| + | ===== Ejercicios ===== | ||
| + | |||
| + | ==== Ejercicio 1 ==== | ||
| + | |||
| + | Di si cada tarea se hace con una //skill// o con un agente, y por qué: | ||
| + | |||
| + | ^ Tarea ^ Skill o agente ^ Por qué ^ | ||
| + | | Las convenciones de los controladores REST del proyecto | | | | ||
| + | | Comprobar que cada requisito de '' | ||
| + | | Cómo se escribe un mensaje de commit en el equipo | | | | ||
| + | | Revisar el servicio que se acaba de escribir | | | | ||
| + | |||
| + | ==== Ejercicio 2 ==== | ||
| + | |||
| + | Escribe la //skill// '' | ||
| + | |||
| + | Abre **una conversación nueva** y pide «crea el controlador de '' | ||
| + | |||
| + | ==== Ejercicio 3 ==== | ||
| + | |||
| + | Escribe el agente '' | ||
| + | |||
| + | Abre **una conversación nueva** y lánzalo con '' | ||
