+250 skills, dinamita para tu productividad 🧨Explorar →

DeepSeek Harness: el agente open source donde todo es un plugin

DeepSeek ha publicado su propio agent harness y no es otro clon de Claude Code con la marca cambiada.

Se llama DeepSeek Harness, el comando es dsh, la licencia es MIT y arranca con una interfaz web en el navegador, no en la terminal. Pero lo que de verdad merece un rato de tu tiempo no es la interfaz: es la frase que preside el repositorio.

Everything is a Plugin.

Todo. El adaptador del modelo es un plugin. El registro de herramientas es un plugin. El log de sesión es un plugin. Y el bucle del agente —la pieza que en cualquier otra herramienta es el corazón intocable— también es un plugin. No hay un núcleo privilegiado que parchear.

Esto es lo que vamos a ver:

  1. Qué es dsh y en qué se diferencia de los agentes que ya usas
  2. Cómo instalarlo y tener un agente trabajando en cinco minutos
  3. Qué significa “todo es un plugin” cuando bajas al código
  4. Perfiles, bundles y capas: el sistema de configuración que lo sostiene
  5. Cómo escribir, empaquetar y publicar tu propia herramienta
  6. Qué trae de serie (MCP, skills, subagentes, sandbox, Ralph)
  7. Los cuatro modos de ejecución, incluido el que escribe programas en vez de llamar herramientas
  8. Por qué presume de que cada ejecución es trazable
  9. Si merece la pena hoy o conviene esperar

⚠️ Antes de nada, la advertencia que el propio repositorio pone en mayúsculas: DeepSeek Harness está en developer preview y su versión actual es la 0.1.0-rc.5. “THERE WILL BE COMPATIBILITY-BREAKING CHANGES”, dicen. Créetelo.

¿Qué es DeepSeek Harness y en qué se diferencia de Claude Code o Codex?

DeepSeek Harness es un agent harness: el andamiaje que rodea a un modelo para que pueda leer archivos, editarlos, ejecutar comandos, delegar trabajo y mantener un plan. Lo publica DeepSeek AI bajo licencia MIT y el repositorio supera las 100.000 estrellas en GitHub, una cifra que dice más del interés por la marca DeepSeek que de la madurez del proyecto.

La palabra “harness” es la clave y conviene no traducirla mal. No es un modelo. No es un IDE. Es el arnés: la capa que convierte un modelo de lenguaje en algo que trabaja sobre tu repositorio.

La propia página del proyecto lo resume en una ecuación que me parece la mejor definición corta que he leído: Agente = Modelo + Harness. El modelo es el alma del agente; el harness es lo que le permite entender su entorno, usar herramientas y seguir trabajando en condiciones reales. Cuando un agente falla en tu proyecto, muchas veces el problema no está en el modelo: está en el arnés.

¿Y en qué se diferencia de lo que ya tienes instalado? En dónde ponen el límite de lo que puedes tocar.

Aspecto Claude Code OpenCode DeepSeek Harness
Superficie principal Terminal Terminal Interfaz web local
Extensibilidad Skills, plugins, MCP, hooks Plugins, MCP Todo el árbol de plugins, incluido el bucle del agente
Modelo por defecto Claude Configurable DeepSeek V4
Núcleo modificable No Parcial Sí, por configuración
Madurez Producto estable Estable Developer preview

Si vienes de comparar los dos primeros, ya sabes que la elección entre Claude Code y OpenCode se juega sobre todo en ergonomía y precio. Con dsh la comparación cambia de eje.

La diferencia real está en la última fila de extensibilidad. En Claude Code puedes añadir cosas alrededor del agente: skills, servidores MCP, hooks. En dsh puedes sustituir el agente. El bucle que decide cuándo pedir otra respuesta al modelo es una fila más en un fichero de configuración, y puedes reemplazarla por la tuya sin tocar el código del proyecto.

🔑 La pregunta que define si esta herramienta es para ti: ¿alguna vez te has topado con un límite de tu agente de IA y has pensado “esto lo arreglaría en diez minutos si pudiera meter mano por dentro”? Si la respuesta es sí, sigue leyendo. Si nunca te ha pasado, dsh te va a parecer una complicación innecesaria.

¿Cómo instalar DeepSeek Harness y arrancarlo en cinco minutos?

La ruta rápida es un solo comando. Necesitas Node.js instalado —el repositorio pide ^22.19.0 o >=24.0.0 en su package.json— y nada más:

npx @deepseek-ai/dsh web

