DeepSeek Harness: así se arma un plugin dsh completo

En pocas palabras: El décimo artículo de la serie DeepSeek Harness, publicado el 18/09/2026, enseña a construir un plugin completo llamado workspace-context con cinco piezas: inyección de contexto en el system prompt, tool get_workspace_info, confirmación antes de operaciones peligrosas, medición de tiempos por tool call y limpieza automática al descargarse.

DeepSeek publicó el 18 de septiembre de 2026 el décimo artículo de su serie sobre DeepSeek Harness (dsh): un tutorial que arma de punta a punta un plugin llamado workspace-context, con inyección de contexto en el system prompt, una tool de lectura de archivos, confirmación antes de borrar y medición de tiempos de ejecución, según el artículo original en dev.to.

DeepSeek Harness, conocido como dsh, es un framework de agentes de DeepSeek que organiza sus capacidades con el protocolo de plugins Cordis. Un plugin dsh es un módulo TypeScript con tres piezas mínimas: name, inject y apply, que declara de qué servicios depende (tools, systemPrompt) y qué registra en el contexto del agente. Si un servicio todavía no está listo, el plugin queda suspendido en vez de romper la ejecución.

En 30 segundos

  • El artículo es el número 10 de la serie DeepSeek Harness, publicado el 18/09/2026 según dev.to.
  • El plugin de ejemplo se llama workspace-context y cubre 5 requisitos: prompt, tool, permisos, observabilidad y ciclo de vida.
  • La tool get_workspace_info usa schema estricto (additionalProperties: false) y isConcurrencySafe: true para correr en paralelo con otras tools de solo lectura.
  • El hook tools/pre-execute pausa o bloquea tool calls con nombres que contienen “delete” o “rm”; sin approval service configurado, “ask” degrada solo a “deny”.
  • El hook tools/execute mide tiempos con performance.now() y exige siempre return result para no perder la respuesta de la tool.

¿Qué es DeepSeek Harness (dsh) y el sistema de plugins Cordis?

Cordis es el protocolo que define cómo un plugin de dsh se registra, declara dependencias y se limpia solo cuando se descarga. Cada plugin exporta name (identificador único en el árbol de dependencias), inject (la lista de servicios que necesita, como tools o systemPrompt) y apply (la función que recibe el contexto y hace los registros).

Este es el artículo número 10 de la serie. Los nueve anteriores cubrieron, en orden, el sistema de plugins Cordis, el registro de tools, el Agent loop, la memoria de sesión, el armado del System Prompt, las capability seams, la colaboración entre múltiples agentes y la observabilidad. Ninguno de esos artículos armaba algo que corriera de punta a punta. Este sí.

Lo interesante acá: inject no es solo una lista de imports, es un contrato. Le dice al runtime de Cordis “necesito estos servicios, si no están listos, no me llames”. Esa es la base del hot-swapping de plugins que ya se explicó en el artículo 02 de la serie. Relacionado: el rival open source de Claude Code.

¿Qué hace el plugin de ejemplo workspace-context?

deepseek harness diagrama explicativo

El plugin workspace-context resuelve cinco requisitos funcionales que mapean directo a las cinco preocupaciones centrales de armar un plugin en dsh: prompt, tools, permisos, observabilidad y ciclo de vida. Cada punto corresponde a una pieza de código independiente dentro del mismo archivo.

  • Inyecta el directorio de trabajo actual en el system prompt. Así el modelo “sabe dónde está” sin que el usuario tenga que repetirlo en cada mensaje.
  • Expone la tool get_workspace_info. El modelo puede pedir el listado de archivos y sus tamaños en vez de esperar que se lo digan.
  • Pausa antes de tool calls peligrosos. Si el nombre de la tool contiene “delete” o “rm”, el plugin espera confirmación del usuario antes de ejecutar.
  • Mide el tiempo de cada tool call. Registra cuánto tarda cada ejecución y si terminó OK o con error.
  • Limpia todo solo al descargarse. Cuando el plugin se desactiva, todos los registros (system prompt, tool, hooks) se dan de baja solos, sin que tengas que escribir código extra.

