<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: DA SEIN</title>
    <description>The latest articles on DEV Community by DA SEIN (@da_sein_dffa21a60a5fd492f).</description>
    <link>https://dev.to/da_sein_dffa21a60a5fd492f</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4086350%2F55ff43bb-aae2-4bb3-b4b7-a78dc5a5eed3.png</url>
      <title>DEV Community: DA SEIN</title>
      <link>https://dev.to/da_sein_dffa21a60a5fd492f</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/da_sein_dffa21a60a5fd492f"/>
    <language>en</language>
    <item>
      <title>DeepSeek Harness Deep Dive (4): Agent Loop — How One Prompt Turns Into Dozens of Actions</title>
      <dc:creator>DA SEIN</dc:creator>
      <pubDate>Fri, 04 Sep 2026 15:40:38 +0000</pubDate>
      <link>https://dev.to/da_sein_dffa21a60a5fd492f/deepseek-harness-deep-dive-4-agent-loop-how-one-prompt-turns-into-dozens-of-actions-39lf</link>
      <guid>https://dev.to/da_sein_dffa21a60a5fd492f/deepseek-harness-deep-dive-4-agent-loop-how-one-prompt-turns-into-dozens-of-actions-39lf</guid>
      <description>&lt;p&gt;The previous three articles answered three increasingly concrete questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why does an LLM need a Harness at all?&lt;/li&gt;
&lt;li&gt;Why does DeepSeek Harness make almost everything a Plugin?&lt;/li&gt;
&lt;li&gt;How does Cordis keep those Plugins composable instead of letting them become another pile of tightly coupled modules?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At this point the Runtime is ready. Models, Tools, Sessions, events, and other capabilities have all been mounted.&lt;/p&gt;

&lt;p&gt;So now comes the question that matters most in practice:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;When the user sends one message, what actually happens next?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The easy answer is “the Agent Loop runs.” But that phrase hides most of the interesting engineering.&lt;/p&gt;

&lt;p&gt;A toy Agent Loop is often written like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;executeTools&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toolCalls&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is useful for teaching the basic idea, but DeepSeek Harness has to solve a harder problem. A user may send another instruction while the current task is still running. Plugins may rewrite or reject the next model step. A model call may produce several Tool Calls. Some of those calls can run in parallel, others must form barriers. A task may need another model request after the Tools finish—or may need to stop without making any model request at all.&lt;/p&gt;

&lt;p&gt;So instead of starting from &lt;code&gt;while (true)&lt;/code&gt;, it is more useful to start from the three boundaries the Runtime actually manages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Inbox → Turn → Step
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once these three are clear, the rest of the Agent Loop becomes much easier to understand.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Turn and Step Are Not the Same Thing&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This distinction is the first place where the real Harness differs from a simple chatbot loop.&lt;/p&gt;

&lt;p&gt;DeepSeek Harness defines a &lt;strong&gt;Step&lt;/strong&gt; as one model request together with the Tool executions requested by that model response.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;Turn&lt;/strong&gt;, on the other hand, is the larger unit of work. It can contain zero, one, or multiple Steps.&lt;/p&gt;

&lt;p&gt;A useful mental model is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Turn
├── Step 1
│   ├── one model request
│   └── the tools requested by that response
│
├── Step 2
│   ├── another model request
│   └── another group of tool executions
│
└── ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkroki.io%2Fgraphviz%2Fpng%2FeNqVUlGPk0AQfu-vmOCjHIWaRk2DyUUbX7S9tH26YswWRroezOLukl4199-dZSmhmjORBMLsfPN9s_PNpJClFs0RPsKvCYD_32tBD4XU6adNCIcyV5XSaXA6SotBCI0o0jh6NQ-BVIEGG47mHLkiH72eh8zVP98UWRI1psGtlqJigkocsKpUngb2EqXBmhB2rSZ4L_jlGiEJ7lErUBo-K42wtdiY4MuCqZ0w7M1RNJge1GMIxp4rVtCqpQILZv1b1Z0Y-RPTZBZCLXQpKQ3iKHkT8mfmebEomfdftTHjGLjd3W52sO97t9z31Fihrae52yyHXF4JWYOkprUZvQRRItlpo_HG8HU8_H65WQ_4DX7H3GIBU8C6seeM4g7aDcfjl6sP8bU2UhH4xkx78B7mVctl-qurNZ23cBn1kjjBCh3josv0Fr942z394R9D9YfbZJB2hkCSUQI1-1GBxh8tmu6aVqnKXA5Y6nAG2Q-HKWbXFLOMCB_t_7KsrllWGUVRNGQTuHk3VqrdCp2Ufhh14RCr5xBP3uf13QDw3rmBsyOqaSSVgyHP-eEXhYV4Jy6rwdGV5bqznA0nBdh7U6MxrGdGG8JlzvkRy8iLrs6D-UouN-6clD1yt6BOWPQgl_aMi8nT5Dc9xDye" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkroki.io%2Fgraphviz%2Fpng%2FeNqVUlGPk0AQfu-vmOCjHIWaRk2DyUUbX7S9tH26YswWRroezOLukl4199-dZSmhmjORBMLsfPN9s_PNpJClFs0RPsKvCYD_32tBD4XU6adNCIcyV5XSaXA6SotBCI0o0jh6NQ-BVIEGG47mHLkiH72eh8zVP98UWRI1psGtlqJigkocsKpUngb2EqXBmhB2rSZ4L_jlGiEJ7lErUBo-K42wtdiY4MuCqZ0w7M1RNJge1GMIxp4rVtCqpQILZv1b1Z0Y-RPTZBZCLXQpKQ3iKHkT8mfmebEomfdftTHjGLjd3W52sO97t9z31Fihrae52yyHXF4JWYOkprUZvQRRItlpo_HG8HU8_H65WQ_4DX7H3GIBU8C6seeM4g7aDcfjl6sP8bU2UhH4xkx78B7mVctl-qurNZ23cBn1kjjBCh3josv0Fr942z394R9D9YfbZJB2hkCSUQI1-1GBxh8tmu6aVqnKXA5Y6nAG2Q-HKWbXFLOMCB_t_7KsrllWGUVRNGQTuHk3VqrdCp2Ufhh14RCr5xBP3uf13QDw3rmBsyOqaSSVgyHP-eEXhYV4Jy6rwdGV5bqznA0nBdh7U6MxrGdGG8JlzvkRy8iLrs6D-UouN-6clD1yt6BOWPQgl_aMi8nT5Dc9xDye" alt="A Turn can contain zero or more Steps." width="1842" height="347"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 1: A Step is one model request plus the Tools it requested. A Turn is the larger boundary that may contain zero or many Steps.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Suppose the user says:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Fix the failing login test.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first model request may decide to run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pytest tests/test_login.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That model request and the resulting test execution belong to &lt;strong&gt;Step 1&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The Tool result says authentication failed because of an unexpected redirect. The Agent now needs the model to think again. That new model request begins &lt;strong&gt;Step 2&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The second response may read a file, edit it, and run another test. If another model request is needed afterward, that becomes &lt;strong&gt;Step 3&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;All of them may still belong to the same Turn.&lt;/p&gt;

&lt;p&gt;This sounds like a small naming detail, but it changes how we understand an Agent. A Turn is not “one prompt, one answer.” It is closer to:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;One continuous unit of work that may require several rounds of model reasoning and environmental feedback before the Runtime considers it complete.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There is an even stranger possibility: a Turn may contain &lt;strong&gt;zero Steps&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Why would the Harness open a Turn and then never call the model?&lt;/p&gt;

&lt;p&gt;To understand that, we first need to look at the Inbox.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;A User Message Does Not Go Straight to the LLM&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;When a message reaches an Agent, DeepSeek Harness does not immediately append it to a &lt;code&gt;messages[]&lt;/code&gt; array and call the model.&lt;/p&gt;

&lt;p&gt;It first enters the Agent's &lt;strong&gt;Inbox&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The Inbox has two logical destinations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;next-turn
next-step
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These names describe &lt;em&gt;when&lt;/em&gt; the message is eligible to enter model-facing work.&lt;/p&gt;

&lt;p&gt;An ordinary:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;followup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;goes to &lt;code&gt;next-turn&lt;/code&gt; and wakes the driver. It represents a normal new user request.&lt;/p&gt;

&lt;p&gt;But DeepSeek Harness also exposes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;steer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both target &lt;code&gt;next-step&lt;/code&gt;, but they behave differently.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;steer()&lt;/code&gt; is an active intervention. If the Agent is already running, the message is intended for the nearest later Step boundary. If the Agent is idle, steering can wake it and start a Turn.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;inject()&lt;/code&gt; is quieter. It queues model-facing context for the next Step but &lt;strong&gt;does not wake an idle Agent by itself&lt;/strong&gt;. That makes it useful for things such as file-change notices, extra instructions, or other context that should be seen the next time the Agent is already doing work.&lt;/p&gt;