Eso levanta la interfaz web en http://127.0.0.1:3080. El proceso usa como ubicación por defecto el directorio desde el que lo lanzas, aunque una instalación nueva arranca sin workspace seleccionado: hasta que no elijas uno, el compositor de sesiones está bloqueado.

Si prefieres el código fuente, con pnpm:

git clone https://github.com/deepseek-ai/deepseek-harness.git
cd deepseek-harness
pnpm install
pnpm run build
pnpm dsh web

Con el servidor arriba, la secuencia de puesta a punto son tres pasos:

  1. Configura el modelo. Abre Settings → Models, mete tu API key de DeepSeek y guarda. La ruta del modelo queda usable en el acto, sin reiniciar el servidor.
  2. Elige el workspace. Pulsa Choose workspace y añade el directorio del proyecto donde arrancaste dsh.
  3. Lanza una tarea. Abre una sesión y pide algo concreto: “Resume este repositorio e identifica sus paquetes principales”.

A partir de ahí el agente lee y edita ficheros del workspace, ejecuta comandos, delega trabajo y mantiene un plan. La interfaz pregunta antes de las operaciones que requieran aprobación según la política de permisos activa.

Un detalle que agradezco: las claves son de solo escritura. La página recibe un descriptor censurado tras guardar, nunca el secreto literal. La clave vive en $DSH_HOME/.credentials.yaml y los ajustes solo guardan una referencia a esa credencial.

¿Y si no quiero la interfaz web?

El comando dsh es un lanzador de perfiles, y la web es solo uno de ellos. Estos son los modos de entrada que documenta el propio CLI:

dsh web                                  # alias de --profile web
dsh --profile headless "ejecuta los tests"  # una sesión, imprime la respuesta final y sale
dsh --profile web --port 8080            # --port lo parsea la app web, no el lanzador
dsh plugin --profile demo add ./mi-plugin   # gestiona los plugins de un perfil

El modo headless es el que te interesa para automatizar: una sesión fresca y persistida, la respuesta final por stdout, y fuera. Sin servidor de por medio.

Curso gratis · paso a paso

Tener el agente arrancado es la parte fácil

Lo difícil es decirle qué tiene que hacer sin que se invente la mitad. Eso se llama Spec Driven Development y en este curso recorres el ciclo entero con OpenSpec sobre un proyecto de juguete, del proposal al archivado, antes de coger tú el volante.

Entra en el curso gratis →

¿Qué significa que “todo es un plugin” en DeepSeek Harness?

Significa que debajo de dsh hay un framework de composición llamado Cordis, y que cada parte del producto se monta como una contribución a un contexto compartido.

Un plugin, en su forma más simple, es un módulo TypeScript que exporta una función apply. El framework la llama al cargar el plugin y le pasa un objeto ctx con el que registras capacidades:

import type { Context } from '@deepseek-ai/cordis'

export const name = 'hello-plugin'

export function apply(ctx: Context) {
  // Las dependencias requeridas están listas antes de que corra apply.
  console.log('[hello-plugin] plugin loaded!')
}

Esa es toda la configuración. No hay más ceremonia.

Lo interesante viene después, en dos propiedades que se notan cuando llevas un rato escribiendo plugins.

La primera: la limpieza es automática. Todo lo que registres a través de ctx —listeners de eventos, herramientas, temporizadores— se desmonta cuando el plugin se descarga. No hay removeListener ni clearInterval que recordar. Para recursos que necesitan un cierre explícito, como una conexión de red, existe ctx.effect():

export function apply(ctx: Context) {
  ctx.effect(() => {
    const timer = setInterval(() => {
      console.log('heartbeat')
    }, 5000)

    // La función devuelta se ejecuta cuando el plugin se descarga.
    return () => clearInterval(timer)
  })
}

La segunda: las dependencias se declaran, no se importan. Si tu plugin consume un servicio como tools o llm, lo dices en inject y el framework espera a que esté disponible antes de cargarte:

export const name = 'my-tool-plugin'
export const inject = ['tools']

export function apply(ctx: Context) {
  // ctx.tools está listo aquí.
  ctx.tools.register(/* ... */)
}

Los paquetes centrales que se montan en ese árbol tienen nombres reveladores: core/session es dueño del log append-only de eventos, core/tools del registro de herramientas y su pipeline de ejecución con guardas, core/agent-loop del driver por defecto. Todos ellos, filas de configuración. Todos ellos, reemplazables.

