- Identificar capacidades necesarias para una tarea.
- Evitar coleccionar herramientas innecesarias.
- Crear un perfil reproducible.
Capacidades mínimas
Para revisar código quizá necesites búsqueda, lectura y tests. Para resumir documentos no necesitas shell. Cada herramienta adicional aumenta la superficie de error y las decisiones que debes auditar.
- Modelo: proveedor, nombre y parámetros.
- Herramientas: archivos, terminal, web o APIs, solo cuando hagan falta.
- Política: qué acciones requieren confirmación.
- Observabilidad: logs y evidencia de ejecución.
Cómo se compone un Profile
Un perfil contiene un `package.json` con dependencias de plugins y un manifiesto `dsh.profile` con la lista ordenada de bundles. Además tiene un `cordis.patch.yml` con tu capa de configuración.
La CLI compone primero los parches de los bundles, después el patch del perfil, luego `$DSH_HOME/cordis.patch.yml` y finalmente los overlays pasados con `--patch`.
Orden conceptual: 1. bundles del profile 2. cordis.patch.yml del profile 3. $DSH_HOME/cordis.patch.yml 4. overlays --patch # Inspeccionar sin arrancar dsh --profile web --dump-default-config dsh --profile web --dump-config
Tu primer plugin mínimo
La guía oficial de desarrollo empieza con un plugin TypeScript que exporta `name` y una función `apply(ctx)`. Cordis llama a `apply` al cargarlo y el contexto permite registrar capacidades.
Para probarlo en Web UI desde un checkout del repo, crea un patch con ruta absoluta y arranca `pnpm dsh web --patch ./scratch-plugin/cordis.yml`.
import type { Context } from '@deepseek-ai/cordis'
export const name = 'hello-plugin'
export function apply(ctx: Context) {
console.log('[hello-plugin] plugin loaded!')
}Dependencias y limpieza
Si un plugin usa un servicio como `tools`, declara `inject = ['tools']`; Cordis espera a que el servicio esté disponible antes de cargarlo.
Todo lo registrado a través de `ctx` se limpia al descargar el plugin. Para recursos externos, como sockets o timers, usa `ctx.effect()` y devuelve un disposer.
export const name = 'my-tool-plugin'
export const inject = ['tools']
export function apply(ctx) {
ctx.tools.register(/* ... */)
ctx.effect(() => {
const timer = setInterval(() => {}, 5000)
return () => clearInterval(timer)
})
}Prueba de regresión
Después de añadir un plugin, repite una tarea corta que ya conocías. Si el resultado empeora, aumenta coste o introduce acciones no solicitadas, vuelve al perfil anterior.
Perfil: revision-solo-lectura Herramientas: buscar, leer Prohibido: escribir, red, comandos destructivos Salida: hallazgos con ruta y línea
Si has guardado la evidencia de esta lección, continúa con «Subagentes, skills y orquestación». Si no, repite la comprobación antes de avanzar.