&lt;p&gt;The routing looks roughly like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkroki.io%2Fgraphviz%2Fpng%2FeNp9kU1PAjEQhu_8ismeNK4oMcavrAlKNBjBRLyhh4EOS7VM17YrqPG_O7slK8bESzNf79PO25bSucNiDtfw2QKI8dghvyjtstv7FCb51BrrsmQ514GSFApU2X774DAFtoo8FZIdSlaJYnb0dCasqgtjP8eCsoldpeDDu6EscbZkRUpIM8uBcSG1rtNo1hWvPyjrdFJYoMs1Z8l-u3OcytFJai6pXLj_aE9kTOauYGxwQiZLZtYYuyyLrQV5jzltP_ISX8iDcvqNXMSOmnEfiNyf2T0I8h4KHpjQkQ-yDxVRe9NoNT_TNGyIlRXt8O4BKsrGhaIaPjQyplXYDaVjeC2ppEgdjn73q_s2-5e33f6gGenVaJga1IvYv2h63QAINX5SmY_u_fSR0Rj44e6AZYLmHZEw6PcaRp-9lg9FcCWz5rzmCeYHobkoA0yRYUakIMwjD0Zrn-o_2T2XvaPfVTiK9jWheCJxvdnags00biyVi1-ZPPOs9dX6BjZt4AQ" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkroki.io%2Fgraphviz%2Fpng%2FeNp9kU1PAjEQhu_8ismeNK4oMcavrAlKNBjBRLyhh4EOS7VM17YrqPG_O7slK8bESzNf79PO25bSucNiDtfw2QKI8dghvyjtstv7FCb51BrrsmQ514GSFApU2X774DAFtoo8FZIdSlaJYnb0dCasqgtjP8eCsoldpeDDu6EscbZkRUpIM8uBcSG1rtNo1hWvPyjrdFJYoMs1Z8l-u3OcytFJai6pXLj_aE9kTOauYGxwQiZLZtYYuyyLrQV5jzltP_ISX8iDcvqNXMSOmnEfiNyf2T0I8h4KHpjQkQ-yDxVRe9NoNT_TNGyIlRXt8O4BKsrGhaIaPjQyplXYDaVjeC2ppEgdjn73q_s2-5e33f6gGenVaJga1IvYv2h63QAINX5SmY_u_fSR0Rj44e6AZYLmHZEw6PcaRp-9lg9FcCWz5rzmCeYHobkoA0yRYUakIMwjD0Zrn-o_2T2XvaPfVTiK9jWheCJxvdnags00biyVi1-ZPPOs9dX6BjZt4AQ" alt="followup, steer, and inject enter different Inbox paths." width="1006" height="346"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 2: &lt;code&gt;followup()&lt;/code&gt; targets the next Turn; &lt;code&gt;steer()&lt;/code&gt; and &lt;code&gt;inject()&lt;/code&gt; target the next Step, but only steering wakes the driver.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This design matters because a running Agent is not a closed pipeline.&lt;/p&gt;

&lt;p&gt;Imagine the Agent is already investigating a bug and you suddenly send:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Do not modify the database layer.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A simplistic implementation might have to cancel the whole run, rebuild the prompt, and start over.&lt;/p&gt;

&lt;p&gt;DeepSeek Harness instead has a place for &lt;strong&gt;steering&lt;/strong&gt; to wait until the next safe Step boundary.&lt;/p&gt;

&lt;p&gt;That is a much more useful abstraction for long-running Agents: the user can intervene while work is in progress without pretending that every interaction starts from an idle chatbot.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The Turn Opens Before the Model Is Called&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Once waking work is available, the driver enters its &lt;code&gt;running&lt;/code&gt; state and opens a durable Turn:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;turn/start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the order: the Turn begins &lt;strong&gt;before&lt;/strong&gt; the first Step.&lt;/p&gt;

&lt;p&gt;The driver then claims the input for the proposed Step. At a Turn boundary, that means:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;all pending next-step input
+
one queued next-turn message
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The claimed messages are no longer merely waiting in the Inbox. They are now the candidate input for the next model-facing Step.&lt;/p&gt;

&lt;p&gt;But the model still has not been called.&lt;/p&gt;

&lt;p&gt;Before that happens, DeepSeek Harness runs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;agent/pre-step
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is one of the most important interception points in the whole Agent Loop.&lt;/p&gt;

&lt;p&gt;A listener can decide:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;reject
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;enter(messages)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And &lt;code&gt;enter(messages)&lt;/code&gt; does not have to return the exact batch that was claimed. Plugins can rewrite what enters the Step.&lt;/p&gt;

&lt;p&gt;That gives Context-management, compaction, policy, or steering-related extensions a clean place to intervene &lt;em&gt;before&lt;/em&gt; the model request is derived.&lt;/p&gt;

&lt;p&gt;It also explains the zero-Step Turn.&lt;/p&gt;

&lt;p&gt;The sequence can legally be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;turn/start
   ↓
claim input
   ↓
agent/pre-step
   ↓
reject
   ↓
turn/end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No &lt;code&gt;step/start&lt;/code&gt; occurs. No LLM request occurs.&lt;/p&gt;

&lt;p&gt;This is a subtle but important design choice: the durable history can record that the Runtime opened and closed a Turn even when policy or preprocessing prevented any model work from happening.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Only After Pre-Step Does a Step Really Begin&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If &lt;code&gt;agent/pre-step&lt;/code&gt; returns &lt;code&gt;enter(messages)&lt;/code&gt;, the driver finally opens:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;step/start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The entered user-role messages are then appended to the Session as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;user/message
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, the Harness has enough information to construct the request.&lt;/p&gt;

&lt;p&gt;But even here it does not simply reuse a mutable &lt;code&gt;messages[]&lt;/code&gt; object.&lt;/p&gt;

&lt;p&gt;The Runtime does two different things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It assembles the current System Prompt and Tool schemas from registered capabilities.&lt;/li&gt;
&lt;li&gt;It derives model history from the Session log.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Session log
   ↓
derive model history

Plugin registrations
   ↓
assemble system prompt + tool schemas

both
   ↓
model request
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The actual request then passes through:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;agent/request
   ↓
llm/stream
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The model streams back chunks. DeepSeek Harness records those raw chunks as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;assistant/chunk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and, after a successful provider call, records the assembled result as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;assistant/message
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This may seem excessively detailed for a simple model call, but it serves a larger design rule that we will examine in the next article:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Model-visible means logged.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The Session is not merely a chat transcript. It is the durable source from which model-visible history can be reconstructed.&lt;/p&gt;

&lt;p&gt;For now, the important point is simpler: &lt;strong&gt;the Agent Loop never treats the model request as an isolated black box.&lt;/strong&gt; The request is constructed from Runtime state, streamed through an adapter seam, and written back into the Session as durable facts.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;A Step Includes the Tools Requested by That Model Call&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Suppose the model response contains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;read_file("src/auth.ts")
run_test("tests/login.test.ts")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Step does not end as soon as the model stops generating.&lt;/p&gt;

&lt;p&gt;Those Tool Calls belong to the Step that produced them.&lt;/p&gt;

&lt;p&gt;At a high level, the loop does this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;assistant/message
   ↓
classify Tool Calls
   ↓
tool/call
   ↓
Tool execution pipeline
   ↓
tool/result
   ↓
step/end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;DeepSeek Harness can classify calls by execution mode. Some Tool Calls are allowed to overlap; exclusive calls form ordering barriers. Results are then committed in model order.&lt;/p&gt;

&lt;p&gt;We will leave the permission checks, pre/execute/post waterfalls, timeouts, Sandbox providers, and parallel scheduling details for the dedicated Tool Pipeline article. The important point here is only the boundary:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;One Step owns one model request and the Tool executions requested by that response.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The Step closes only after those calls have settled and their results have been written.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Why Does the Loop Start Another Step?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now we reach the actual loop.&lt;/p&gt;

&lt;p&gt;After:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;step/end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the Runtime asks whether more model work is owed.&lt;/p&gt;

&lt;p&gt;There are several reasons why the answer may be yes.&lt;/p&gt;

&lt;p&gt;A Tool result may require the model to interpret what happened. A Tool may defer additional model-facing context. The user may have sent steering while the previous Step was running. Other &lt;code&gt;next-step&lt;/code&gt; input may now be waiting.&lt;/p&gt;

&lt;p&gt;If more work exists, the Runtime does &lt;strong&gt;not&lt;/strong&gt; open a new Turn immediately.&lt;/p&gt;

&lt;p&gt;Instead, the current Turn continues:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Step 1
   ↓
Tool results
   ↓
claim next-step input
   ↓
agent/pre-step
   ↓
Step 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is why:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Turn ≠ Step
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is not just terminology.&lt;/p&gt;

&lt;p&gt;The Turn is the continuity boundary. Steps are individual rounds of model interaction inside it.&lt;/p&gt;

&lt;p&gt;A Coding Agent may therefore spend one Turn doing something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Step 1: run failing test
Step 2: inspect relevant files
Step 3: edit implementation
Step 4: rerun test
Step 5: inspect another failure
Step 6: final verification
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the user's point of view, that may still feel like one request.&lt;/p&gt;

&lt;p&gt;From the Harness's point of view, it is a sequence of separately logged and interceptable model Steps.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;When Does a Turn Actually End?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The obvious answer would be:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When the model says it is done.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But the Harness cannot rely on that alone.&lt;/p&gt;

&lt;p&gt;A model response may look final while a Tool has requested continuation. Steering may have arrived during execution. Another piece of next-step context may already be queued.&lt;/p&gt;

&lt;p&gt;DeepSeek Harness therefore checks whether the Turn still &lt;strong&gt;owes&lt;/strong&gt; more work.&lt;/p&gt;