💡 Si vienes de escribir plugins para editores, la analogía que mejor funciona es la de un sistema de inyección de dependencias con ciclo de vida reversible. Registras efectos; al descargar, se deshacen solos.

Cada semana aparece un harness, un protocolo o un patrón nuevo para trabajar con agentes. Cada domingo te contamos cuáles estamos probando de verdad y qué tal salen. Ya somos +6.700.

Quiero esa dinamita 🧨

¿Qué son los perfiles y los bundles, y por qué te importan?

Aquí está la parte del diseño que más me ha costado entender y que más rendimiento da cuando la pillas.

Un dsh en marcha es un árbol de plugins compuesto en el arranque a partir de capas ordenadas. Y hay dos conceptos, cada uno con su manifiesto:

  • Un bundle es un paquete npm que aporta una capa de configuración. Su package.json declara dsh.bundle y responde a “¿qué contribuye este paquete?”.
  • Un perfil es un directorio bajo $DSH_HOME/profiles/<nombre> que describe una composición ejecutable. Declara dsh.profile y responde a “¿qué bundles componen este montaje, y en qué orden?”.

Un bundle es lo que tú escribes y distribuyes. Un perfil es lo que un usuario arranca con dsh --profile <nombre>. Nada es las dos cosas a la vez.

El orden de aplicación de capas sobre una raíz vacía es este, y merece la pena memorizarlo porque explica casi cualquier comportamiento raro:

  1. Cada patch de bundle nombrado en dsh.profile.bundles, en orden de lista. @deepseek-ai/dsh-base siempre primero.
  2. El cordis.patch.yml propio del perfil.
  3. El cordis.patch.yml del home, en $DSH_HOME, con las preferencias locales de la máquina.
  4. Cada overlay --patch <ruta>, en orden de argumentos.

Las capas posteriores ganan por fila. Y ojo con esto: un patch reemplaza el config entero de una fila, no hace deep-merge de claves. Si sobrescribes una fila, tienes que volver a escribir todas las claves que necesita, no solo la que cambias.

¿Quieres ver el árbol que arranca de verdad tu máquina, sin arrancarlo?

dsh --profile web --dump-config

Cualquier fila que imprima ese comando la puedes sustituir por un patch tuyo. Incluida, insisto, la del bucle del agente.

¿Cómo escribes tu primera herramienta para el agente?

Vamos a lo práctico. Una herramienta es lo que el modelo puede llamar, y en dsh se define con un DSL que valida los argumentos por ti.

Este plugin registra una herramienta greet que el modelo verá en su prompt:

import type { Context } from '@deepseek-ai/cordis'
import { defineTool } from '@deepseek-ai/dsh-tools'

export const name = 'greet-tool'
export const inject = ['tools']

export function apply(ctx: Context) {
  ctx.tools.register(defineTool({
    name: 'greet',
    description: 'Greet someone by name.',
    parameters: {
      name: { type: 'string', required: true, description: 'The name to greet' },
    },
    output: {
      schema: { type: 'string' },
      render: (_args, value) => [{ type: 'text', text: value }],
    },
    async execute(args) {
      return `Hello, ${args.name}!`
    },
  }))
}

Fíjate en la separación entre execute y output.render. execute devuelve el valor canónico declarado en output.schema; render convierte ese valor en el contenido que ve el modelo. Es una distinción que muchas implementaciones de tool calling se saltan y que aquí te ahorra tener que decidir el formato de salida dentro de la lógica de negocio.

Para cargarlo sin publicar nada, un overlay que apunte al fichero con ruta absoluta:

- insert:
    - id: hello
      name: '/ruta/absoluta/a/deepseek-harness/scratch-plugin/src/my-plugin.ts'

Y lo arrancas así:

pnpm dsh web --patch ./scratch-plugin/cordis.yml

Abre http://127.0.0.1:3080, pide “Usa la herramienta greet para saludar a Ada” y el modelo recibirá Hello, Ada! como resultado. Del prompt al tool call sin escribir una línea de fontanería.

🔑 La ruta del plugin debe ser absoluta. Un fichero de patch aporta configuración, pero no cambia el directorio de perfil desde el que el loader resuelve rutas de módulos. Es el error de novato número uno.

¿Cómo se empaqueta y se publica un plugin de dsh?

Cuando tu plugin deja de ser un experimento, lo empaquetas como bundle y lo instalas en un perfil. La estructura mínima son tres ficheros:

hello-plugin/
├── package.json       # declara dsh.bundle
├── cordis.patch.yml   # la capa que se aplica cuando un perfil lista este bundle
└── index.js           # los módulos de plugin que referencian las filas del patch

