DSH plugin agent lifecycle: turn/step and event streams
The most common agent-lifecycle mistake is treating two event families as one: agent/* is real-time coordination, while session/event is durable replay. The first tells you what is queued, running, or worth retrying; the second tells you what actually happened. Decide which one you need before writing a plugin, or you will see “it was live but not in replay” and misread it as data loss.
DeepSeek Harness: The shape of a turn
A user input enters the inbox, the driver claims it as a turn, and the turn can run multiple steps. The main sequence:(source)
- followup(content) — a user or upstream puts a message in the inbox. Expected:
agent/inbox/splicedandagent/inbox/inserted. - turn/start — the driver wakes and status becomes running. Expected: it claims pending next-step input plus one queued prompt.
- system-prompt/assemble — the system prompt is assembled. Expected: a waterfall can rewrite it here.
- agent/pre-step — decides whether to enter a message batch. Expected: reject or enter(messages).
- step/start — a step begins. Expected:
agent/request, request preparation, and message admission follow. - assistant/message or assistant/attempt — records success or a failed attempt. Expected:
agent/assistant-streamemits chunks first, then a committed end. - Tool execution — classified by executionMode and scheduled with barriers and a bounded rolling pool. Expected:
tool/call, tool-owned events, andtool/resultin order. - step/end → turn/end — the turn closes when there is no next-step input and the agent stops naturally. Expected: status returns to idle.
If pre-step rejects, the first batch is empty, or pre-step fails, the claimed batch stays removed and the open turn spends no step. That is a normal refusal, not an error.
DeepSeek Harness: agent/* versus session/event
Real-time state and durable facts are separate channels; consuming the wrong one gives an incomplete history. Compare:(source)
| Channel | Content | Best for |
|---|---|---|
agent/* | queues, status, request construction, steering, errors | UI and real-time plugins |
session/event | turns, steps, messages, tool calls and results | SDK transcripts, replay, audit |
The official guidance is direct: SDK users who need a replayable transcript should consume session/event. agent/* is not history; it is coordination.
Realtime agent/assistant-stream chunks are transient. Replay reads the durable settlement in assistant/message or assistant/attempt. A hard interrupt before settlement leaves no persistent attempt stream.
DeepSeek Harness: Three intervention points
A plugin does not need to modify the driver; pick the right hook: pre-step for admission, request-error for overflow, turn-stopping for closure. Three points:(source)
agent/pre-step— intercept or replace messages before the request is built. Expected: reject a batch, add context, or preserve downstream messages.agent/request-error— handle canonical context overflow and retry decisions. Expected: return a retry action or preserve the original error; do not use it as a generic catch-all.agent/turn-stopping— a serial terminal checkpoint when the agent stops naturally with an empty inbox. Expected: close out checks; do not start long work here.
When wrapping next(), preserve downstream messages and startsRequestSeries unless you intend to replace the whole batch.
DeepSeek Harness: Tool concurrency and barriers
Tools do not all run concurrently; the driver classifies by executionMode and controls the pace with barriers and a bounded rolling pool. Key points:(source)
- Classify before start — each pending call gets an execution mode. Expected: read-only and write calls do not interleave arbitrarily.
- Ordered pre, concurrent execute, ordered post — pre and post follow model order, execution may run concurrently. Expected: results still match the model’s request order.
- Tool-owned events — tools may emit their own events during execution. Expected: they do not replace
tool/result. - Barriers reclassify — the rolling pool rechecks before starting. Expected: state changes cannot bypass a barrier.
When writing a tool plugin, do not assume the previous tool has finished; declare ordering explicitly instead of relying on timing.
DeepSeek Harness: Three consumption modes
UI, SDK transcript, and plugin hooks need different streams; choosing wrong adds glue code. Three:(source)
- UI real-time — consume
agent/statusandagent/assistant-stream. Expected: status and streaming stay current. - SDK transcript — consume
session/event. Expected: complete turns, steps, and tool results for replay. - Plugin hooks — listen to
agent/pre-step,agent/request-error, andagent/turn-stopping. Expected: intervene at the right phase without breaking driver order.
If the two channels disagree, use session/event for history and agent/* for real-time coordination.
DeepSeek Harness: A compact event order
When debugging timing, list the key events in order instead of reading the whole log. Simplified:(source)
| Phase | Key events | Meaning |
|---|---|---|
| Enqueue | agent/inbox/spliced, inserted | Message enters the inbox |
| Start | turn/start, agent/status running | Driver claims input |
| Admit | system-prompt/assemble, agent/pre-step | Decide whether to enter a batch |
| Request | step/start, agent/request | Prepare and send the model request |
| Result | assistant/message or assistant/attempt | Successful message or failed attempt |
| Tools | tool/call, tool/result | Schedule by executionMode |
| Close | step/end, turn/end, agent/status idle | Turn ends |
If a segment is missing, do not blame the model first; check whether pre-step rejected it, it was cancelled, or the process stopped before settlement.
Three diagnostic rules
Timing problems are easier to locate by “which segment is missing” than by reading every line. Three rules:
- turn/start without step/start — usually pre-step rejection, an empty first batch, or pre-step failure. Expected: the turn spends no step; this is a normal refusal.
- step/start without assistant/message — the request failed or was cancelled, possibly leaving
assistant/attempt. Expected: check request-error and the cancellation reason. - tool/call without tool/result — the tool is still running, blocked by a barrier, or the process stopped. Expected: inspect executionMode and active execution.
These rules point at admission, request, or tool layers instead of a vague “the agent is stuck”.
DeepSeek Harness FAQ
Why is there live output but no replay? Realtime chunks are transient; replay reads settlement. An attempt without settlement leaves no persistent stream.
Can a step appear after turn/end? No. turn/end is the end of the turn; the next input starts a new turn.
Where does compaction happen?
Base compaction handles pressure through agent/pre-step; agent/request-error handles canonical context overflow. It prunes tool results before choosing summarization.
The short version: real-time uses agent/*, history uses session/event, and intervention picks the right hook. Mixing them turns coordination state into a false audit trail.
FAQ
DeepSeek Harness: agent/* is real-time control and state: queues, status, request construction, steering, and error handling. session/event is durable replay: turns, steps, messages, and tool results. SDK transcript consumers should read session/event.
DeepSeek Harness: a turn can contain multiple steps. Each step is one model request plus the tool execution that follows. A new step starts when the inbox has next-step input or tool results require another request.
DeepSeek Harness: the claimed batch stays removed and the open turn spends no step. The same applies when the first batch is empty or pre-step fails. A listener that wraps next() can preserve downstream messages and startsRequestSeries.
DeepSeek Harness: no. It is primarily for canonical context overflow. Compaction handles pressure in pre-step, then request-error triggers tool-result pruning and summarization. Use specific error paths for ordinary failures.
DeepSeek Harness: no. agent/assistant-stream chunk frames are transient. Replay reads the durable settlement in assistant/message or assistant/attempt; a hard interrupt before settlement leaves no persistent attempt stream.
Related Terms
- turn
- A turn is one complete user-input-driven cycle in DeepSeek Harness, from turn/start to turn/end. A turn can contain multiple steps.— DeepSeek Harness reference - Agent turn and step lifecycle
- step
- A step is one model request and tool execution unit inside a turn, from step/start to step/end. Messages, requests, and tool results happen inside a step.— DeepSeek Harness reference - Agent turn and step lifecycle
- agent/pre-step
- agent/pre-step is a DeepSeek Harness waterfall hook that decides whether a message batch enters before a model request is built. A rejection does not spend a step.— DeepSeek Harness reference - Agent turn and step lifecycle
- session/event
- session/event is the durable DeepSeek Harness session event stream containing turns, steps, messages, tool calls, and results. It is the source of truth for replay and SDK transcripts.— DeepSeek Harness reference - Agent turn and step lifecycle
Sources
- DeepSeek Harness reference - Agent turn and step lifecycle· deepseek-ai
- DeepSeek Harness reference - Sessions· deepseek-ai