Imagine asking an Agent to investigate an intermittent failure: read the logs and configuration, find the cause, then decide whether anything needs changing. Once it starts, you remember a constraint and add: “Don't write files yet. Just give me the analysis.”
The model may still be streaming, or it may already have requested several tools. Should the system insert that message into the current request immediately? Should it interrupt reads already in progress? If a write is awaiting approval, can another policy still block it after you click Allow?
“Call the model, run tools, repeat” does not answer these questions. DeepSeek Harness puts its default driver in agent-loop, surrounded by input queues, tool scheduling, and execution policy. This final article connects them through that hypothetical investigation. The source is pinned to dsh-v0.1.2-rc.1; this is neither an official incident report nor a real repair task performed for the article. Driver overview
Entering the system is not entering the model
Start with your added constraint. The Agent has two pending lists: next-turn for later turns and next-step for the next step boundary. followup() adds input to the next turn and wakes the driver. steer() targets the next step and wakes it. inject() also targets the next step but does not wake an idle Agent. Input entry points
Supplying context and starting work are therefore distinct operations. A plugin can stage background information until actual work arrives. Adding an item to a queue also cannot rewrite input already sent to a model. Messages are normally claimed at the next step boundary.
At a turn's beginning, the Inbox claims all next-step input, followed by one queued next-turn message. Later steps within that turn claim only next-step input. Independent queued assignments do not all collapse into the current step, while input intended to steer current work can enter the following one. Inbox claiming
This version records queue insertions, removals, and claims as agent/inbox/spliced events. Inbox construction replays its own events to reconstruct pending state. The same message identity cannot be pending twice across the two lists. A recoverable queue is still not model history: claimed input must pass the next admission point before being recorded as user/message.
One turn can ask the model many times
Two terms matter here. A turn encloses a round of work. A step is a model request and its subsequent tool processing. The driver records turn/start, claims input, assembles the prompt, and asks agent/pre-step whether to enter.
That admission point can reject or rewrite the proposed messages. Rejection produces a blocked turn. An initial entry rewritten to an empty batch can finish without spending a model call. Only after admission does the driver record step/start and the messages actually entering it. Queued, claimed, and model-visible are different states. Turn state machine
If the model answers without tool calls, the step can finish. With tool calls, the driver executes and records their results, usually owing another model request to interpret them. The source represents that obligation by not yet having a step-ending reason. A tool result can carry concludesTurn, making the step completed after the tool batch; it is not an instruction to cancel the remaining tools immediately.
Even a completed step can be followed by new next-step input. The agent/turn-stopping extension point also lets policy participate before final exit. It is a serial event, not another instance of a universal middleware protocol with next(). Ending an Agent turn involves more than noticing that the model stopped talking. Steps and turn stopping
Run several tools without scrambling the record
In our investigation, reading logs and configuration may be independent, while modifying a file may depend on earlier results. Harness classifies tool execution, places parallel-safe calls into a bounded rolling pool, and treats exclusive calls as barriers.
Suppose A, B, and C are parallel calls and the pool holds two. If A is slow but B finishes quickly, C can start when B finishes; it need not wait for the initial batch to finish together. An exclusive X waits for the preceding pool to drain, runs alone, and holds later calls until it finishes. Tool scheduler

Dispatch and tool bodies can overlap, but preparation policy and final result processing remain model-ordered. The scheduler stores an outcome in each call's slot, and committed advances only through contiguous ready slots. B may finish first and release concurrency capacity, but its final result cannot pass unfinished A into history. Additional context follows those ordered results into the next-step queue.
This deliberately retains some waiting. A slow A delays final recording of later results without necessarily stopping the pool from using free capacity. The default limit is ten parallel calls, not ten threads or a model-service throughput guarantee. Later calls are also reclassified before starting, rather than assuming the earliest registry state remains valid forever. Configuration, rolling pool and commit cursor
Safe concurrency cannot be inferred from a tool's name alone. This version classifies individual calls. If safety requires comparing sibling calls against shared resources, those calls should remain exclusive. The scheduler does not supply file locking or database conflict detection for every business operation.
The model's request is not execution permission
When a write reaches the front of the queue, the model has expressed intent. The tool registry still runs an execution pipeline. tools/pre-execute produces an allow, deny, or ask decision. An ask is resolved through the approval service.
Missing approval services, unroutable agent-less calls, and unavailable approval channels do not turn an inability to ask into permission. A one-time approval only lets the call proceed to the next stage. Registered monotonic guards still follow: they can deny or abstain, but cannot override another guard's denial with a forced allow. Approval resolution and guards