El manifiesto es corto:

{
  "name": "dsh-hello-plugin",
  "version": "0.1.0",
  "type": "module",
  "main": "index.js",
  "files": ["index.js", "cordis.patch.yml"],
  "dsh": { "bundle": { "patch": "./cordis.patch.yml" } }
}

Y la instalación en un perfil pasa por pnpm, que dsh envuelve:

dsh plugin --profile demo add ./hello-plugin
dsh --profile demo --dump-config   # muestra una capa "# == dsh-hello-plugin"
dsh --profile demo

Un paquete sin la declaración dsh.bundle se instala igual, pero solo como dependencia normal: dsh plugin avisa y no activa ninguna capa. Ese formato es para librerías que otros plugins importan, no para plugins que el usuario habilita.

La trampa de instalar desde GitHub

No hace falta publicar en un registro: puedes instalar directo desde un git host con dsh plugin --profile demo add github:tu-usuario/hello-plugin. Pero una instalación desde git trae fuentes, no artefactos construidos. Nada ejecuta tu script de build, así que un paquete TypeScript llega sin su lib/ y falla al cargar.

Se arregla por los dos lados. El autor envía un script prepare autocontenido que compile los puntos de entrada. Y el usuario tiene que autorizar esa compilación, porque pnpm ≥10 se niega a ejecutar el prepare de una dependencia git hasta que lo permitas de forma explícita en el pnpm-workspace.yaml del perfil:

allowBuilds:
  dsh-hello-plugin: true

