HTTP 境界をなくしたローカルコーディングエージェント: DwarfStar の native agent を読む【第7回/全8回】
本シリーズは、DeepSeek V4 Flash / Pro 専用推論エンジン DwarfStar(
ds4)のコードを読み解く連載です。
第7回は、ds4-agentを扱います。OpenAI/Anthropic 互換サーバではなく、推論エンジンを同じプロセスの内側から直接操作するネイティブコーディングエージェントです。主な参照箇所:
README.md,AGENT.md,ds4_agent.c,ds4_kvstore.c,ds4.h読みどころ: HTTP 境界を外すと、サーバ編で苦労した KV 整合性問題が「構造的に起きない」状態になります。そのトレードオフを読みます。
連載「ds4.c を読み解く」全8回
- 第1回 なぜ専用エンジンを書くのか
- 第2回 非対称2bit量子化とimatrix
- 第3回 Metalグラフと圧縮KV
- 第4回 ディスクKVキャッシュ
- 第5回 サーバとDSMLツール呼び出し
- 第6回 TCPパイプライン分散推論
- 第7回 ネイティブエージェント(本記事)
- 第8回 ステアリング・MTP・評価基盤
TL;DR
-
ds4-agentは HTTP API 境界を持たない。UI スレッドとワーカースレッドは分かれるが、ワーカーがライブのds4_sessionと KV 状態を直接所有する。 - README は、エージェントのセッションがオンディスク KV キャッシュそのものとして表現される、と説明している。
- サーバ編で必要だった OpenAI/Anthropic JSON と DSML の往復変換が薄くなる。エージェントのツールプロンプトは DeepSeek V4 用 DSML を前提に作られ、ツール実行もネイティブ DSML パーサから直接ディスパッチされる。
- セッションは
~/.ds4/kvcacheに保存され、/save,/list,/switch,/del,/stripで操作できる。 - 保存セッションの ID は最初のユーザープロンプト由来のタイトルと作成時刻から SHA1 で作る。再保存しても同じ同一性を保つ。
- ツールは
read,more,write,edit,search,list,bash,bash_status,bash_stop,google_search,visit_pageなど。編集プロンプトは DS4 の低速デコードと長文脈を意識して、アンカー付き編集を強く促している。 -
ds4-agentは README 上で明示的に alpha 品質とされ(エンジン本体の beta より前段階)、プロジェクトに後から追加された。とはいえ「ローカル推論をエージェントとして本当に使えるか」を検証するための垂直統合として重要。
1. なぜネイティブエージェントを持つのか
第5回で見た ds4-server は、OpenAI/Anthropic 互換 API を持つために、多くの変換を行っていました。
- OpenAI のツール呼び出し JSON
- Anthropic の
tool_useブロック - OpenAI Responses のアイテムライフサイクル
- DeepSeek V4 の DSML テキスト
- ライブのサンプル済み状態
- ステートレスなクライアントトランスクリプト
これは既存クライアントと接続するには必要ですが、複雑です。
一方 ds4-agent は、最初から DS4 / DeepSeek V4 のために作られたネイティブエージェントです。README は次のように説明しています。
- 推論はエージェント自身の内側から制御される
- ソケット/API 境界がない
- セッションはオンディスク KV キャッシュそのものとして表現される
- ツールとシステムプロンプトは DeepSeek V4 Flash / Pro 向けに垂直設計されている
要するに、既存 API 互換ではなく、「このエンジンとこのモデルに最も合うエージェント」を作る方向です。
2. プロセスモデル: UI スレッドとワーカースレッド
ds4_agent.c の冒頭のコメントは、エージェントのスレッドモデルを説明しています。
/* The agent is intentionally a single process: the UI thread owns terminal
* input/output, while the worker thread owns the live DS4 session and KV state.
* ... used to render sampled assistant text and DSML tool calls as they arrive.
*/
サーバではクライアントスレッドがリクエストをキューに積み、単一グラフワーカーが処理しました。エージェントでもライブセッションをワーカー側に閉じ込める考え方は同じです。
違うのは、外部の HTTP プロトコルがないことです。UI はターミナル入力と表示を担当し、ワーカーは ds4_session、トランスクリプト、ツール実行、KV の保存/ロードを扱います。
agent_worker には以下のような状態があります。
ds4_session *session;
ds4_tokens transcript;
char session_sha[41];
char *session_title;
uint64_t session_created_at;
bool session_dirty;
ここで transcript はレンダリング済みチャットトークン列、session はライブ KV チェックポイントを持つ実体です。
3. セッションは ~/.ds4/kvcache に保存される
README によると、エージェントのセッションは ~/.ds4/kvcache に保存されます。
主要コマンド
| コマンド | 役割 |
|---|---|
/save |
現在のセッションを保存 |
/list |
保存セッションを最近の更新順に表示 |
/switch <sha> |
セッションを再開 |
/del <sha> |
保存セッションを削除 |
/strip <sha> |
重い KV ペイロードを削除し、レンダリング済みテキストだけ残す |
/strip が面白いです。KV ペイロードは大きいため、不要になったらトランスクリプトとタイトルだけ残せます。strip 済みセッションに switch すると、保存されたレンダリング済みテキストを prefill して KV を再構築します。
フル KV セッションなら、switch 後に prefill なしで再開できます。これは README が挙げるネイティブエージェントの利点の一つです。セッションの状態遷移を図にすると、「KV の有無」が中心にあることが分かります。
4. セッションの同一性はタイトルと作成時刻
サーバのディスク KV はレンダリング後バイトプレフィックスの SHA1 をファイル名にしました。エージェントのセッションでは、少し違う同一性を使います。
ds4_agent.c のコメント
/* Modern sessions:
* SHA1(title || created_at_le64).kv, where title is the first user prompt and
* created_at is preserved across future saves. The title is stored in an
* agent-only trailer after the KV payload.
*/
保存済みセッションのファイル名は、最初のユーザープロンプトから作ったタイトルと作成時刻の SHA1 です。再保存してトランスクリプトと KV ペイロードが更新されても、セッションの同一性は変わりません。
これはエージェントの UX に合っています。会話が伸びるたびにファイル名が変わると /switch や /list が扱いにくくなります。セッションという単位を安定させるため、プレフィックスハッシュではなくタイトル + 作成時刻を使っています。
ただしファイル形式の中身は第4回で見た KVC / DSV4 と同じ流れです。エージェント専用のタイトルトレーラが追加されるだけです。
5. システムプロンプトは DSML ネイティブ
ds4_agent.c には、エージェント用のツールプロンプトが C の文字列として埋め込まれています。
冒頭は次のような方針です。
- ローカルワークスペースで動くコーディングエージェント
- ファイル/システム作業にはツールを使う
- 大きなファイル内容や大きなコードブロックを回答として出さず、ツールで作成・編集する
- DSML のツール記述を厳密な構文で書く
- ツール呼び出しは
<think></think>の中に出してはいけない
ツールプロンプトは DeepSeek V4 の DSML トークンを前提にトークナイズされます。
/* The built-in tool prompt is trusted DS4 control text. Tokenize it like a
* rendered chat prompt so the literal DSML markers in the examples become
* the model's dedicated DSML token. Do not apply that tokenizer to user text.
*/
ここは重要です。ユーザーテキストに含まれる DSML 風の文字列を制御トークンとして扱ってはいけません。一方、信頼できるシステム/ツールプロンプト内の DSML マーカーは、モデルにネイティブなツール構文として教える必要があります。
6. ネイティブツールのスキーマ
エージェントプロンプトには、利用可能なツールスキーマが直接埋め込まれています。
代表的なツール:
| ツール | 役割 |
|---|---|
read |
テキストファイル / 行範囲を読む |
more |
前回の read 系出力の続きを読む |
write |
ファイル作成または全置換 |
edit |
old/new による正確な単一置換 |
search |
ファイル検索 |
list |
ディレクトリ一覧 |
bash |
シェルコマンド実行 |
bash_status |
長時間実行 bash ジョブの状態確認 |
bash_stop |
実行中の bash ジョブを停止 |
google_search |
可視ブラウザ経由の Web 検索 |
visit_page |
URL を可視ブラウザで開いて Markdown 化 |
ds4_agent.c にはそれぞれの実装関数があります。
static char *agent_tool_read(...);
static char *agent_tool_write(...);
static char *agent_tool_edit(...);
static char *agent_tool_search(...);
static char *agent_tool_google_search(...);
static char *agent_tool_visit_page(...);
サーバ編のように OpenAI のツールスキーマを DSML に変換しているのではなく、最初から DSML のツールスキーマとしてプロンプトに埋め込み、それをネイティブパーサが受けます。
7. 編集プロンプトはかなり実務的
エージェントプロンプトの編集指示は、実務的で興味深いです。
write は新規ファイルまたは意図的なファイル全置換に使う。通常の変更は edit を使う。edit の old は現在のファイルにちょうど一度だけ一致しなければ失敗する。
さらに大きな置換では、[upto] を使ったアンカー付き編集を推奨しています。
For large replacements, prefer anchored old text:
write the first lines, then [upto], then the final lines.
これはローカル LLM のデコード速度と文脈の圧力をよく理解した設計です。
巨大なファイル全体をモデルに再出力させると遅く、ミスも増えます。必要なアンカーを read / search で集め、old/new の狭い差分だけをツールに渡すほうが安定します。
DS4 エージェントは「モデルが賢ければ何でもできる」ではなく、ローカル推論の制約に合わせてワークフローを作っています。
8. DSML パーサは厳密
エージェント側にも DSML パーサがあります。
コメント
/* The model streams raw text tokens. This parser recognizes completed DSML
* tool stanzas and keeps a copy of the raw stanza for diagnostics. It is
* deliberately strict after the opening marker ...
*/
パーサの状態は次のように分かれています。
typedef enum {
AGENT_DSML_SEARCH,
AGENT_DSML_STRUCTURAL,
AGENT_DSML_PARAM_VALUE,
AGENT_DSML_DONE,
AGENT_DSML_ERROR,
} agent_dsml_state;
開始マーカーを見つけるまではストリーミング検出器がある程度面倒を見ますが、DSML ブロックとして開始した後は厳密にパースします。誤字の回復をパーサ本体に入れすぎないことで、ツール実行の誤爆を避けています。
ツール呼び出しが完成すると、agent_tool_call に名前と引数が入り、ネイティブのツールディスパッチに渡されます。
9. ストリームの可視化
エージェントは生のアシスタントテキストとツール呼び出しをターミナルに表示します。agent_tool_visualizer は、ツール名やパラメータの型に応じて表示を変えます。
例えば、
-
readはパスと行範囲をコンパクトに表示 -
bashのコマンドは目立つ色 -
editの old/new は diff 風に表示 -
write/editのコード本体はコードとして扱う
この部分は推論エンジンそのものではありませんが、ネイティブエージェント体験には効きます。ツール呼び出しが隠れた JSON として裏で発生するのではなく、モデルが何をしようとしているかをストリーミング中に見せます。
10. システムプロンプトのリマインダ
長いセッションでは、最初のシステム/ツールプロンプトが文脈の遠い位置に流れていきます。エージェントは一定トークン数ごとにシステムプロンプトのリマインダを再注入します。
#define AGENT_SYSTEM_PROMPT_REMINDER_TOKENS 50000
agent_worker_maybe_append_system_prompt_reminder() は、前回のリマインダから 50k トークン以上進むと、ツールプロンプトと追加のシステム指示を再度トランスクリプトに入れます。
これは長文脈モデルでも実用上重要です。1M の文脈があっても、エージェントのツール構文や編集ルールは定期的に近い位置へ戻したほうが安定します。
11. Web ツールは可視ブラウザ前提
エージェントプロンプトには google_search と visit_page もあります。実装コメントには、Web サブシステムは Chrome を立ち上げ、エージェント側は権限、ツールディスパッチ、visit_page の上限を扱うとあります。
初回の Web 呼び出しではユーザー権限を求める設計です。これはネイティブエージェントがローカルマシンの外へ出る境界なので、ファイルツールとは扱いが違います。
サーバ互換 API だけではこの種の UI/権限フローを入れるのが難しいですが、ネイティブエージェントならターミナル UI とワーカー状態の中に直接組み込めます。
12. ネイティブエージェントの利点と限界
README が挙げる利点を、実装目線で言い換えると以下です。
| 利点 | 実装上の理由 |
|---|---|
| 低レイテンシ | ソケット/API 境界がなく、ワーカーがセッションを直接持つ |
| ライブ進捗バー | prefill とセッション状態が同一プロセス内 |
| DSML 変換不要 | ツールプロンプトとパーサが DSML ネイティブ |
| KV 不一致が構造的に起きにくい | 現在の状態が常にワーカーセッションの真実 |
| セッション切り替えが速い | フル KV ペイロードを ~/.ds4/kvcache からロード |
一方で、README は ds4-agent を alpha 品質とし、prime time にはまだ作業が必要とも書いています。将来的には、ネイティブエージェントで得た形をもとに、ステートフルなセッションプロトコルを持つサーバ/クライアント分離へ進む可能性が示されています。
これは自然な進化です。OpenAI/Anthropic 互換 API は既存クライアント接続に強い。一方、ネイティブエージェントは DS4 に最適化した UX と状態モデルを試せる。この実験結果をステートフルなプロトコルに戻せれば、両者の良い部分を合わせられます。
13. この記事の要点
ds4-agent は、DwarfStar の「推論エンジン + 専用 GGUF + エージェント検証」という思想の、C に相当する部分です。
- エンジンと同じプロセス内でライブセッションを操作する
- セッション保存はオンディスク KV キャッシュそのもの
- ツール呼び出しは DSML ネイティブで、JSON 互換層を通らない
- ツールプロンプトはローカルコーディングのワークフローに強く寄せている
-
/save,/list,/switch,/stripで長時間のローカルセッションを扱う - システムプロンプトのリマインダやアンカー付き編集など、ローカル推論の制約に合わせた工夫がある
次回は最終回として、DwarfStar の周辺実験機構をまとめます。directional steering、MTP speculative decoding、ds4-eval、ds4-bench、自前データ構造など、連載本編に入りきらなかった技術的な見どころを拾います。
本記事は クイックイタレート株式会社 のローカル LLM 研究の一環として、
公開リポジトリ antirez/ds4 のコードを読み解いたものです。行番号・定数・ベンチ値は閲覧コミット ba00a8a(2026-05-30)/README 取得日 2026-06-01 時点のものです。ds4-agent は alpha、エンジン本体は beta 品質で活発に変化するため、引用箇所は各自で最新の README / ソースに当たって再確認してください。
クイックイタレート株式会社
IoT / 電力監視 / AI / 衛星・無線通信 / システムインテグレーション/
ローカル LLM・エージェント基盤に関するお問い合わせはお気軽にどうぞ。