Ponele que estás armando un agente de terminal para tu equipo: subís el modelo, lo conectás a un directorio real, funciona bárbaro en la demo, lo mandás a un flujo con archivos de producción y de repente alguien le pide “borrá los logs viejos” sin darse cuenta de que el agente iba a ejecutar un borrado masivo. Ese es justo el escenario que workspace-context previene con el punto 3.

¿Cómo se inyecta contexto dinámico en el system prompt con ctx.systemPrompt.section()?

Con ctx.systemPrompt.section() se registra un bloque de texto que dsh reevalúa cada vez que arma el system prompt completo, no una sola vez al inicio de la sesión. El campo text del ejemplo no es un string fijo: es una función que lee el cwd de la sesión en el momento exacto de armar el prompt y devuelve un bloque “## Workspace” con la ruta actual. Esto se conecta con lo que analizamos en el runtime donde todo es un plugin.

Eso significa que si el directorio de trabajo cambia a mitad de sesión (algo que en un agente de terminal pasa todo el tiempo), el próximo request ya arranca con el dato actualizado. Y no hace falta guardar el disposer que devuelve section(): como se llamó desde ctx.systemPrompt, Cordis sabe que esa sección pertenece a este plugin y la borra sola cuando el plugin se descarga.

Nada de eso es magia. Es una función que se ejecuta en el momento justo.

¿Cómo se registra la tool get_workspace_info con esquema estricto?

La tool get_workspace_info se define con defineTool y un schema de salida con additionalProperties: false, lo que impide que el modelo devuelva campos que no estaban previstos en la respuesta (path, entries, type, size). La separación entre lo que execute() retorna, datos estructurados listos para procesar, y lo que render() convierte en texto legible para el modelo, es, según el propio artículo, un principio de diseño central de dsh.

Un detalle que no es menor: la tool se marca con isConcurrencySafe: () => true. Como es de solo lectura, dsh puede correrla en paralelo con otras tools de solo lectura dentro del mismo turno del Agent loop, en vez de ejecutarlas una por una. Para cualquier tool que no modifique estado, esa bandera debería ser true casi siempre.

¿Cómo interceptar tool calls peligrosos y medir tiempos de ejecución en dsh?

Se intercepta con el hook tools/pre-execute: si el nombre de la tool incluye “delete” o “rm”, el plugin devuelve { kind: 'ask' } y pausa la ejecución hasta que el usuario confirme. Si el Bundle no tiene configurado un approval service, ese “ask” degrada solo a “deny”: la tool nunca corre. Es el patrón middleware de siempre: llamar a next() deja pasar la cadena, devolver otra cosa sin llamar a next() la corta ahí mismo. Lo explicamos a fondo en cómo se compara Deepseek frente a Google.

Ojo con un detalle del diseño: la detección se basa en convención de nombres, no en una whitelist de tools seguras. Funciona para el ejemplo, pero un proyecto real probablemente necesite reglas más precisas. ¿Qué pasa con una tool llamada “remove_temp_cache” que en realidad es inofensiva? Ahí la convención de nombres se queda corta, y conviene sumar una lista explícita de excepciones.

La medición de tiempos usa el hook tools/execute, que envuelve la ejecución real de la tool con performance.now() antes y después, y loguea si terminó OK o ERROR según el flag isError del resultado. El error más común al escribir este tipo de hook es olvidarse del return result al final. ¿Y si te olvidás? El agente se queda esperando una respuesta que nunca llega, porque el resultado real de la tool se perdió dentro del hook.

Qué está confirmado y qué no sobre dsh

Confirmado, según el artículo publicado en dev.to: la estructura mínima de un plugin (name, inject, apply), el uso de ctx.systemPrompt.section() con texto dinámico, el hook tools/pre-execute con los estados “ask” y “deny”, y el hook tools/execute para medir tiempos. También está confirmado que el plugin de ejemplo, workspace-context, es código completo y ejecutable, pensado para pegar directo en un Bundle.

Lo que no está confirmado en esta entrega: no hay versión ni changelog público de dsh mencionado en el artículo, tampoco fecha de disponibilidad general del framework fuera de la serie de blog, ni datos de rendimiento sobre cuánto tarda un turno con múltiples tools corriendo en paralelo. Tampoco se aclara si @deepseek-ai/dsh-tools está publicado en un registro público de paquetes. Antes de llevar este patrón a producción, conviene revisar si existe un repositorio oficial de dsh y no asumir que la convención “delete/rm” cubre todos los casos peligrosos de tu propio set de tools. Para más detalles técnicos, mirá cómo se compara Deepseek frente a Openai.