&lt;p&gt;When there is no Tool continuation and the next-step Inbox is empty, the loop reaches a final checkpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;agent/turn-stopping
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives interested Plugins one last place to react before the Turn is committed as finished.&lt;/p&gt;

&lt;p&gt;Then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;turn/end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is appended.&lt;/p&gt;

&lt;p&gt;Only after the driver's work drains does the Agent return to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;idle
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One subtle point: &lt;code&gt;running&lt;/code&gt; does not mean “a Turn is currently open.” It describes the broader driver activity interval and may span consecutive queued Turns.&lt;/p&gt;

&lt;p&gt;Again, DeepSeek separates several notions that a toy Agent often collapses into one variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Agent status
Turn lifetime
Step lifetime
Inbox state
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That separation is what lets the Runtime support steering, cancellation, replay, queued work, and extensions without turning the main loop into one giant stateful function.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The Whole Path&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;We can now put the lifecycle together:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkroki.io%2Fgraphviz%2Fpng%2FeNp9U8tu2zAQvPsrFjq1iRLHKII-ArVwbaMIEAMB7FPsHmhxI7GmSJak6rhFr_2AfmK_pEtRluwA7WUh7WM0OzsacFFYZkr4BD8GAPF5ZZnacmGz5ccUNkWupbZZsiuFxyQFw3h2dfnqOgWlOTo04e1NCmEovl1_viGsUIWVK5nBbKOfUnB-LzFLrK4VR05Ij1p5xSrKja1gss048R2z0SiFitlCqCy5uhy9TimMkgYXeUG4_5l9S23UdwsryTYos-RW0ffj8HLRZX1t1dB5Zn0sTbrKRDJRgUHFhSpA4ZO_cB4NCGVqv1bnoBXGdMCACp1jBUaU-w6FUsoPjcVmeK0sfsHcg7ZAebQv2jH3Mg5OD1pxwSqteAotzix0Q8D4EDsX_Q4hG3dYK2YCY6gd2uEJpXHXPnYOq41EcHuapBWtroyHc_BaS3B5iRVzazVFK74hVHRACaVwXts9PFIvLAhXaBVx756tavFrjc7Dn1-_QcqKeFlkVcth3jcTBFGmgbys1fas6e-TJ9SX_bWI4TBnUsb-hrARBqWgWxwyRMHV0p-1Os1OdSJ1YmH-L6nn2iLstN2C3iE_yL18tmc4Ot1UG0P2aHnOTm3Vfeqh1z7MguCyWa3x58X74EeKkxDuQ5hGK4RKD6k0DCHaB_nBLdRyZIQ9us4cVBmHcNc8zRuwpn0W4jwq0Hz1aPpdlDSnn0iomnm68lqRV5-5_yBggFseEeykiswpPtwMfg7-AiUpZu8" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkroki.io%2Fgraphviz%2Fpng%2FeNp9U8tu2zAQvPsrFjq1iRLHKII-ArVwbaMIEAMB7FPsHmhxI7GmSJak6rhFr_2AfmK_pEtRluwA7WUh7WM0OzsacFFYZkr4BD8GAPF5ZZnacmGz5ccUNkWupbZZsiuFxyQFw3h2dfnqOgWlOTo04e1NCmEovl1_viGsUIWVK5nBbKOfUnB-LzFLrK4VR05Ij1p5xSrKja1gss048R2z0SiFitlCqCy5uhy9TimMkgYXeUG4_5l9S23UdwsryTYos-RW0ffj8HLRZX1t1dB5Zn0sTbrKRDJRgUHFhSpA4ZO_cB4NCGVqv1bnoBXGdMCACp1jBUaU-w6FUsoPjcVmeK0sfsHcg7ZAebQv2jH3Mg5OD1pxwSqteAotzix0Q8D4EDsX_Q4hG3dYK2YCY6gd2uEJpXHXPnYOq41EcHuapBWtroyHc_BaS3B5iRVzazVFK74hVHRACaVwXts9PFIvLAhXaBVx756tavFrjc7Dn1-_QcqKeFlkVcth3jcTBFGmgbys1fas6e-TJ9SX_bWI4TBnUsb-hrARBqWgWxwyRMHV0p-1Os1OdSJ1YmH-L6nn2iLstN2C3iE_yL18tmc4Ot1UG0P2aHnOTm3Vfeqh1z7MguCyWa3x58X74EeKkxDuQ5hGK4RKD6k0DCHaB_nBLdRyZIQ9us4cVBmHcNc8zRuwpn0W4jwq0Hz1aPpdlDSnn0iomnm68lqRV5-5_yBggFseEeykiswpPtwMfg7-AiUpZu8" alt="The core DeepSeek Harness Agent Loop from Inbox to Turn, Step, model request, Tool execution, and Turn end." width="612" height="1639"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 3: The Agent Loop is not simply LLM → Tool → LLM. Inbox routing, durable Turn/Step boundaries, pre-step interception, Session logging, and continuation checks all sit around that familiar cycle.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In a compressed form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User / plugin input
        ↓
      Inbox
        ↓
   turn/start
        ↓
 claim proposed input
        ↓
  agent/pre-step
        ↓
    step/start
        ↓
append user/message
        ↓
assemble request
        ↓
 agent/request
        ↓
   llm/stream
        ↓
assistant/message
        ↓
 Tool Calls + results
        ↓
    step/end
        ↓
more work?
   ↙        ↘
 yes        no
 ↓           ↓
next Step   agent/turn-stopping
             ↓
          turn/end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the point where “Agent Loop” stops being a vague name for &lt;code&gt;while (true)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It is better understood as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;A driver that continuously turns queued work into durable Turn and Step transitions, derives each model request from Runtime state, executes the actions the model asks for, and decides whether the current unit of work should continue or close.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That also explains why DeepSeek Harness keeps the Agent Loop itself replaceable behind a Service interface. The loop is enormously important, but it is still one Plugin in the larger composition rather than a privileged core that every extension must modify.&lt;/p&gt;

&lt;p&gt;And one part of this lifecycle deserves its own article.&lt;/p&gt;

&lt;p&gt;We repeatedly wrote events such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;turn/start
user/message
assistant/message
tool/result
turn/end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why log all of them instead of just maintaining the latest &lt;code&gt;messages[]&lt;/code&gt; array?&lt;/p&gt;

&lt;p&gt;Why does DeepSeek insist that model-visible information must be reconstructable from the log?&lt;/p&gt;

&lt;p&gt;That is the next piece of the architecture:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Session is not chat history.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The next article will focus on the rule behind it: &lt;strong&gt;Model-visible means logged.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;References&lt;/strong&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/architecture.md" rel="noopener noreferrer"&gt;DeepSeek Harness Architecture&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/agent-lifecycle.md" rel="noopener noreferrer"&gt;Agent Turn and Step Lifecycle&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/core.md" rel="noopener noreferrer"&gt;DeepSeek Harness Core Subsystem&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/session.md" rel="noopener noreferrer"&gt;DeepSeek Harness Session Subsystem&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/tools.md" rel="noopener noreferrer"&gt;DeepSeek Harness Tools Subsystem&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>deepseek</category>
    </item>
    <item>
      <title>DeepSeek Harness (3): Everything Is a Plugin — Now What?</title>
      <dc:creator>DA SEIN</dc:creator>
      <pubDate>Sun, 23 Aug 2026 13:52:16 +0000</pubDate>
      <link>https://dev.to/da_sein_dffa21a60a5fd492f/deepseek-harness-3-everything-is-a-plugin-now-what-356f</link>
      <guid>https://dev.to/da_sein_dffa21a60a5fd492f/deepseek-harness-3-everything-is-a-plugin-now-what-356f</guid>
      <description>&lt;p&gt;The previous article ended with a simple question:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;“Everything is a Plugin” sounds clean, but once dozens of Plugins exist at the same time, does the complexity really disappear?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Of course not.&lt;/p&gt;

&lt;p&gt;A Tool Plugin may depend on a Sandbox. The Agent Loop depends on Tools and Sessions. A permission component may need to intervene before a Tool actually runs. More importantly, these Plugins are not always loaded once at startup and left alone forever. They may be replaced by configuration, mounted only for a specific Agent, or removed once a task is finished.&lt;/p&gt;

&lt;p&gt;If a “plugin system” only means dynamically importing a collection of modules, then the coupling that used to live inside the Harness core will simply reappear somewhere else.&lt;/p&gt;

&lt;p&gt;That is the problem Cordis is designed to solve.&lt;/p&gt;

&lt;p&gt;DeepSeek’s own description of Cordis is actually fairly modest: the Cordis kernel mainly manages &lt;strong&gt;Plugin mounting, unmounting, and dependencies&lt;/strong&gt;, while the actual Agent capabilities remain inside the Plugins themselves. In other words, Cordis is not another, larger “Agent core.” It is closer to a set of Runtime rules: it does not decide how Shell execution should work, but it does make sure that questions like “who provides Shell, who depends on Shell, when is it available, and what should disappear when the Plugin is removed?” remain manageable.&lt;/p&gt;

&lt;p&gt;That is the best entry point for the concepts that follow.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;First, Do Not Confuse Context with the Prompt&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The first overloaded word is &lt;strong&gt;Context&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Earlier, when discussing LLMs, we also used “context” to mean the information the model can see in one request: user messages, history, Tool schemas, System Prompt, and so on.&lt;/p&gt;

