第6課:世界を感知する:スキル、検索、コンテキスト
一言でいうと:エージェントは「手を動かす」だけでは不十分で、「感知」もできなければなりません――再利用可能なスキルパック(skill)で新しい能力を学び、Web検索とフェッチで情報を調べ、LSPでコードのセマンティクスを読み取り、ワークスペースで自分がどのプロジェクトにいるかを記憶し、コンテキスト圧縮で超長いセッションでも「記憶喪失」にならないようにする。そしてDSHでは、これらの感覚はすべて交換可能なプラグインのシーム(seam)です。
1. まず物語を:手を動かすだけのエージェントに足りないもの
新しい同僚を雇ったと想像してください――起動したばかりのDSHエージェントです。それは生まれつき「手足」を持っています。ファイルの読み書き、コマンドの実行、コードの編集ができます。しかし初出勤の日、それは世界について何も知らないことに気づきます。
- 「リポジトリの規約に従ってPRを提出して」と頼んでも、規約がどこに書かれているのか、PRのプロセスがどうなっているのか分かりません。
- 「あるフレームワークの最新の使い方を調べて」と頼んでも、ネットワークがないためコードベースを眺めて固まるだけです。
- 「この関数のすべての呼び出し箇所を見つけて」と頼んでも、文字列をgrepするだけで、ファイルをまたいだ参照を取りこぼします。
- 会話が3時間目に入ると、冒頭で言った「ここは本番環境だから変更は慎重に」ということさえ忘れています。
手足だけで感覚のないエージェントは、目隠しをしたインターンのようなものです。力は十分でも、方向感覚がまったくありません。DSHは5種類の「感覚」でこの問題を解決します。
| 感覚 | 解決する問題 | 対応する能力 |
|---|---|---|
| スキル(skill) | 新しい能力を学ぶ | 再利用可能な命令パック。使うときだけ展開 |
| 検索(web) | 情報を調べる | Web検索とページフェッチ |
| コードセマンティクス(lsp) | コードを理解する | 定義への移動、参照の検索 |
| ワークスペース(workspace) | 自分がどこにいるかを知る | 永続ワークスペースディレクトリ |
| コンテキスト(context) | 長いセッションで記憶喪失にならない | コンテキスト拡張と圧縮 |
感官接缝:技能渐进披露、Web 搜索、LSP 语义、工作区与上下文压缩
上の図はDSHの「感覚マップ」です。中央のエージェント(脳+身体)が5種類の感覚に囲まれています。破線に注目してください――それは実線の接続ではなく「シーム」です。どの感覚も個別に引き抜いて新しいものに交換できます。まず最も重要なスキルから説明しましょう。
2. スキル(skill):再利用可能な「能力パック」、使うときだけ展開
2.1 skillとは何か?
skill(スキル)は再利用可能な能力パックです。エージェント向けに書かれた「操作マニュアル」で、特定の種類のタスクをどう完了するかを教えます――たとえば「リポジトリの規約に従ってPRを提出する方法」「monorepoを整理する方法」「あるフレームワークのテストを書く方法」などです。skill能力ファミリーに対するDSH公式の定義は次のとおりです。
「このファミリーは再利用可能なagent(エージェント)命令を発見し、プロバイダーに依存しないカタログとloaderを通じてモデルに公開する。」 —— packages/skill/README.zh.md
平易に言い換えると、skillファミリーは再利用可能な命令を「見つける」役割を担い、それらを出所に依存しない方法でモデルに渡します。skillはローカルファイル、組み込みプラグインデータ、さらにはリモートサーバーから来ることもあります。レジストリ(ctx.skills)は発見・検索・読み込みだけを担当し、スキルがどこに保存されているかは気にしません。
2.2 段階的開示:使うときだけ展開
ここで問題が生じます。システムには何百ものskillがインストールされているかもしれません。すべてのskillの完全な本文をシステムプロンプトに詰め込んだら、そのカタログだけでコンテキストウィンドウがあふれてしまいます。
DSHの答えは**段階的開示(progressive disclosure)**です――これは私たちの発明ではありません。アーキテクチャドキュメントの能力一覧では、ctx.skillsの公式ラベルが「skill(スキル)プロバイダーレジストリと段階的開示」となっています。
「定義は引き続き段階的ロードを採用する。
get()は呼び出しのたびに勝者プロバイダーに本文を要求し、このレジストリに本文をキャッシュしない。」 —— packages/skill/skill/README.zh.md
この仕組みは2つのステップで動きます。
- まずカタログを渡す:モデルは最初、各skillの「要約」――名前と一文の説明――だけを見ます。1行で済みます。分厚いマニュアルが本棚に置かれ、背表紙には書名しかないようなものです。
- 使うときだけ展開:モデルが「このタスクにはあるskillが必要だ」と判断して初めて、
skillツールで完全な本文を読み込みます。本文は<skill_content>ブロックの形でツール結果としてコンテキストに入り、使い終わったら消えます。
なぜトークンを節約できるのか? 1回のタスクで必要なskillはたいてい1、2個だからです。段階的開示は「何百冊ものマニュアル」を「数百行のカタログ+必要時に展開される1、2編の本文」に格下げし、残りは一字も無駄にしません。
🎁 たとえるなら:スマホのアプリストアはアプリ名と一文の紹介だけを表示し、「インストール」をタップして初めて完全なアプリをダウンロードします。ストア内のすべてのアプリを強制的にプリインストールしたら、スマホはとっくにいっぱいです。
3. 感知のシーム:検索、コードセマンティクス、ワークスペース
第1章「DSH入門」で「能力とはシーム(seam)」と説明しました。交換可能な能力はService Definition(どんな形か)、Service Provider(誰がやるか)、Consumer(誰が使うか)の3部から成ります。感覚も例外ではありません――以下の3つの感覚はすべてシームです。モデルが見る語彙は固定で、働き手は自由に交換できます。
3.1 Web検索とフェッチ:エージェントに「目」を与える
エージェントが情報を調べたいときに頼るのがweb能力ファミリーです。
「このファミリーはプロバイダーに依存しないweb検索・フェッチ操作と、それらを消費するモデル向けツールを提供する。」 —— packages/web/README.zh.md
- 検索:Exa、Perplexity、あるいはDeepSeekネイティブ検索に接続できます――複数のプロバイダーから自由に選べます。
- フェッチ:ローカルの
web-fetch-httpが公開HTTPおよびHTTPSリソースをフェッチし、ページ本文を持ち帰ります。
モデルが知っているツールは2つだけです。web_search(検索)とweb_fetch(URLのフェッチ)です。今日はExa、明日はPerplexityに変えたい?設定を変えるだけで、モデル側の約束事は一字も変わりません。検索とフェッチはあえて1つのシーム(ctx.web)を共有しています。「このharnessがどうwebにアクセスするか」はもともと同じ設定問題だからです。
3.2 LSP:エージェントに「顕微鏡」を与える
grepはテキストマッチングですが、LSPはコードセマンティクスです。エージェントが文字列を「マッチ」するのではなくコードを「理解」したいとき、lsp能力ファミリーを呼び出します。
「このseamは
goToDefinition、findReferences、goToImplementation、hoverというちょうど4つのセマンティック操作のみを公開し、汎用JSON-RPCの抜け道は提供しない。したがって、プロバイダーを交換してもモデルのナビゲーション要求方法は変わらない。」 —— packages/lsp/README.zh.md
4つの操作をIDEユーザーの言葉に訳すと、定義へ移動(F12)、参照の検索(右クリック→Find All References)、実装へ移動、ホバーでドキュメント表示です。2つの細部に注目してください。
- ちょうど4つ:ごちゃごちゃした汎用プロトコルの抜け道がなく、モデルが要求できるナビゲーション能力は閉じていて予測可能です。
- プロバイダーは自由に交換可能:下でどの言語サーバー(TypeScript、Python……)が動くかは
lsp-stdioが担当し、モデルは常に同じ4つの操作で道を尋ねます。
3.3 Workspace:エージェントに自分がどこにいるかを知らせる
「自分はどのプロジェクトにいるのか?このセッションは誰のものか?」こうした問いに答えるのがworkspaceファミリーです。
「このファミリーは永続workspaceを所有する。タイトルと順序付きセッションメンバーシップを持つユーザーディレクトリである。」 —— packages/workspace/README.zh.md
workspaceは永続のユーザーディレクトリです。タイトルを持ち、どのセッションがその下にぶら下がっているかを知っています。エージェントがセッションを開くと、自分がどのworkspaceで作業しているかが分かり、パスやプロジェクトコンテキストがこの線に沿って組織されます。複数のセッションが同じworkspaceに属すことができ、1つのプロジェクトの下にぶら下がる複数の作業台のようなものです。
3.4 まとめ:感覚はすべてソケット
| 感覚 | シーム | モデルが見る固定語彙 | 交換可能なプロバイダー |
|---|---|---|---|
| 検索 | ctx.web | web_search | Exa / Perplexity / DeepSeekネイティブ |
| フェッチ | ctx.web | web_fetch | ローカルfetch |
| コードセマンティクス | ctx.lsp | 4つのセマンティック操作 | 各種言語サーバー |
| ワークスペース | ctx.workspaceRegistry | workspaceエンティティ | ストレージバックエンド |
どの感覚を交換してもモデルには分かりません――これこそがシームの意味です。
4. コンテキスト管理:なぜ「いっぱい」になるのか、圧縮はどう要点を失わないのか
4.1 まず追加:コンテキスト拡張プラグイン
「負荷を減らす」前に、「感知」のもう半分であるコンテキスト拡張を見ましょう。ツールで調べるべきではなく、すべてのリクエストに直接追加されるべきコンテキストがあります――たとえば「現在時刻は何時か」「どのworkspaceで作業しているか」「別のセッションの要約」などです。DSHはcontextファミリーでこれを実現します。
「ツールを定義せずにモデル向けリクエストコンテキストを追加するプロダクトプラグイン。」 —— packages/context/README.zh.md
訳すと、ツールは定義されない――エージェントはわざわざ何かを呼び出す必要がなく、これらの情報は自動的にリクエストに現れます。代表的なメンバーは、agent-instructions(ワークスペース命令。デフォルトバンドルに同梱)、time-context(現在時刻と経過時間)、session-reference(他セッションの有界スナップショット)です。拡張はコンテキストに「追加」し、圧縮はコンテキストの「負荷を減らす」。両者の連携で、長いセッションを完全かつ過負荷なしに保ちます。
4.2 なぜコンテキストは「いっぱい」になるのか?
モデルのコンテキストウィンドウは有限です(たとえば数十万トークン)。エージェントのすべての思考、すべてのツール呼び出しとその戻り値が、ウィンドウに物を詰め込み続けます。長いセッションは必ず天井にぶつかり、「いっぱい」になり方は2通りあります。
- 圧力(pressure):会話がウィンドウの上限に近づいているが、まだ壁にはぶつかっていない――能動的に圧縮。
- オーバーフロー(context-overflow):リクエストがすでにウィンドウを超過し、モデルプロバイダーに拒否された(エラーコード
CONTEXT_WINDOW_EXCEEDED)――圧縮してから再試行。
4.3 圧縮:一段の要約でまるごとの履歴と交換する
圧縮(compaction)の公式定義は控えめです。
「履歴が大きすぎるかを判定し、より早い範囲を単一の表層ノードに要約するが、実装方法は規定しない。」 —— packages/compaction/compaction/README.zh.md
どうやって「要点を失わない」のでしょうか?秘訣は3層にあります。
- 剪定(prune):まず巨大なツール結果を小さくします――たとえばコマンドの出力が10万行なら、要点まで刈り込みます。
- 要約(summarize):次にモデルに、より早い一段の会話をひとつの段落に濃縮させ、「要約チェックポイント」で原文を置き換えます。
- 末尾を保持:最近の会話は一字も動かしません。
「バックエンドは1つの要約で、もともと保持されていた複数の履歴トークンと交換し、最近の末尾を変更しないまま保つ。」 —— packages/compaction/compaction/README.zh.md
最も重要なのは、元のイベントが削除されないことです。それらはセッションログに完全なまま残っており、モデルのメッセージに入らなくなるだけです。つまり圧縮が触るのは「モデルのワーキングメモリ」であり、「システムの完全な記録」には触れません。リプレイは依然として決定論的です。
🎁 たとえるなら:500ページの本を読んでいて、400ページで冒頭を思い出せないことに気づいたとします。本を捨てて読み直すのではなく、最初の300ページを1ページの読書ノートにまとめて挟み込み、続きを読みます。ノートは細部を失いますが主線は保ちます――本当に重要な原文は本棚(ログ)にまだあります。
4.4 オーバーフロー再試行:壁にぶつかったらどうするか
リクエストが本当に「コンテキストがいっぱい」で拒否されたとき、DSHは諦めもしなければ闇雲に再試行もせず、規範化された復旧フローをたどります。
「
dsh-compaction-basicはリクエスト派生前にagent/pre-stepで圧力を処理し、agent/request-errorは規範的なコンテキストオーバーフローのみに使われる。いずれかのトリガー条件が満たされると、システムはまずオプションのツール結果剪定を実行し、次に要約を選択する。」 —— docs/agent-lifecycle.zh.md
完全なフローは、オーバーフロー → 剪定 → 要約 → 再試行です。最後のステップの規律に注目してください。剪定または要約が実際に表層を前進させた(実際の圧縮が発生した)場合にのみ、システムはまったく新しい再試行ラウンドを開始します。圧縮が成立しなければ、無限ループで再試行するのではなく元のエラーを保持します。
また、圧縮自体もシーム(ctx.compactionシーム)です。自動圧力チェック、オーバーフロー復旧、手動の/compactコマンドはすべて同じサービスを共有し、バックエンド(compaction-basic)は丸ごと交換できます。ここまでで気づいたはずです――「記憶の管理」さえも、DSHは交換可能なプラグインにしているのです。
要点の振り返り
この課の情報量は少なくありませんが、次の5文だけ覚えておけば十分です。
- エージェントは手を動かすだけでは不十分――ツールに加えて、5種類の感覚が必要です。スキル、検索、コードセマンティクス、ワークスペース、コンテキスト。
- skillは能力パックで、段階的開示――レジストリはモデルにカタログの要約だけを見せ、モデルは「使うときだけ」完全な本文を展開します。これがトークン節約の鍵です。
- 感知はすべてシーム――Web検索/フェッチ、LSPの4つのセマンティック操作、workspaceパスは、モデル語彙が固定でプロバイダーは自由に交換できます。
- コンテキストはいっぱいになり、圧縮は要点を失わない――圧力では能動的に圧縮し、オーバーフローでは剪定→要約→再試行。要約が置き換えるのは「モデルのワーキングメモリ」で、元のログはそのままです。
- 記憶の管理もプラグイン――コンテキスト拡張も圧縮バックエンドも交換可能なシームであり、「すべてはプラグイン」の哲学が感知層を貫いています。
🚀 次課(第6課)では「目標、計画、協調」を扱います――感覚のそろったエージェントが、どう「単独作戦」から「軍団協調」へと変わるのか。
セルフテスト · 世界を感知する
回答を終えたら「解答を送信」をクリックすると、正誤と解説を確認できます。
