Introduction¶
The plugin-based architecture of DeepSeek Harness (DSH) allows capabilities to be dynamically extended at runtime. While an agent performs time-consuming tasks (such as long text generation or tool calls), traditional interaction models often require users to wait for the current turn to end, or use steer to wait for the next step boundary. This makes it impossible for users to insert new instructions while waiting, fragmenting the interaction experience.
The dsh-autofork plugin solves this problem with a passive trigger mechanism on the harness side: when it detects that the agent is busy and cannot be interrupted, newly submitted user instructions are automatically executed in a new session (fork). The original session remains in the background and continues running until completion, then its result is injected back into the foreground session. This mechanism transforms “must wait” serial interaction into “can interject anytime” parallel interaction.
Core Features¶
- Automatic forking: When the agent is busy, new instructions automatically trigger a fork, allowing users to receive an immediate response in an idle session.
- Background continuation and injection: The original session is not aborted; after it completes, its result is injected into the current session.
- Family lineage view: Provides a “Fork” tab that displays the lineage tree of forked sessions.
- Toolset: Exposes three tools—
fork_list,fork_steer, andfork_cancel—for foreground invocation. - Container mode: An experimental feature that attempts to route messages to a bound instance for processing.
Installation and Enablement¶
Install it using the official plugin command:
dsh plugin --profile web add github:vlln/dsh-autofork
After installation, restart the web process so the bundle can reload the layer stack.
Usage¶
- Trigger condition: A fork is triggered only when the agent is running the current turn and cannot be interrupted in time. If the agent is idle, it responds directly, without creating an unnecessary session.
- Fork behavior:
- A new session appears in the left-hand list, named
⑂n <original session name>. - Focus automatically switches to the new session, allowing users to interact immediately with the idle agent.
- The old session continues running in the background, and its result is injected back after completion.
- Fork tab: Displays the lineage tree of the entire family, including session status, triggering instruction, and fork time.
- Injected summary: Injected content is collapsed by default into a one-line summary, which can be expanded for viewing.
Tools and Parameters¶
The plugin exposes three tools to the foreground:
| Tool | Description |
|---|---|
fork_list |
Lists family sessions and shows their names and real-time status (running / idle / ended). ↑ indicates that the session took over the foreground, ↓ indicates that it was taken over by the foreground, and ~ indicates another fork in the same family. |
fork_steer |
Sends a mid-flight instruction to a session in the family; equivalent to steer, without requiring abortion. |
fork_cancel |
Aborts a session in the family. Parameter keepInbox=true aborts only the current turn and retains pending items. |
Configuration parameters are centralized in src/params.mjs; the key parameters are as follows:
| Parameter | Default | Description |
|---|---|---|
enabled |
true |
Master switch. |
minStepAgeMs |
0 |
Fork threshold: no fork is created if the step has been running for less than this duration. |
coalesceWindowMs |
2000 |
Falls back to steer when the next step boundary is less than this duration away. |
maxActiveBranches |
3 |
Maximum number of active background forks under the same foreground. |
followHead |
true |
Whether to switch focus to the newly created fork. |
titleMark |
'⑂' |
Naming marker for forked sessions; format is <marker><number> <family root name>. |
noticeSummaries |
true |
Whether injected messages are collapsed into a one-line summary. |
exposeDispatchTools |
true |
Whether to expose tools to the foreground. |
containerMode |
false |
Container mode (experimental), disabled by default. |
mirrorDelivery |
'safe' |
Instance reply delivery method. 'immediate' is known to corrupt container transcripts. |
Limitations and Notes¶
- Not a subagent tree: Forked sessions are regular sessions and do not appear in the native “subagent” instance tree. Family relationships are represented by the “Fork” tab and
fork_list. - Naming limitation: Once fork naming is enabled, sessions are no longer auto-named, and the title is pinned.
- File isolation: There is no file-level isolation; forks and the old session share the same
cwd. Concurrent file writes require manual coordination (for example, using a stale-version guard). - Experimental switches:
containerModecan cause duplicate work between containers and forks, andmirrorDelivery: 'immediate'is known to corrupt session transcripts. It is recommended to keep the defaults. - Platform limitations: Some client features only take effect on the web platform (
dsh.client.platform = web).
Verification and Self-Check¶
- Health check:
GET /api/dsh-autofork/health[?sessionId=<id>]returns plugin parameters, registered tools, and family status. - Local verification: Run
npm run verifyto perform syntax checks, static gates, and tests.
License¶
MIT