&lt;p&gt;But Cordis &lt;code&gt;ctx&lt;/code&gt; is not that.&lt;/p&gt;

&lt;p&gt;A useful first approximation is to think of it as &lt;strong&gt;the shared runtime workspace in which Plugins discover and register capabilities&lt;/strong&gt;. If a Plugin wants to find a service, subscribe to an event, or register something that should later be cleaned up, it usually starts from &lt;code&gt;ctx&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So it is better to keep these two meanings separate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Model Context
= information sent into the LLM for one request

Cordis Context / ctx
= runtime environment where Plugins find and register capabilities
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why do we need such a Runtime Context at all?&lt;/p&gt;

&lt;p&gt;Suppose one Plugin needs access to the Tool system. The most direct implementation would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;toolRegistry&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./tool-registry&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But that immediately couples the Plugin to one concrete implementation. If you later want to replace the Tool Registry, swap the Session Provider, or use different implementations under different configurations, every consumer may need to change.&lt;/p&gt;

&lt;p&gt;Cordis inserts another layer: &lt;strong&gt;a Plugin does not directly look for another Plugin. It looks for the Service that Plugin provides.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A Service can be understood as a capability exposed under a stable name. In DeepSeek Harness, common examples include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ctx.tools
ctx.sessions
ctx.llm
ctx.agents
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Provider Plugin registers the capability under a stable key. Consumer Plugins depend on that key rather than on the concrete implementation behind it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkroki.io%2Fgraphviz%2Fpng%2FeNp9kU1LAzEQhu_9FcOeFGJtC4ogEaQHLx4WoafWQzYZd2PTZJlJa6v4353tttJ68BLm453nHSYD52sybQNP8DUA6OM5mbh0nvTzi4Kqtikk0sVH4zMWClrj9Gg4uVEQk0PGVrJbBd1Mn9y93guqa8KcG9OirtJWAeddQF1QWkeHTkBvKeZoVlJ7JG_CocL-E_V4omBlqPZRF6Ph-E7JMyn2XHS1cP-bHe11JcyDqTDooqS08Q4JyrAWYo-Z_raniZxnmMo8bvMicjZVQGCkjbcIS9wtos3bYU4pMFxDFzMy-xS5Z81OWJHXqz9WJVw9nPgR1p6zaA4Ox31ENDsRcQobPNfMzkEObTCE4LBFOWm0O7jw8R1tvpR7dP9XGbs8Ht4ZbtAJ53vwA96JosU" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkroki.io%2Fgraphviz%2Fpng%2FeNp9kU1LAzEQhu_9FcOeFGJtC4ogEaQHLx4WoafWQzYZd2PTZJlJa6v4353tttJ68BLm453nHSYD52sybQNP8DUA6OM5mbh0nvTzi4Kqtikk0sVH4zMWClrj9Gg4uVEQk0PGVrJbBd1Mn9y93guqa8KcG9OirtJWAeddQF1QWkeHTkBvKeZoVlJ7JG_CocL-E_V4omBlqPZRF6Ph-E7JMyn2XHS1cP-bHe11JcyDqTDooqS08Q4JyrAWYo-Z_raniZxnmMo8bvMicjZVQGCkjbcIS9wtos3bYU4pMFxDFzMy-xS5Z81OWJHXqz9WJVw9nPgR1p6zaA4Ox31ENDsRcQobPNfMzkEObTCE4LBFOWm0O7jw8R1tvpR7dP9XGbs8Ht4ZbtAJ53vwA96JosU" alt="Plugins cooperate through stable Service keys instead of importing each other's concrete implementations." width="945" height="128"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 1: A Provider Plugin registers a capability into the Cordis Context; a Consumer Plugin resolves it through a stable key.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This resembles Dependency Injection, but Cordis adds something important: a Plugin can &lt;strong&gt;explicitly declare what it depends on&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;plugin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tools&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sessions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;

  &lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ctx.tools and ctx.sessions are available here&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is nothing mysterious about &lt;code&gt;inject&lt;/code&gt;. It simply says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;This Plugin only makes sense when both &lt;code&gt;tools&lt;/code&gt; and &lt;code&gt;sessions&lt;/code&gt; exist.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The Plugin therefore does not need to guess whether Sessions should start first, or manually poll until Tools are ready. The Runtime can infer activation from declared dependencies. If those dependencies change later, it can react to that change as well.&lt;/p&gt;

&lt;p&gt;This is much closer to what Cordis means by &lt;strong&gt;Spatial Composability&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In the previous article, we used “which Agent owns this capability?” as an intuition. That intuition is useful, but it is not the formal meaning. Spatial composability is more fundamentally about this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;A component can declare the external capabilities it depends on, and the Runtime can react as those dependencies appear, disappear, or change.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So “spatial” here is not simply a location in an Agent tree. It is about the component’s position inside a network of dependencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;A Plugin Must Be Removable, Not Just Loadable&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If dependency management answers “how Plugins work together,” the next problem is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What happens when a Plugin leaves?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is where many ordinary plugin systems become much less convincing.&lt;/p&gt;

&lt;p&gt;Imagine a Plugin that does all of the following when it starts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;register a Tool
add a Prompt section
subscribe to an Event
start a Timer
open an external resource
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If unloading the Plugin only means removing it from a list, the system is not actually clean.&lt;/p&gt;

&lt;p&gt;The Tool schema may still exist. The Event listener may still fire. The Timer may still be running. The Prompt may still tell the model that a capability exists even though the Plugin that provided it is gone.&lt;/p&gt;

&lt;p&gt;The Runtime has accumulated ghost state.&lt;/p&gt;

&lt;p&gt;Cordis treats these runtime changes as &lt;strong&gt;Effects&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The term sounds abstract, but here it can be understood very literally:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;An Effect is a change a Plugin makes to the Runtime, together with enough information to undo that change later.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A simplified example looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;effect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dispose&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;registerCapability&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;dispose&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the Plugin registers something, it also returns a disposer: the logic required to remove that registration later.&lt;/p&gt;

&lt;p&gt;So the lifecycle becomes reversible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Mount Plugin
   ↓
register Tool / listener / timer / prompt
   ↓
Runtime uses the capability
   ↓
Unmount Plugin
   ↓
run the disposer
   ↓
restore the Runtime
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkroki.io%2Fgraphviz%2Fpng%2FeNplj09LxDAQxe_9FEPPdf8URGGJIOzixQUp9lQ9pM20DaZJmKSrq_jdnW51Fby8ZOa9-TGTKN2R9D3cwUcCMP8rkvZFaRL3RQZ11zjjSKSvvY6YZuClEqtFfpmBdQoDeq64mGbm4up5w6jJhCr00qOo3VsGIR4NipTcaBUqBrXORisH7t2Slua7E_Q7inWewSCp01akq8X6OmPJ0xN3D5WRNRqR7pkU4cGMHJu93dkrsNMhIsGubbGJ4ck-OmdgCWZqWzaWEPVwej25wceZUPwSGM4BGAMGaKSXtTY6HudYeY6Vdvi3xvYvBJQO3gUk3oFwcAcEnHcCbYHwwA6CI4X0c-DFDV_CUkxSTrLdJJ_JF3nuiKQ" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkroki.io%2Fgraphviz%2Fpng%2FeNplj09LxDAQxe_9FEPPdf8URGGJIOzixQUp9lQ9pM20DaZJmKSrq_jdnW51Fby8ZOa9-TGTKN2R9D3cwUcCMP8rkvZFaRL3RQZ11zjjSKSvvY6YZuClEqtFfpmBdQoDeq64mGbm4up5w6jJhCr00qOo3VsGIR4NipTcaBUqBrXORisH7t2Slua7E_Q7inWewSCp01akq8X6OmPJ0xN3D5WRNRqR7pkU4cGMHJu93dkrsNMhIsGubbGJ4ck-OmdgCWZqWzaWEPVwej25wceZUPwSGM4BGAMGaKSXtTY6HudYeY6Vdvi3xvYvBJQO3gUk3oFwcAcEnHcCbYHwwA6CI4X0c-DFDV_CUkxSTrLdJJ_JF3nuiKQ" alt="Cordis tracks Plugin registrations as reversible Effects and disposes them when the Plugin is unmounted." width="1286" height="109"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 2: Dynamic composition is not only about mounting Plugins; the Runtime must also be able to remove the Effects they leave behind.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This corresponds to &lt;strong&gt;Temporal Composability&lt;/strong&gt; in the Cordis paper.&lt;/p&gt;

&lt;p&gt;Its strict meaning is not simply “when in the Agent Loop should a Plugin run?” For example, “Memory injects information before the LLM request” or “Logger records results after Tool execution” describe lifecycle intervention points, but they are not the core definition.&lt;/p&gt;

&lt;p&gt;The deeper requirement is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;When a component leaves the system, the side effects it previously introduced must be completely reversible.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A Plugin should not only be easy to add now. It should also be possible to remove later without leaving the Runtime in a half-mutated state.&lt;/p&gt;

