DeepSeek Harness Session V4: Tool Result Restructure, Source Identity & Migration Impact
This article details the major data structure changes in DeepSeek Harness Session V4, including tool/result message restructuring, source.kind identity model shift, new developer/message surface type, dynamic tool history via headerSeq, deferLoading schema support, and migration rules affecting plugin authors and session parsers.
In version 0.1.7, DeepSeek Harness upgrades its session format from V3 to V4. This change is critical for developers who write plugins, session parsers, replay tools, or directly process Harness Session JSONL files.
1. tool/result No Longer Classified as user Message
Session V4 redesigns the Tool Result data structure. In V3, the event type was tool/result but the internal message still used role: "user" with the tool result wrapped in a tool-result content block. The hierarchy was:
tool/result Event
↓
user message
↓
tool-result wrapper
↓
actual tool contentV4 promotes Tool Result to a true tool message:
tool/result Event
↓
tool message
↓
direct tool contentKey field mappings:
V3: role: "user" → V4: role: "tool" V3: content[0].toolCallId → V4: message.toolCallId V3: content[0].content → V4: message.content V3: content[0].isError → V4: message.isError V3: type: "tool-result" wrapper → V4: removed
Old detection logic like
if (message.role === "user" && message.content[0]?.type === "tool-result")breaks in V4. New logic should check message.role === "tool" and read message.toolCallId, message.content, message.isError directly.
2. source.kind: From Source Category to Producer Identity
V3 used a two-field model: kind: "plugin" for category and plugin: "abc" for specific producer. V4 merges them into a single kind field with format "plugin:abc". The kind now directly carries the producer identity.
Old plugins outputting { "kind": "plugin", "plugin": "abc" } will trigger error: format v4 message requires a producer-owned source kind. This enforces stricter message provenance semantics.
Session now records message producer identity as structured semantics.
3. Session Surface Adds developer/message
V3 model-visible surface included: system/message, user/message, assistant/message, tool/result. V4 adds developer/message as a first-class surface type. It participates in session replay, surface append/replace, fork, compaction, and history reconstruction. This allows developer-layer instructions and state changes to be formally persisted in the session history, not just reconstructed at runtime.
4. Dynamic Tool Changes Gain Formal Session History
Via developer/message, V4 records tool-addition and tool-removal events. Sessions now capture when tools are added or removed during execution, crucial for long-running sessions, dynamic plugins, and on-demand tool loading, especially for debugging.
5. headerSeq: Dynamic Tools Bound to Historical Request Header
Tool additions are not just a tool name; they bind via headerSeq to a previously saved request/header. Example:
seq 100
request/header
tools:
- name: search
description: ...
parameters: ...
seq 135
developer/message
headerSeq: 100
content:
- type: tool-addition
toolName: searchOn replay, Harness reads the tool definition from the historical request header (seq 100), not the current environment. This ensures deterministic replay regardless of present tool versions.
6. Tool Schema Officially Supports deferLoading
V4 introduces deferLoading?: true in tool schemas. Migration does not retroactively reinterpret a V3 extension field named deferLoading as the new V4 meaning. This reflects a core migration principle: new versions must not rewrite old data semantics.
7. Migration Rules
Namespace cleanup: Harness core types and third-party extensions placed in separate namespaces to avoid collisions.
Migrator only processes explicitly defined schemas; it modifies only positions with certain semantics.
Additional rules visible in migration source code.
8. Common Post-Upgrade Issues
Still Writing source.kind = "plugin"
Old format { "kind": "plugin", "plugin": "my-plugin" } must adapt to producer-owned source.
Treating Tool Result as user Message
Logic relying on role = user and content[0].type = tool-result fails.
Depending on tool-result Wrapper
Fields toolCallId, content, isError are now at message level.
Hardcoding Surface Types to Four
Parsers must now handle developer/message or risk dropping developer history.
Strict Tool Schema Whitelist
Code allowing only name, description, parameters must add deferLoading support.
Custom Extension Types Lacking Namespace Awareness
Migrated extensions may appear as plugin:<type>; code recognizing bare names needs adjustment.
Summary
Session V4 strengthens historical determinism: tool additions bind to historical request headers via headerSeq, parent sessions can use child evidence to complete catalogs, historical extensions are namespaced, and certain known V3 anomaly logs can be safely fixed during migration.
References
https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/session/session-format-v3-to-v4/README.md https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/cookbook/adding-a-session-format-version.mdSigned-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
DeepHub IMBA
A must‑follow public account sharing practical AI insights. Follow now. internet + machine learning + big data + architecture = IMBA
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