The ordering is useful. Extensible preparation middleware handles interaction, explanations, and deployment policy; restrictions that a later allow must not overturn belong in guards. For example, approving a write within one directory need not defeat a separate scope restriction. This illustrates the architecture; the registry itself does not implement every possible filesystem permission rule.
After execution come tools/post-execute, tool-owned content finalization, and final-result notification. A preparation denial skips the body but can still pass through result handling to produce a model-readable failure. The model can adjust its plan on the next step instead of encountering a vanished tool call. Execution pipeline
Changing returned text does not undo side effects. If an operation has written to a remote service, rewriting its result as an error cannot erase that write. Permission checks must precede the relevant side effect, and business systems still own their data permissions and transaction rules.
Why Stop can take a moment
agent.cancel() aborts the active AbortController and clears pending input by default. The caller must explicitly set keepInbox to retain the queue. New waking input arriving after cancellation is routed to the next turn, rather than being inserted into an already-aborted activity. Cancellation and waking again
For the tool pool, cancellation first stops replenishment, then waits for started calls to settle and commit. Remaining undispatched model calls receive synthetic tool/call and error-result pairs with ABORTED_BEFORE_DISPATCH. These records explain why execution did not happen; they do not prove the tool body ran. Scheduler cancellation
The registry also retains the original caller signal. Even if an around-wrapper replaces the execution signal, both are fused before entering the body. Once a body starts, the registry awaits its Promise's settlement instead of winning a Promise race and abandoning active work. Whether the side effect can actually stop depends on the tool's response to that signal. Tool bodies and signal fusion
Stopping can therefore take time. A tool that ignores cancellation and never settles its Promise can hold up this cooperative exit path. The loop does not promise to kill every external operation instantly. Required timeouts, process termination, or container restrictions belong in the relevant plugins and execution backends; the presence of a Stop button does not establish those capabilities.
Preserve why execution ended
If cancellation interrupts a streamed answer, the driver retains recordable content already delivered, appends an assistant message marked interrupted: true, and cites the corresponding chunks. The prefix the user saw need not disappear without explanation from later model history.
Steps and turns also have their own ending records. Cancellation records an aborted outcome and its cause; ordinary failure records an error. Reaching max-tokens remains significant rather than being casually downgraded by a later normal step. Model-request recovery involves agent/request-error; tool errors, plugin exceptions, and model-service failures do not all become one unconditional retry mechanism. Ending states and request recovery
This version has no built-in whole-turn budget. Tool calls or new input can keep work moving, and a deployment that bounds runaway turns needs policy using existing lifecycle cancellation points. Concurrency limits bound simultaneous tools, and token limits bound a request's output. Neither replaces a budget for an entire task's elapsed time or number of calls.
Reliability is more concrete than apparent intelligence
Across four articles, the responsibilities now form a chain. Plugin composition makes capabilities replaceable. Workflow expresses multi-agent assignments as control flow. Session retains traceable facts. The Agent loop connects input, requests, tools, and ending states. Reliability depends on those boundaries fitting together, not only on how convincing the next model answer sounds.
For this article, 18 checks executed the pinned tool-calls.ts and inbox.ts, covering rolling replenishment, exclusive barriers, ordered results, cancellation, and queue reconstruction. Registry stages, Session, and message creation used substitutes. No complete Agent, real model, or approval channel was exercised. Permission and signal-fusion claims are supported by source inspection, not a production isolation test.
This completes the four-part DeepSeek Harness series. Next comes Hermes Agent: its architectural organization and runtime paths offer another way to examine which state and capabilities should be shared across entry points, and which should stay separate.