&lt;p&gt;Cordis uses a &lt;strong&gt;Fiber&lt;/strong&gt; to track a running Plugin instance. The name may sound abstract, but for our purposes a Fiber can be understood as &lt;strong&gt;the lifecycle record associated with one mounted Plugin instance&lt;/strong&gt;. It tracks whether dependencies are currently satisfied, which Effects were registered, and what must be cleaned up when the Plugin is removed.&lt;/p&gt;

&lt;p&gt;So:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Plugin
= code and configuration

Fiber
= the running instance of that Plugin and its lifecycle record
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now “unload a Plugin” means more than deleting an object reference. The Runtime can follow the Fiber and undo what the Plugin added.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Agent Scope: Not Every Capability Should Be Global&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Once dependencies and teardown are handled, DeepSeek Harness still faces a more concrete problem:&lt;/p&gt;

&lt;p&gt;A single Runtime may contain multiple Agents, but not every registration should be visible to every Agent.&lt;/p&gt;

&lt;p&gt;Some capabilities naturally belong to the global layer, such as model providers, persistence infrastructure, or shared services. Others may exist only for a particular Agent: a special Prompt section, a Tool variant, or a Listener that only makes sense for the current task.&lt;/p&gt;

&lt;p&gt;If all registrations live in one global registry, Agent A’s local capabilities can leak into Agent B.&lt;/p&gt;

&lt;p&gt;DeepSeek Harness therefore adds a local registration layer for each Agent. A useful mental model is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Agent A sees
= Global Layer + Agent A Local Layer

Agent B sees
= Global Layer + Agent B Local Layer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkroki.io%2Fgraphviz%2Fpng%2FeNpljjFPwzAQhff8ipNXTGkjIZCQkZIlS0fUJWVw4qtj4drR2VAK4r_j4rRCzWLde37vuyuU0STHARr4LgDy3JJ0b8qQeKk5dLr31pNgh8FEZBxGqcRyUd5zcF5hwDGpJE6dLB5enxLq9AltGOSIovOfHEI8WhSM_LtTqBJo5110cp-8ioy0kxPMF4pVyWEvSRsn2HKxeuTpKdkft4HWyg6tYI31nbSwlkekrUubCBUEpA_TY4A7INQmRJLReBdyubqUK40uJr32_ZmRI_VVpJ5HNnPMxuBh66aLbs7cKT5HXsXr__EGbp_TinzuZcxunS-cxp_iFzTYh24" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkroki.io%2Fgraphviz%2Fpng%2FeNpljjFPwzAQhff8ipNXTGkjIZCQkZIlS0fUJWVw4qtj4drR2VAK4r_j4rRCzWLde37vuyuU0STHARr4LgDy3JJ0b8qQeKk5dLr31pNgh8FEZBxGqcRyUd5zcF5hwDGpJE6dLB5enxLq9AltGOSIovOfHEI8WhSM_LtTqBJo5110cp-8ioy0kxPMF4pVyWEvSRsn2HKxeuTpKdkft4HWyg6tYI31nbSwlkekrUubCBUEpA_TY4A7INQmRJLReBdyubqUK40uJr32_ZmRI_VVpJ5HNnPMxuBh66aLbs7cKT5HXsXr__EGbp_TinzuZcxunS-cxp_iFzTYh24" alt="Different Agents share the Global Layer but only add their own Local Layer." width="746" height="237"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 3: Agent Scope does not duplicate the entire Runtime; it overlays agent-local registrations on top of shared infrastructure.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There is an important detail here that our earlier intuition can easily get wrong: &lt;strong&gt;the current implementation is not simply “child Agents automatically inherit every capability from their parents.”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It is not:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Parent Agent
   ↓ automatically inherit everything
Child Agent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is closer to explicitly selecting the current Agent and resolving capabilities from &lt;code&gt;Global + that Agent’s Local Layer&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This gives the system much tighter control over local registrations and avoids accidentally leaking one Agent’s local capabilities into another.&lt;/p&gt;

&lt;p&gt;But Scope should not be confused with a security boundary.&lt;/p&gt;

&lt;p&gt;It answers:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Which registrations should this Agent operation see?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It does not automatically answer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Should this Plugin be trusted? Can it access the host filesystem?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Approval, permissions, and Sandboxes still need separate mechanisms. Scope is a composition boundary, not a security sandbox.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;If We Have Services, Why Do We Still Need Events?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;At this point, one final question remains.&lt;/p&gt;

&lt;p&gt;If Plugins can already call each other through Services, why does DeepSeek Harness make such heavy use of Events?&lt;/p&gt;

&lt;p&gt;Because not every form of collaboration should look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;someService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some components merely want to observe something that happened. Others want to intercept an operation before it becomes final. They should not force the Agent Loop to import every possible extension directly.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Tool is about to execute
   ↓
Permission Plugin wants to inspect it

Tool execution finishes
   ↓
Logger wants to record the result

Model request is about to be sent
   ↓
Another Plugin wants to modify or intercept it
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the Agent Loop contains an &lt;code&gt;if&lt;/code&gt; branch for every extension, “Everything is a Plugin” quickly collapses back into “the core knows about every module.”&lt;/p&gt;

&lt;p&gt;Events provide shared extension points.&lt;/p&gt;

&lt;p&gt;The simplest Event is just a notification:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Something happened; interested Plugins may respond.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;DeepSeek Harness also makes frequent use of Waterfall Events. A Waterfall can be understood as a chain of middleware with explicit control handoff. A Listener handles the current request and calls &lt;code&gt;next()&lt;/code&gt; to delegate to the next Listener. If it owns the final decision, it can stop the chain instead.&lt;/p&gt;

&lt;p&gt;This leads to a practical rule that is easy to remember:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Use a Service when you need to directly call a capability.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use an Event when you need to observe, intercept, or inject policy into an existing flow.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is how Permission, Telemetry, Sandbox adapters, and other extensions can attach themselves to an existing runtime path without moving back into the Agent Loop core.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Putting the Pieces Back Together&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now Cordis no longer looks like a pile of abstract nouns.&lt;/p&gt;

&lt;p&gt;Its core flow can be summarized like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Plugin declares required capabilities
        ↓
inject

Dependencies become available
        ↓
Plugin activates

Plugin resolves stable Services through ctx
        ↓

Plugin registers capabilities or listeners
        ↓
those changes are tracked as reversible Effects

While the Plugin is running
        ↓
Services handle direct capability calls
Events handle observation, interception, and policy

If a registration belongs only to one Agent
        ↓
place it in that Agent's Local Scope

Plugin is replaced or removed
        ↓
Fiber triggers teardown
        ↓
Effects are disposed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, “Everything is a Plugin” finally becomes more than an architectural slogan.&lt;/p&gt;

&lt;p&gt;Cordis does not eliminate complexity. Tools still need implementations. Sessions still need persistence. The Agent Loop still needs to manage state transitions. What Cordis does is force that complexity into clearer boundaries:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;A Plugin declares what it depends on, what it provides, what it registers, and how its runtime changes can be undone; the Runtime organizes those relationships.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That makes it possible to add a new capability beside the existing system instead of repeatedly modifying an ever-growing privileged core.&lt;/p&gt;

&lt;p&gt;And that leads naturally to the next question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Once all of these Plugins are mounted, how does a single user message actually travel through DeepSeek Harness?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;From Session input, to Turn and Step, to the model request, Tool Call, and finally back into the next model context—that is the next layer to unpack: the &lt;strong&gt;Agent Loop&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;References&lt;/strong&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://www.deepseek.com/harness/" rel="noopener noreferrer"&gt;DeepSeek Harness Official Page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/architecture.md" rel="noopener noreferrer"&gt;DeepSeek Harness Architecture&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/cordis-primer.md" rel="noopener noreferrer"&gt;DeepSeek Harness Cordis Primer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/cordiverse/paper" rel="noopener noreferrer"&gt;A Programming Paradigm for Spatiotemporal Composability&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/deepseek-ai/deepseek-harness/blob/master/.agents/notes/implemented/architecture/2026-07-08-agent-scope-contexts.md" rel="noopener noreferrer"&gt;DeepSeek Harness — Agent Scope Architecture Note&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>tutorial</category>
    </item>
    <item>
      <title># DeepSeek Harness Deep Dive (2): Everything Is a Plugin — But What Exactly Is a Plugin?</title>
      <dc:creator>DA SEIN</dc:creator>
      <pubDate>Fri, 21 Aug 2026 13:47:51 +0000</pubDate>
      <link>https://dev.to/da_sein_dffa21a60a5fd492f/-deepseek-harness-deep-dive-2-everything-is-a-plugin-but-what-exactly-is-a-plugin-3mih</link>
      <guid>https://dev.to/da_sein_dffa21a60a5fd492f/-deepseek-harness-deep-dive-2-everything-is-a-plugin-but-what-exactly-is-a-plugin-3mih</guid>
      <description>&lt;p&gt;As discussed earlier, a mature Harness needs to handle at least tool execution, Context management, Session persistence, and execution control. But once Agents begin taking on more complex tasks, that is no longer enough. Models need access to more tools, file systems and browsers, sandboxed code execution, long-term memory, and sometimes collaboration with other Agents. As a result, more and more capabilities begin to accumulate inside the Harness:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                 Agent Runtime

                      |

 ------------------------------------------------

 |          |          |          |             |

Model     Tools     Memory    Session     Sandbox
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Adding capabilities is not the problem by itself. The real problem is that all of them eventually end up inside the Runtime.&lt;/p&gt;