Aquí la documentación de DeepSeek hace algo que agradezco y que no es habitual: no vende la comodidad, avisa del riesgo. Esa autorización es permiso para ejecutar el código del paquete en tu máquina en tiempo de instalación, fuera de cualquier sandbox bajo el que corra el agente. Permite solo paquetes cuyo código te fías y fija un commit (github:tu-usuario/hello-plugin#<sha>) para que un push posterior no cambie en silencio lo que se ejecuta.

🛡️ Si prefieres no pedirle esa confianza a nadie, distribuye artefactos ya construidos: publica en npm con lib/ compilado, o manda un tarball de pnpm pack. Ninguna de las dos formas necesita permiso de build.

Construye agentes con criterio

Leer la arquitectura de un agente está bien; diseñar la tuya está mejor

Seis niveles de arquitectura, de un LLM con tools a un sistema multiagéntico revisado por otro modelo: guardarraíles, memoria, skills, MCP y orquestación, con código en la mano para que no se te descontrole en producción.

Asomarme a la masterclass →

6 niveles de arquitectura, en directo

¿Qué trae DeepSeek Harness de serie?

Bastante más de lo que sugiere una versión 0.1.0-rc.5. El bundle dsh-base es la primera capa de todo perfil e inserta adaptadores de modelo, herramientas, persistencia, política de sandbox y aprobación, ajustes, credenciales y telemetría. Estas son las piezas que más me han llamado la atención.

Cliente MCP. Hay un plugin de puente que conecta con servidores Model Context Protocol externos y registra sus herramientas como nativas, con nombres cualificados por servidor (mcp__github__create_issue). Es exactamente la misma forma que usan Claude Code y Codex, así que tus servidores existentes funcionan sin tocarlos. Se configura con una instancia de plugin por servidor y soporta transporte stdio y streamable-http.

Skills. Existe una familia de capacidad completa para skills: definición de servicio, proveedor de sistema de ficheros, proveedor de skills empaquetadas y una herramienta skill que ve el modelo. Si ya tienes skills escritas para otros agentes, el concepto viaja.

Subagentes que no son suyos. Esta es la más divertida. Entre los proveedores de subagente del repositorio están subagent-claude-code y subagent-codex. Es decir: dsh puede delegar una tarea en Claude Code —invocando el Agent SDK oficial en el workspace de la sesión— o en Codex, y recibir solo la respuesta final. Cargan en estado dormido y cada preset de agente decide si contribuye la herramienta de delegación. Si ya tienes rodada tu manera de crear subagentes, aquí el proveedor es otra fila más de configuración.

Sandbox y presets de permisos. El modo de sandbox gobierna los efectos sobre el sistema de ficheros con tres valores: read-only, workspace-write y danger-full-access. En Linux usa bwrap y Landlock, en macOS Seatbelt, y en Windows un backend de token restringido por ACL. Encima de eso, los presets empaquetan sandbox y política de aprobación en un solo selector: workspace-write (con aprobación ask) y danger-full-access (con aprobación never).

Goals y el bucle Ralph. Un goal es un objetivo de finalización duradero atado a una sesión existente, con fases active, paused, blocked y complete y un tope de rondas. El Ralph loop es otra cosa: un flujo de trabajo en primer plano que le da un objetivo inmutable a una secuencia de agentes hijo frescos. Cada ronda de Ralph es una sesión hija nueva que no recibe la conversación del padre ni la de los hijos anteriores; solo el workspace compartido y un informe estructurado acotado —el handoff— con estado, resumen, evidencias, siguientes pasos y bloqueos.

El tope por defecto de un run de Ralph son 256 rondas. Suena a mucho, y lo es, pero la idea de fondo tiene sentido: si el contexto contaminado es lo que degrada a un agente en tareas largas, empieza de cero cada vez y deja que el repositorio sea la memoria.

Y además: LSP, terminales persistentes, jobs en segundo plano, compactación de contexto, un servidor ACP (Agent Client Protocol) para clientes programáticos, y un token-meter para contar lo que gastas.

¿Qué son los cuatro modos de ejecución de DeepSeek Harness?

Son cuatro composiciones de agente que vienen de fábrica, y cambian bastante más que un puñado de ajustes: cambian qué herramientas ve el modelo y cómo las llama. En el repositorio viven como presets en apps/cli/config/agent-presets/, cada uno con su propio agent.cordis.yml.

Modo Qué es Cuándo lo quieres
Standard El agente de código completo: edición de ficheros, shell, búsqueda en ficheros y web, skills, planificación, goals, subagentes y workflows Trabajo normal
Code Todo lo de Standard, pero las herramientas se exponen como un SDK y el modelo escribe un programa TypeScript Secuencias largas de llamadas
Minimal Dos herramientas y nada más: bash persistente y str_replace_editor Medir modelos sin ruido
Creator Standard más la capacidad de leer y escribir el runtime en el que se está ejecutando Crear tus propios presets

Code Mode es el que más me ha hecho pensar. En lugar de una llamada a herramienta por acción, el modelo escribe un programa contra un SDK generado y una herramienta reservada, run_code, lo ejecuta. Lo dice sin rodeos el comentario del propio preset: una secuencia que serían cinco viajes de ida y vuelta al modelo se convierte en uno.

Lo bonito del diseño es que tus herramientas llegan ahí gratis. Cualquier herramienta registrada y visible está disponible como await tools.<nombre>(args) sin integración adicional: los tipos de argumentos y de retorno se derivan de los mismos esquemas que ya escribiste, y las llamadas vuelven a entrar en el pipeline de ejecución normal, con sus políticas y sus guardas. Si escribiste el greet de antes, ya es llamable desde un programa.

El modo Minimal parece pobre y es deliberado: persona fija como prompt completo del sistema, sin identidad global, sin orientación de la interfaz, sin compactación de contexto y con solo dos herramientas. Es el banco de pruebas para evaluar un modelo en un entorno mínimo, que es justo lo que documenta el fichero BENCHMARK.md del repositorio.

Y el modo Creatorcordis en el disco— existe para algo muy concreto: que le pidas a un agente que escriba otro agente. Añade el conjunto de herramientas autorreferencial de Cordis, una skill que enseña a componer y una persona que le dice a qué plano pertenece cada edición.

🛡️ Antes de que te emociones con Creator, el aviso que trae su propia configuración en mayúsculas: cordis_mount evalúa JavaScript escrito por el modelo contra el runtime vivo, y una composición que escriba ese agente se convierte en un preset que otras sesiones montan. Trata una sesión en ese preset como si fuera acceso a shell. Porque lo es.

¿Por qué presume de que cada ejecución es trazable?

Porque no es una promesa de marketing, es una invariante del sistema. Y esta es, para mí, la mejor idea del proyecto.

Todo lo que ve el modelo queda registrado en un log de sesión append-only: prompts del sistema, razonamiento, llamadas a herramientas y sus resultados, planificación de subagentes y cada inyección de contexto. La interfaz tiene una vista llamada Trajectory donde inspeccionas esos registros por origen.

Lo importante es lo que se construye encima. Reanudar una sesión, bifurcarla, buscar en ella y reproducirla operan todas sobre el mismo stream de eventos. No hay un formato para la interfaz, otro para la persistencia y otro para la telemetría: hay un log, y el resto son proyecciones de ese log.

La regla que lo sostiene está escrita en la documentación de arquitectura con estas palabras: model-visible means logged. Cualquier cosa que llegue a una petición al modelo tiene que ser reconstruible desde el log, y hay una invariante en tiempo de ejecución que lo comprueba. Por eso añadir una entrada nueva visible para el modelo obliga a extender el mapa de eventos de sesión, no vale con colarla por un lado.

¿Por qué te debería importar a ti, que igual nunca abres el código? Porque es la diferencia entre poder responder “¿por qué mi agente hizo esto?” y encogerte de hombros. Si alguna vez has intentado depurar por qué un agente tomó una decisión rara tres pasos atrás, sabes exactamente de qué hablo.

¿Puedo usar DeepSeek Harness con modelos que no sean DeepSeek?

Sí, y es una de las razones para mirarlo aunque no uses DeepSeek.

Desde Add provider eliges un proveedor del catálogo instalado —Anthropic u OpenAI, por ejemplo— y metes su clave. El catálogo aporta endpoint, protocolo y lista de modelos. Los proveedores con autenticación nativa necesitan sus propias credenciales: Bedrock pide credenciales AWS y región, Vertex un proyecto ADC, Azure una api-version y Codex OAuth. Rellenar solo el campo de API key no los configura.

Para un gateway de empresa, un servidor propio o cualquier proveedor ausente del catálogo, está Add a custom provider: ID en minúsculas, URL base, protocolo de API, credencial y al menos un modelo. Hay un botón para consultar los modelos disponibles contra la URL base, que llama al endpoint GET /models compatible con OpenAI.

Dos avisos que la documentación deja claros y que te van a ahorrar una tarde:

  • El Provider ID es permanente. Las peticiones, las sesiones guardadas, los modelos por defecto y las referencias a credenciales lo usan. Para renombrar un proveedor, añades uno nuevo y borras el viejo.
  • Un modelo que escribes a mano se trata como solo texto hasta que digas lo contrario. Nada puede preguntarle a un endpoint qué modalidades acepta, así que adjuntar una imagen se rechaza antes de enviarla. La solución es una línea en $DSH_HOME/settings.yaml:
llm-pi-ai:
  providers:
    my-gateway:
      apiKeyEnv: GATEWAY_API_KEY
      api: openai-completions
      baseURL: https://gateway.example/v1
      models:
        - id: legacy-chat
        - id: vision-preview
          input: [text, image]

El adaptador propio de DeepSeek (dsh-llm-deepseek) trae por defecto los modelos V4 Flash y V4 Pro, thinking activado, reasoningEffort en high, un tope de salida de 256.000 tokens y una ventana de contexto de referencia de un millón. Su ruta de chat-completions es solo texto y no se puede configurar de otra forma.

Conectar tu agente a un modelo u otro cambia el resultado más de lo que parece. En la newsletter compartimos 12 recursos cada domingo y las experiencias de los developers que ya están en esto. Gratis desde 2018.

Suscríbete gratis →

¿Se puede usar desde Python?

Hay un SDK publicado, y es la alternativa programática a la interfaz web. Necesitas Python 3.10 o superior, y Linux x64/arm64 o macOS 14+ en arm64.

git clone https://github.com/deepseek-ai/deepseek-harness.git
cd deepseek-harness
python -m venv .venv
. .venv/bin/activate
python -m pip install deepseek-harness-sdk

El runtime instalado no necesita Node.js en el sistema: viene empaquetado con la misma versión del SDK. Después, la llamada es tan directa como esto:

from pathlib import Path
from deepseek_harness import DeepSeekHarness

config = Path("examples/jsonrpc-agent/minimal.cordis.yml").resolve()

with DeepSeekHarness(
    provider="deepseek-official",
    model="deepseek-v4-flash",
    max_tokens=49_152,
    cwd="/ruta/absoluta/al/workspace",
    session_root="/ruta/absoluta/a/sessions",
    cordis=str(config),
) as harness:
    result = harness.run(
        "Inspect the repository and fix the failing tests.",
        session_id="example-001",
    )

print(result.final_response)

Reutilizar el mismo harness y el mismo session_id preserva el proceso Bash de la sesión, incluido su directorio de trabajo, sus variables exportadas y sus funciones de shell. Para una tarea independiente, un session_id nuevo.

Un aviso serio: la composición de ejemplo usa danger-full-access. Ejecútala solo dentro de un checkout desechable o un contenedor, porque Bash y el editor pueden modificar cualquier ruta que vea el proceso del runtime.

¿Merece la pena usar DeepSeek Harness hoy?

Voy a ser honesto contigo, que es lo que me gustaría que hicieran conmigo.

Para trabajo diario, no. Está en developer preview, la versión es una release candidate del 0.1.0 y el propio repositorio promete cambios que rompen compatibilidad. No vas a mover tu flujo de trabajo aquí esta semana, y tampoco deberías.

Para aprender cómo está construido un agente por dentro, sí, y con ganas. Y esto no es un premio de consolación.

Su documentación es de las mejores que he leído en un proyecto de agentes. Hay un glosario que define un término canónico por concepto, un mapa de eventos con productores y consumidores, un diagrama de secuencia del ciclo de vida, un catálogo de configuración generado, un directorio de postmortems con los fallos que se han encontrado y una arquitectura documentada al detalle. Documentan hasta el diagrama de flujo de un turno:

turn/start
  claim next-step input plus one queued message
  assemble prompt sections + tool schemas
  -> agent/pre-step                   reject | enter(messages)
     step/start
     append entered messages as user/message
     derive model history from the log
     agent/request -> llm/stream -> assistant/chunk* -> assistant/message
     tool/call* -> tools/pre-execute -> tools/execute -> tools/post-execute -> tool/result*
     step/end
  -> agent/turn-stopping
turn/end

Ahí tienes, en catorce líneas, lo que la mayoría de agentes esconde. Un step es una petición al modelo más las herramientas que llama. Un turn son cero o más steps: se abre antes de reclamar su primera entrada y se cierra cuando no queda nada pendiente.

Ese diagrama, junto a la invariante de trazabilidad que vimos antes, es lo que separa un juguete de un sistema. No es que hayan documentado bien un producto: es que el producto está diseñado para poder documentarse así.

Lo que no me convence: la curva de entrada es empinada. Entre Cordis, perfiles, bundles, capas de patch, seams de capacidad y scopes por agente hay mucho vocabulario propio antes de escribir tu primera línea útil. El propio equipo lo admite entre líneas cuando recomienda, en su documentación de arquitectura, “usar un agente para explorar el código y entender la arquitectura”. Cuando la sugerencia oficial para entender tu proyecto es lanzarle una IA encima, algo dice de su tamaño.

💡 Mi recomendación práctica: clona el repositorio, lee docs/architecture.md y docs/glossary.md, haz el tutorial del plugin greet y para ahí. Son dos horas y sales entendiendo mejor cómo funciona cualquier agente de código, incluido el que uses a diario.

TL;DR

  • 🚀 DeepSeek Harness (dsh) es el agent harness open source de DeepSeek AI, con licencia MIT y arquitectura donde absolutamente todo —incluido el bucle del agente— es un plugin sobre el framework Cordis.
  • ⚡ Arranca con npx @deepseek-ai/dsh web y una interfaz web en http://127.0.0.1:3080; el modo headless ejecuta una tarea y sale, ideal para automatizar.
  • 🔧 Un plugin es un módulo que exporta apply(ctx), se limpia solo al descargarse y declara sus dependencias con inject; una herramienta se define con defineTool separando el valor canónico de lo que ve el modelo.
  • 🧩 Trae cliente MCP con nombres compatibles con Claude Code y Codex, skills, sandbox en tres modos, presets de permisos, goals, el bucle Ralph de agentes frescos y subagentes que delegan en Claude Code o Codex.
  • 🎛️ Cuatro modos de ejecución de fábrica: Standard, Code (el modelo escribe un programa TypeScript en vez de encadenar llamadas), Minimal (dos herramientas, para benchmarks) y Creator (el agente escribe otros agentes; trátalo como acceso a shell).
  • 🔍 Cada ejecución es trazable: un log append-only registra todo lo que ve el modelo, y reanudar, bifurcar, buscar y reproducir operan sobre ese mismo stream de eventos.
  • ⚠️ Está en developer preview (0.1.0-rc.5) y avisa de cambios que rompen compatibilidad: úsalo para aprender arquitectura de agentes, no para producción.

Preguntas frecuentes sobre DeepSeek Harness

¿Qué es DeepSeek Harness?
Es un agent harness open source desarrollado por DeepSeek AI, con licencia MIT, cuyo comando es dsh. Proporciona el andamiaje que permite a un modelo leer y editar ficheros, ejecutar comandos y delegar trabajo sobre un workspace. Su arquitectura se basa en que cada parte del producto es un plugin sobre el framework Cordis.

¿Cómo instalo DeepSeek Harness?
Con Node.js instalado, ejecuta npx @deepseek-ai/dsh web y abre http://127.0.0.1:3080. Para trabajar desde el código fuente, clona el repositorio y ejecuta pnpm install, pnpm run build y pnpm dsh web.

¿DeepSeek Harness es gratis?
El software es gratuito y de código abierto bajo licencia MIT. Lo que pagas es el consumo del modelo que configures: DeepSeek, Anthropic, OpenAI o cualquier endpoint compatible con OpenAI que añadas como proveedor personalizado.

¿Puedo usar Claude o GPT con DeepSeek Harness?
Sí. Desde Settings → Models puedes añadir proveedores del catálogo como Anthropic u OpenAI con su API key, o registrar un proveedor personalizado con su URL base y protocolo. Bedrock, Vertex, Azure y Codex necesitan sus credenciales nativas, no basta con una API key.

¿Qué diferencia hay entre DeepSeek Harness y Claude Code?
Claude Code es un producto estable centrado en la terminal y se extiende por los bordes con skills, MCP y hooks. DeepSeek Harness arranca en el navegador, está en developer preview y permite sustituir cualquier pieza interna —incluido el bucle del agente— mediante capas de configuración.

¿Qué es un perfil en dsh?
Un perfil es un directorio bajo $DSH_HOME/profiles/<nombre> que describe una composición ejecutable. Su package.json declara dsh.profile con la lista ordenada de bundles que apila, y contiene un cordis.patch.yml con la capa de ajustes propia del usuario. Se arranca con dsh --profile <nombre>.

¿Puedo usar mis servidores MCP existentes?
Sí. El plugin cliente de MCP conecta con servidores externos por stdio o streamable-http y registra sus herramientas con nombres cualificados por servidor, con la misma forma mcp__<servidor>__<herramienta> que usan Claude Code y Codex.

¿Es seguro dejar que el agente ejecute comandos?
Depende del modo que elijas. read-only deniega escrituras, workspace-write las permite bajo el workspace y el área temporal, y danger-full-access desactiva el confinamiento. Los presets combinan cada modo con una política de aprobación, y el ejemplo del SDK de Python usa danger-full-access, así que conviene ejecutarlo solo en un contenedor o un checkout desechable.

¿Qué es el Code Mode de DeepSeek Harness?
Es uno de los cuatro modos de ejecución que vienen de fábrica. En lugar de una llamada a herramienta por acción, el modelo escribe un programa TypeScript contra un SDK generado y una herramienta reservada llamada run_code lo ejecuta, así que una secuencia que serían cinco viajes al modelo se resuelve en uno. Cualquier herramienta registrada está disponible como await tools.<nombre>(args) sin integración adicional.

¿Puedo ver todo lo que ha hecho el agente?
Sí. Todo lo que ve el modelo queda en un log de sesión append-only —prompts, razonamiento, llamadas a herramientas, resultados, subagentes e inyecciones de contexto— y la interfaz lo expone en una vista llamada Trajectory. Reanudar, bifurcar, buscar y reproducir una sesión operan sobre ese mismo stream de eventos.

¿Qué es el bucle Ralph?
Es un flujo de trabajo que entrega un objetivo inmutable a una secuencia de agentes hijo frescos. Cada ronda arranca una sesión nueva sin la conversación previa, usando el workspace compartido como memoria y un informe estructurado acotado como traspaso entre rondas. El tope por defecto es de 256 rondas.

¿Está listo para producción?
No. El repositorio declara que está en developer preview, su versión es 0.1.0-rc.5 y avisa en mayúsculas de que habrá cambios que rompen compatibilidad. Es una herramienta excelente para estudiar la arquitectura de un agente, no para apoyar tu trabajo diario todavía.

Fuentes

🧨 Última oprtunidad para recibir la dinamita que mereces sobre programación con IA el próximo domingo: Suscríbete gratis a Web Reactiva en https://webreactiva.com/newsletter

Imagen de Daniel Primo
Claude, IA de Anthropic

Escrito con la ayuda de la IA generativa de Claude, fuentes fidedignas y con un human in the loop:
Dani Primo.

CEO en pantuflas de Web Reactiva. Programador y formador en tecnologías que cambian el mundo y a las personas. Activo en linkedin, en substack y canal @webreactiva en telegram

12 recursos para developers cada domingo en tu bandeja de entrada

Además de una skill práctica bien explicada, trucos para mejorar tu futuro profesional y una pizquita de humor útil para el resto de la semana. Gratis.