Errores comunes al construir un plugin para dsh

  • Olvidar el return result en un hook de tipo wrapper. Hooks como tools/execute envuelven la ejecución real; si no devolvés el resultado que te da next(), el agente pierde la respuesta de la tool aunque la ejecución haya sido exitosa.
  • Poner texto estático en vez de una función en systemPrompt.section(). Si el campo text es un string fijo con el cwd hardcodeado, el modelo va a operar con un directorio viejo apenas cambie la sesión.
  • Confiar solo en una convención de nombres para decisiones de seguridad. Una tool con un nombre poco convencional puede saltarse un filtro basado únicamente en “contiene delete o rm”. Conviene combinar convención de nombres con una lista explícita de tools sensibles.
  • No declarar las dependencias correctas en inject. Si el plugin usa ctx.tools pero no lo declaró en inject, Cordis no puede garantizar que el servicio esté listo antes de llamar a apply, y el plugin falla de forma intermitente.

Preguntas Frecuentes

¿Qué es DeepSeek Harness (dsh)?

DeepSeek Harness (dsh) es un framework de agentes de DeepSeek que arma sus capacidades mediante plugins TypeScript basados en el protocolo Cordis. Cada plugin declara sus dependencias de servicio y se registra en tiempo de ejecución, según describe la serie técnica publicada en dev.to.

¿Cómo se crea un plugin para dsh?

Un plugin de dsh se crea como un módulo TypeScript que exporta tres elementos: name (identificador único), inject (lista de servicios necesarios) y apply (función que recibe el contexto y hace los registros de tools, prompt o hooks). Con esas tres piezas alcanza para que Cordis reconozca el plugin y lo cargue en el Bundle.

¿Qué es el sistema de plugins Cordis?

Cordis es el protocolo de dependencias e inyección de servicios que usa dsh para cargar plugins. Gestiona qué servicios necesita cada plugin, suspende el plugin si algún servicio no está disponible en vez de romper la ejecución, y limpia solos todos los registros (tools, secciones de prompt, hooks) cuando el plugin se descarga.

¿Cómo bloquear o pedir confirmación antes de una tool peligrosa en un agente?

En dsh se usa el hook tools/pre-execute: si el nombre de la tool coincide con un patrón riesgoso, por ejemplo contiene “delete” o “rm”, devolvés { kind: ‘ask’ } para pedir confirmación humana o { kind: ‘deny’ } para bloquear la ejecución directamente. Si no hay un approval service configurado, un “ask” degrada solo a “deny”.

¿Para qué sirve dsh de DeepSeek?

dsh sirve para construir agentes de IA con capacidades extensibles mediante plugins: inyectar contexto dinámico en el system prompt, registrar tools nuevas, interceptar llamadas peligrosas y medir tiempos de ejecución para observabilidad. El objetivo, según lo describe la serie de artículos, es que cada preocupación (prompt, tools, permisos, observabilidad, ciclo de vida) se resuelva con piezas independientes dentro del mismo plugin.

Conclusión

El aporte real de este décimo artículo de la serie no es una función nueva de dsh: es mostrar que las piezas que ya se explicaron por separado (Cordis, tools, system prompt, hooks) encajan en un plugin de cinco funciones que cabe en un solo archivo. Si venís siguiendo la serie desde el artículo 01, workspace-context es el primer ejemplo donde todo eso deja de ser teoría y pasa a ser código que corre.

Para quien esté evaluando dsh para un proyecto propio, el patrón más reutilizable es el de permisos: el hook tools/pre-execute con degradación automática de “ask” a “deny” cuando no hay approval service configurado es un mecanismo de seguridad razonable por defecto, siempre que no dependas solo de la convención de nombres para decidir qué es peligroso. Antes de escalar esto a producción, un criterio práctico simple es armar una lista propia de tools sensibles (más allá de las que contienen “delete” o “rm”) y testear el flujo de confirmación con casos límite reales antes de exponerlo a usuarios finales.

Fuentes

Desplazarse hacia arriba