&lt;p&gt;The most straightforward approach is simply to add whatever is missing. Need Memory? Add a Memory module to the Harness. Need a Sandbox? Add another Sandbox layer. Need Subagents? Extend the Agent Loop with multi-Agent scheduling. This works reasonably well while the system is small, but as it grows, the modules begin to entangle with one another.&lt;/p&gt;

&lt;p&gt;The Agent Loop needs to know when Memory should run. The Tool system needs to know how the Sandbox works. The permission layer has to intervene before a Tool is actually executed. The Session system, meanwhile, needs to record state changes produced by all of these components. Eventually, adding one new capability no longer means adding one isolated module—it means changing relationships across the existing Runtime.&lt;/p&gt;

&lt;p&gt;The Harness can easily end up looking like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;              Harness Runtime

 ------------------------------------------------

 LLM code
 Tool code
 Memory code
 Session code
 Sandbox code
 Permission code
 Agent Loop code
 Subagent code
 ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The Harness was originally introduced to manage the complexity of an Agent, but it can quickly become the new center of complexity itself.&lt;/p&gt;

&lt;p&gt;DeepSeek Harness takes a very direct approach to this problem:&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="boxpad"&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Everything&amp;nbsp;is&amp;nbsp;a&amp;nbsp;Plugin&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="stretchy fbox"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;p&gt;The idea is to avoid hard-coding specific capabilities directly into the Runtime whenever possible. Instead, the Runtime becomes a platform responsible for &lt;strong&gt;loading, composing, and managing capabilities&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The architecture therefore shifts from “a Harness containing a collection of modules” toward something closer to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;              Harness Runtime

                    |

              Plugin System

 ------------------------------------------------

 |          |          |          |             |

 Model    Tool     Memory    Session      Agent Loop

Plugin   Plugin    Plugin    Plugin       Plugin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The important point here is that a Plugin in DeepSeek Harness is not just a Tool. Model adapters, Session infrastructure, Agent Loops, and other runtime capabilities can all be brought under the same plugin model. In other words, an Agent is no longer defined primarily by a hard-coded Agent class. It is increasingly defined by the set of capabilities currently loaded into the Runtime.&lt;/p&gt;

&lt;p&gt;That is a significant shift.&lt;/p&gt;

&lt;p&gt;Traditionally, a Coding Agent might be implemented as something like:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Coding Agent
├── LLM
├── Shell
├── File System
├── Git
└── Memory
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Those capabilities are usually tightly associated with the Agent itself.&lt;/p&gt;

&lt;p&gt;Under a plugin-based design, the same Agent is better understood as:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Agent Runtime
     +
Model Plugin
     +
Shell Plugin
     +
File Plugin
     +
Session Plugin
     +
Memory Plugin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Change the combination, and you can construct a different Agent. The Runtime does not need separate implementations for a Research Agent, Coding Agent, or Data Agent. Instead, it needs a stable mechanism for composing capabilities.&lt;/p&gt;

&lt;p&gt;But this immediately creates a second problem: &lt;strong&gt;Plugins inside an Agent system are more complicated than ordinary software plugins.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In conventional software, a plugin is often little more than an extra callable feature. A translation extension in a browser, for example, might simply expose:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;translate(text)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You provide text, receive a translation, and the plugin has done its job.&lt;/p&gt;

&lt;p&gt;Many capabilities inside an Agent system do not work like that.&lt;/p&gt;

&lt;p&gt;Take Memory. If a Memory Plugin were nothing more than:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;memory.search()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;then it would effectively be just another Tool.&lt;/p&gt;

&lt;p&gt;A real Memory system may need to load previous experience when a task begins, retrieve relevant information before model inference, record important outcomes after a Tool executes, and extract durable knowledge when the task finishes.&lt;/p&gt;

&lt;p&gt;In other words, it participates in several stages of the Agent lifecycle:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Task begins
   ↓
Load history

Before model inference
   ↓
Inject relevant information

After tool execution
   ↓
Record results

Task ends
   ↓
Persist useful experience
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;So in DeepSeek Harness, it is more useful to think of a Plugin not as:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Plugin&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Function&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;p&gt;but as:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Plugin&lt;/span&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Capability&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Lifecycle&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;State&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;A Plugin does not merely describe &lt;strong&gt;what it can do&lt;/strong&gt;. It also needs to participate in questions such as &lt;strong&gt;when it should act&lt;/strong&gt;, &lt;strong&gt;within which runtime environment it should act&lt;/strong&gt;, and &lt;strong&gt;what state should remain after it acts&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This also explains why Tools, although extremely important, are only one kind of Plugin.&lt;/p&gt;

&lt;p&gt;Formally, we can write:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Tool&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;⊂&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Plugin&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;A Shell Tool itself may be as simple as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;shell("pytest")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Its job is to execute a command.&lt;/p&gt;

&lt;p&gt;But before that command actually runs, the Harness may need to answer several questions. Does the current Agent have permission to execute it? Does the operation require user approval? Are the arguments valid? Should the command run on the host system or inside a Sandbox? What happens if it times out?&lt;/p&gt;

&lt;p&gt;After execution, another set of questions appears. Is the output too long? Should it be truncated? Where should the full log be stored? Which parts of the result should enter the next Context?&lt;/p&gt;

&lt;p&gt;The real execution path therefore looks more like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Model produces Tool Call

        ↓

Check capability and permissions

        ↓

Validate arguments

        ↓

Enter execution environment

        ↓

Execute Tool

        ↓

Process result

        ↓

Record state and update Context

        ↓

Continue to the next inference step
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;At this point, ordinary “modularity” is still not enough.&lt;/p&gt;

&lt;p&gt;The components inside an Agent Runtime have two additional relationships that are especially important.&lt;/p&gt;

&lt;p&gt;The first is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Who does this capability belong to?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The second is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When should this capability intervene?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Suppose a Main Agent creates both a Research Agent and a Coding Agent:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                 Main Agent

              /              \

      Research Agent      Coding Agent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The Coding Agent may need Shell, Git, and file-system access, while the Research Agent may need Browser, Paper Search, and Citation capabilities.&lt;/p&gt;

&lt;p&gt;If every Plugin is global, both Agents would see every capability. That would be confusing and potentially dangerous. An Agent whose job is only to inspect code has no reason to possess database-write, deployment, or file-deletion privileges.&lt;/p&gt;

&lt;p&gt;Capabilities therefore need a scope.&lt;/p&gt;

&lt;p&gt;Some capabilities may be inherited by child Agents. Some should remain local to the current Agent. Others may need to be replaced or restricted in a child Agent. This is the kind of problem addressed by &lt;strong&gt;Spatial Composability&lt;/strong&gt;:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="boxpad"&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;What&amp;nbsp;is&amp;nbsp;the&amp;nbsp;scope&amp;nbsp;of&amp;nbsp;a&amp;nbsp;capability&amp;nbsp;within&amp;nbsp;the&amp;nbsp;Agent&amp;nbsp;structure?&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="stretchy fbox"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;p&gt;The second problem comes from the way Agents operate over time.&lt;/p&gt;

&lt;p&gt;An Agent does not execute a single function and stop. It repeatedly moves through a loop such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User input
   ↓
Model inference
   ↓
Produce action
   ↓
Execute tool
   ↓
Receive feedback
   ↓
Infer again
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Different Plugins need to intervene at different points in that lifecycle.&lt;/p&gt;

&lt;p&gt;A Permission Plugin may need to inspect an action before a Tool executes. A Memory Plugin may need to inject information before the LLM is called. A Logger may need to record results after a Tool returns. These components are not merely attached to the side of the Runtime; they are embedded into the temporal structure of the Agent itself.&lt;/p&gt;

&lt;p&gt;That leads to the second concept:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="boxpad"&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;Temporal&amp;nbsp;Composability&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="stretchy fbox"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;p&gt;In other words: &lt;strong&gt;At what point in the runtime lifecycle should a capability appear, what effect should it have, and how should that effect be removed when the capability disappears?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So the real problem behind “Everything is a Plugin” in DeepSeek Harness is not ordinary software modularity.&lt;/p&gt;

&lt;p&gt;The deeper goal is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Turn capabilities inside the Agent Runtime from fixed structure into dynamically composable components, while still controlling where those components apply across Agents and when they intervene throughout the runtime lifecycle.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is also why DeepSeek does not stop at simply designing a Plugin API.&lt;/p&gt;

&lt;p&gt;If Memory, Tools, and Sessions are all converted into Plugins but there is no mechanism for managing their dependencies, scopes, and lifecycles, those Plugins will eventually become tangled again. The complexity has merely been moved somewhere else.&lt;/p&gt;

&lt;p&gt;So after “Everything is a Plugin,” the more important question becomes:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Who manages these Plugins, and how can they remain composable inside an Agent Runtime that is constantly changing?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is where Cordis enters the picture.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>tutorial</category>
      <category>agents</category>
    </item>
    <item>
      <title>DeepSeek Harness Deep Dive(1): Introduction to Agents and Harness</title>
      <dc:creator>DA SEIN</dc:creator>
      <pubDate>Thu, 20 Aug 2026 14:04:12 +0000</pubDate>
      <link>https://dev.to/da_sein_dffa21a60a5fd492f/deepseek-harness-analysis-1-introduction-to-agents-and-harness-2adb</link>
      <guid>https://dev.to/da_sein_dffa21a60a5fd492f/deepseek-harness-analysis-1-introduction-to-agents-and-harness-2adb</guid>
      <description>&lt;p&gt;Over the past few years, the development of artificial intelligence has&lt;br&gt;
mainly revolved around Large Language Models (LLMs). As model scale and&lt;br&gt;
the number of parameters continue to increase, their knowledge and&lt;br&gt;
reasoning abilities have improved continuously. However, from a certain&lt;br&gt;
perspective, what LLMs do is still an evolution from simple "fill in the&lt;br&gt;
blank" into a more complex and longer "fill in the blank" process --- a&lt;br&gt;
user's question is essentially a problem given to the model.&lt;/p&gt;

&lt;p&gt;However, this purely conversational interaction is clearly far from&lt;br&gt;
sufficient in real-world applications. For example, when you ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Help me fix the login bug in this project."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A native LLM can list possible causes, suggest solutions, and even&lt;br&gt;
provide code examples, but it cannot truly inspect project files, run&lt;br&gt;
tests, modify code, obtain execution results, or iteratively adjust&lt;br&gt;
itself based on feedback.&lt;/p&gt;

&lt;p&gt;Therefore, in order to make LLMs more practically useful, concepts such&lt;br&gt;
as workflows and agents were developed. Today, agents have become one of&lt;br&gt;
the most widely discussed topics in AI.&lt;/p&gt;

&lt;p&gt;As the beginning of this series analyzing DeepSeek Harness, let's first&lt;br&gt;
briefly introduce what an Agent is.&lt;/p&gt;


&lt;h2&gt;
  
  
  From LLM to Agent
&lt;/h2&gt;

&lt;p&gt;At the simplest level, an LLM can be represented as:&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;LL&lt;/span&gt;&lt;span class="mord mathnormal"&gt;M&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;:&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;C&lt;/span&gt;&lt;span class="mord mathnormal"&gt;o&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mord mathnormal"&gt;e&lt;/span&gt;&lt;span class="mord mathnormal"&gt;x&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;→&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;O&lt;/span&gt;&lt;span class="mord mathnormal"&gt;u&lt;/span&gt;&lt;span class="mord mathnormal"&gt;tp&lt;/span&gt;&lt;span class="mord mathnormal"&gt;u&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;In other words:&lt;/p&gt;

&lt;p&gt;Given a context:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;C&lt;/span&gt;&lt;span class="mord mathnormal"&gt;o&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mord mathnormal"&gt;e&lt;/span&gt;&lt;span class="mord mathnormal"&gt;x&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;the model produces:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;O&lt;/span&gt;&lt;span class="mord mathnormal"&gt;u&lt;/span&gt;&lt;span class="mord mathnormal"&gt;tp&lt;/span&gt;&lt;span class="mord mathnormal"&gt;u&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;Input:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User:
Explain Transformer.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Model output:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Transformer is a neural network architecture based on the Attention mechanism...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;This process is essentially:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;I&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mord mathnormal"&gt;p&lt;/span&gt;&lt;span class="mord mathnormal"&gt;u&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;→&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;M&lt;/span&gt;&lt;span class="mord mathnormal"&gt;o&lt;/span&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="mord mathnormal"&gt;e&lt;/span&gt;&lt;span class="mord mathnormal"&gt;l&lt;/span&gt;&lt;span class="mspace"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;R&lt;/span&gt;&lt;span class="mord mathnormal"&gt;e&lt;/span&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="mord mathnormal"&gt;so&lt;/span&gt;&lt;span class="mord mathnormal"&gt;nin&lt;/span&gt;&lt;span class="mord mathnormal"&gt;g&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;→&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;T&lt;/span&gt;&lt;span class="mord mathnormal"&gt;e&lt;/span&gt;&lt;span class="mord mathnormal"&gt;x&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mspace"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;O&lt;/span&gt;&lt;span class="mord mathnormal"&gt;u&lt;/span&gt;&lt;span class="mord mathnormal"&gt;tp&lt;/span&gt;&lt;span class="mord mathnormal"&gt;u&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;p&gt;This pattern works very well for tasks that are fundamentally&lt;br&gt;
text-based, such as question answering, writing, translation,&lt;br&gt;
summarization, and generating papers.&lt;/p&gt;

&lt;p&gt;However, it lacks one critical capability:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="boxpad"&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;I&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mord mathnormal"&gt;er&lt;/span&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="mord mathnormal"&gt;c&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mord mathnormal"&gt;i&lt;/span&gt;&lt;span class="mord mathnormal"&gt;o&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mspace"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;w&lt;/span&gt;&lt;span class="mord mathnormal"&gt;i&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mord mathnormal"&gt;h&lt;/span&gt;&lt;span class="mspace"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mord mathnormal"&gt;h&lt;/span&gt;&lt;span class="mord mathnormal"&gt;e&lt;/span&gt;&lt;span class="mspace"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;E&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="mord mathnormal"&gt;i&lt;/span&gt;&lt;span class="mord mathnormal"&gt;ro&lt;/span&gt;&lt;span class="mord mathnormal"&gt;nm&lt;/span&gt;&lt;span class="mord mathnormal"&gt;e&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="stretchy fbox"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;Why is interaction with the environment so important?&lt;/p&gt;

&lt;p&gt;The simplest and most practical way to extend the capabilities of models&lt;br&gt;
is not necessarily to build completely new environments, but rather to&lt;br&gt;
allow models to interact with existing tools and systems.&lt;/p&gt;

&lt;p&gt;Therefore, with Agents, models are no longer only answering questions.&lt;br&gt;
They can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Observe the environment (Observe)&lt;/li&gt;
&lt;li&gt;  Make plans (Think)&lt;/li&gt;
&lt;li&gt;  Execute actions (Act)&lt;/li&gt;
&lt;li&gt;  Receive feedback (Observe)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;forming a loop:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;O&lt;/span&gt;&lt;span class="mord mathnormal"&gt;b&lt;/span&gt;&lt;span class="mord mathnormal"&gt;ser&lt;/span&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="mord mathnormal"&gt;e&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;→&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;T&lt;/span&gt;&lt;span class="mord mathnormal"&gt;hink&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;→&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;A&lt;/span&gt;&lt;span class="mord mathnormal"&gt;c&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;→&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;O&lt;/span&gt;&lt;span class="mord mathnormal"&gt;b&lt;/span&gt;&lt;span class="mord mathnormal"&gt;ser&lt;/span&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="mord mathnormal"&gt;e&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;→&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;For example, a Coding Agent:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User:
Fix the failing test.

Agent:

Read project files

↓

Run pytest

↓

Analyze error logs

↓

Modify code

↓

Run tests again

↓

Confirm the fix
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;As we can see, through interaction with the environment, the Agent gains&lt;br&gt;
much higher practical value.&lt;/p&gt;


&lt;h2&gt;
  
  
  From Agent to Harness
&lt;/h2&gt;

&lt;p&gt;A simple Agent can be represented as:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmnhrn7rfe1l6d13i1ghd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmnhrn7rfe1l6d13i1ghd.png" alt="a simple agent" width="800" height="503"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  LLM is responsible for understanding the task and generating the
next decision.&lt;/li&gt;
&lt;li&gt;  Tools provide capabilities such as file operations, search, and API
calls.&lt;/li&gt;
&lt;li&gt;  Environment is the external world where tools interact, such as file
systems, code repositories, databases, and browsers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, this structure is still incomplete.&lt;/p&gt;

&lt;p&gt;It is missing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  State persistence&lt;/li&gt;
&lt;li&gt;  Context management&lt;/li&gt;
&lt;li&gt;  Permission control&lt;/li&gt;
&lt;li&gt;  Execution loops&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These components together form what is called &lt;strong&gt;Harness&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Harness can be understood as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A complete Agent runtime environment deployed around the model.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In simple terms, if the LLM is the "brain", then Harness provides the&lt;br&gt;
nervous system, sensory system, motor system, and memory system that&lt;br&gt;
allow the brain to actually operate.&lt;/p&gt;

&lt;p&gt;Without Harness:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;llm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The model outputs:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Run pytest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;But then:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Who runs pytest?&lt;/li&gt;
&lt;li&gt;  Who records the result?&lt;/li&gt;
&lt;li&gt;  Who sends the result back to the model?&lt;/li&gt;
&lt;li&gt;  Who decides whether the task succeeded?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These responsibilities cannot be handled by the model itself.&lt;/p&gt;

&lt;p&gt;Therefore, an external system is required:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Model proposes an action

↓

Harness receives the action

↓

Execute the tool

↓

Receive feedback

↓

Update context

↓

Call the model again
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Creating this loop:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;C&lt;/span&gt;&lt;span class="mord mathnormal"&gt;o&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mord mathnormal"&gt;e&lt;/span&gt;&lt;span class="mord mathnormal"&gt;x&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;→&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;LL&lt;/span&gt;&lt;span class="mord mathnormal"&gt;M&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;→&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;A&lt;/span&gt;&lt;span class="mord mathnormal"&gt;c&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mord mathnormal"&gt;i&lt;/span&gt;&lt;span class="mord mathnormal"&gt;o&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;→&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;E&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="mord mathnormal"&gt;i&lt;/span&gt;&lt;span class="mord mathnormal"&gt;ro&lt;/span&gt;&lt;span class="mord mathnormal"&gt;nm&lt;/span&gt;&lt;span class="mord mathnormal"&gt;e&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;→&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;O&lt;/span&gt;&lt;span class="mord mathnormal"&gt;b&lt;/span&gt;&lt;span class="mord mathnormal"&gt;ser&lt;/span&gt;&lt;span class="mord mathnormal"&gt;v&lt;/span&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mord mathnormal"&gt;i&lt;/span&gt;&lt;span class="mord mathnormal"&gt;o&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;→&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;C&lt;/span&gt;&lt;span class="mord mathnormal"&gt;o&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mord mathnormal"&gt;e&lt;/span&gt;&lt;span class="mord mathnormal"&gt;x&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mathnormal mtight"&gt;t&lt;/span&gt;&lt;span class="mbin mtight"&gt;+&lt;/span&gt;&lt;span class="mord mtight"&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;p&gt;Therefore, we can define:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="boxpad"&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;A&lt;/span&gt;&lt;span class="mord mathnormal"&gt;g&lt;/span&gt;&lt;span class="mord mathnormal"&gt;e&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;M&lt;/span&gt;&lt;span class="mord mathnormal"&gt;o&lt;/span&gt;&lt;span class="mord mathnormal"&gt;d&lt;/span&gt;&lt;span class="mord mathnormal"&gt;e&lt;/span&gt;&lt;span class="mord mathnormal"&gt;l&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="mord mathnormal"&gt;r&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mord mathnormal"&gt;ess&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="stretchy fbox"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;A useful analogy is:&lt;/p&gt;

&lt;p&gt;If the LLM is the brain, Harness is the nervous system, sensory system,&lt;br&gt;
motor system, and memory system.&lt;/p&gt;

&lt;p&gt;Without these systems, the brain cannot act independently.&lt;/p&gt;

&lt;p&gt;Therefore, it is easy to understand why the same model can perform&lt;br&gt;
completely differently under different Harness designs.&lt;/p&gt;


&lt;h2&gt;
  
  
  From Harness to DeepSeek Harness
&lt;/h2&gt;

&lt;p&gt;As mentioned above, the LLM itself only performs:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;C&lt;/span&gt;&lt;span class="mord mathnormal"&gt;o&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mord mathnormal"&gt;e&lt;/span&gt;&lt;span class="mord mathnormal"&gt;x&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;→&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;O&lt;/span&gt;&lt;span class="mord mathnormal"&gt;u&lt;/span&gt;&lt;span class="mord mathnormal"&gt;tp&lt;/span&gt;&lt;span class="mord mathnormal"&gt;u&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;What truly turns it into an Agent is the external runtime mechanism that&lt;br&gt;
continuously executes actions, receives feedback, updates state, and&lt;br&gt;
calls the model again.&lt;/p&gt;

&lt;p&gt;Harness is responsible for supporting this entire loop.&lt;/p&gt;

&lt;p&gt;The most direct responsibility is Tool Management.&lt;/p&gt;

&lt;p&gt;The model may decide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  "Run pytest"&lt;/li&gt;
&lt;li&gt;  "Read this file"&lt;/li&gt;
&lt;li&gt;  "Call this API"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But the actual execution, result collection, error handling, and&lt;br&gt;
returning results back to the model are all handled by Harness.&lt;/p&gt;

&lt;p&gt;Without this layer, the model's actions remain only text.&lt;/p&gt;

&lt;p&gt;However, once tools begin running, another problem immediately appears:&lt;/p&gt;

&lt;p&gt;The model needs to know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  What happened before?&lt;/li&gt;
&lt;li&gt;  What actions have already been taken?&lt;/li&gt;
&lt;li&gt;  What are the tool results?&lt;/li&gt;
&lt;li&gt;  What is the original goal?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Therefore, Harness also needs to manage Context.&lt;/p&gt;

&lt;p&gt;It organizes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  User requirements&lt;/li&gt;
&lt;li&gt;  Historical actions&lt;/li&gt;
&lt;li&gt;  Tool results&lt;/li&gt;
&lt;li&gt;  Current environment state&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;into the input used for the next model call.&lt;/p&gt;

&lt;p&gt;As tasks become longer, Harness must decide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Which information should be kept?&lt;/li&gt;
&lt;li&gt;  Which information should be compressed?&lt;/li&gt;
&lt;li&gt;  Which information can be discarded?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Furthermore, if a task needs to run for a long time, maintaining only&lt;br&gt;
the current Context is not enough.&lt;/p&gt;

&lt;p&gt;The Agent also needs to know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  What it has already done&lt;/li&gt;
&lt;li&gt;  Where it currently is&lt;/li&gt;
&lt;li&gt;  How to continue after interruption&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is Session Management.&lt;/p&gt;

&lt;p&gt;It stores the execution state of the entire task.&lt;/p&gt;

&lt;p&gt;Finally, the execution loop itself cannot run forever.&lt;/p&gt;

&lt;p&gt;Harness needs to control:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  When a tool can be executed&lt;/li&gt;
&lt;li&gt;  When user confirmation is required&lt;/li&gt;
&lt;li&gt;  Whether to retry after failure&lt;/li&gt;
&lt;li&gt;  Whether to continue&lt;/li&gt;
&lt;li&gt;  When to stop&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is Execution Control.&lt;/p&gt;

&lt;p&gt;Therefore, a mature Harness can be roughly described as:&lt;/p&gt;


&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="mord mathnormal"&gt;r&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mord mathnormal"&gt;ess&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;≈&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;T&lt;/span&gt;&lt;span class="mord mathnormal"&gt;oo&lt;/span&gt;&lt;span class="mord mathnormal"&gt;l&lt;/span&gt;&lt;span class="mspace"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;M&lt;/span&gt;&lt;span class="mord mathnormal"&gt;ana&lt;/span&gt;&lt;span class="mord mathnormal"&gt;g&lt;/span&gt;&lt;span class="mord mathnormal"&gt;e&lt;/span&gt;&lt;span class="mord mathnormal"&gt;m&lt;/span&gt;&lt;span class="mord mathnormal"&gt;e&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;C&lt;/span&gt;&lt;span class="mord mathnormal"&gt;o&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mord mathnormal"&gt;e&lt;/span&gt;&lt;span class="mord mathnormal"&gt;x&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mspace"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;M&lt;/span&gt;&lt;span class="mord mathnormal"&gt;ana&lt;/span&gt;&lt;span class="mord mathnormal"&gt;g&lt;/span&gt;&lt;span class="mord mathnormal"&gt;e&lt;/span&gt;&lt;span class="mord mathnormal"&gt;m&lt;/span&gt;&lt;span class="mord mathnormal"&gt;e&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;S&lt;/span&gt;&lt;span class="mord mathnormal"&gt;ess&lt;/span&gt;&lt;span class="mord mathnormal"&gt;i&lt;/span&gt;&lt;span class="mord mathnormal"&gt;o&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mspace"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;M&lt;/span&gt;&lt;span class="mord mathnormal"&gt;ana&lt;/span&gt;&lt;span class="mord mathnormal"&gt;g&lt;/span&gt;&lt;span class="mord mathnormal"&gt;e&lt;/span&gt;&lt;span class="mord mathnormal"&gt;m&lt;/span&gt;&lt;span class="mord mathnormal"&gt;e&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;E&lt;/span&gt;&lt;span class="mord mathnormal"&gt;x&lt;/span&gt;&lt;span class="mord mathnormal"&gt;ec&lt;/span&gt;&lt;span class="mord mathnormal"&gt;u&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mord mathnormal"&gt;i&lt;/span&gt;&lt;span class="mord mathnormal"&gt;o&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mspace"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;C&lt;/span&gt;&lt;span class="mord mathnormal"&gt;o&lt;/span&gt;&lt;span class="mord mathnormal"&gt;n&lt;/span&gt;&lt;span class="mord mathnormal"&gt;t&lt;/span&gt;&lt;span class="mord mathnormal"&gt;ro&lt;/span&gt;&lt;span class="mord mathnormal"&gt;l&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fybubruro7nrba06lp65m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fybubruro7nrba06lp65m.png" alt="Harness and ......" width="800" height="738"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Naturally, as Agent systems develop, the number of tools increases,&lt;br&gt;
Context becomes longer, Sessions become more complex, and additional&lt;br&gt;
capabilities such as permissions, logging, lifecycle management, and&lt;br&gt;
more extensions are introduced.&lt;/p&gt;

&lt;p&gt;Once Harness starts taking responsibility for these capabilities, it can&lt;br&gt;
quickly become a complex system itself.&lt;/p&gt;

&lt;p&gt;Therefore, a new question naturally emerges:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How can we allow Harness to continuously gain new capabilities without&lt;br&gt;
putting everything into the Runtime core and eventually turning it&lt;br&gt;
into an increasingly bloated and difficult-to-maintain system?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Or, more directly:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How do we manage the growing complexity of Harness itself?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In my view, one of the values of DeepSeek Harness lies exactly here.&lt;/p&gt;

&lt;p&gt;Its design philosophy starts from:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Everything is a Plugin&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>tutorial</category>
      <category>deepseek</category>
    </item>
  </channel>
</rss>
