mcpField
I
input-token-overheads

input-token-overheads

github.com/moonlight-lupinエージェントワークフロー113121 回インストール1 日前に更新
リポジトリ

input-token-overheads について

input-token-overheads は、Hermes Agent の入力トークンを監査・最適化するスキルです。コンテキストのオーバーヘッドや入力コストを調べる運用担当者向けに、ターンごとの負荷とセッション全体の使用量を測定し、改善後の再計測まで案内します。

主な機能

  1. 01ターンごとのプロンプト要素を測定
  2. 02セッション、cron、ツール通信を集計
  3. 03推定値とプロバイダー実測値を比較
  4. 04コスト順に主要な消費元を特定
  5. 05注入ファイルの切り詰めや参照切れを確認
  6. 06変更前後の差を再測定

活用シーン

  1. 01コンテキスト肥大化や入力コスト増の調査
  2. 02スキルやツール追加後の負荷確認
  3. 03cron ジョブのトークン使用量の分析
  4. 04最適化後の使用量変化の検証

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/moonlight-lupin/agent-skills --skill input-token-overheads

インストール後、Claude Code で/input-token-overheadsを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

evals/
routing-fixtures.json
scripts/
audit_overheads.py
audit.py
tests/
test_audit_overheads.py

詳細

翻訳後に原文が更新されています。最新の内容は原文をご確認ください。

入力トークンのオーバーヘッド

Hermes Agent インスタンスで、ターンごとの入力トークンコストが発生するすべての要因を監査します。それぞれを測定し、コスト順に並べ、最も大きな要因に対処します。

統合監査は scripts/audit_overheads.py で実行します(手順のステップ 1、1 つのコマンドで実行):構造化出力には --json、共有可能なグラフには --chart <png> を指定します。さらに、常時注入されるすべてのファイルについて、コンテキストドクター形式のチェックも行います。TRUNCATED(注入上限を超過し、毎ターン、通知なく切り詰められる)および MISSING のステータスが表示され、注意が必要なファイルがある場合は終了コード 1 になります。jzOcb/context-doctor から移植(MIT ライセンス、OpenClaw 専用。概念のみを採用し、スクリプトはネイティブ実装です)。

使用するタイミング

  • ユーザーが「トークンのオーバーヘッド」「コンテキストが大きすぎる」「入力コストが高いのはなぜ」と尋ねた場合
  • コンテキストの希薄化により、モデルの出力品質が低下した場合
  • コストを最適化する場合 — ターンごとの入力トークンを減らすと、API の利用料金が下がります
  • スキル、プラグイン、ツールを追加した後 — オーバーヘッドの差分を確認します

オーバーヘッドの内訳

各ターンで、Hermes はユーザーのメッセージより前に次のブロックをシステムプロンプトに注入します。

ブロック読み込みタイミングコストモデル
スキルの説明毎ターン(skill-retrieval の上位 K 件)説明 1 件あたり約 200 文字、ターンあたり K 件
メモリ(個人メモ)毎ターン固定。使用に伴い増加
ユーザープロファイル毎ターン固定。好みの蓄積に伴い増加
メモリプロバイダーのコンテキスト毎ターン(メモリプラグインが有効な場合)動的。デフォルトでは 5 件のメモリを呼び出します
ツールスキーマ(直接)毎ターン有効なツールごとの完全な JSON スキーマ
遅延読み込みツールカタログ毎ターン(設定されている場合)名前と説明のみ
必須スキル毎ターン(設定されている場合)SKILL.md の本文全体
プラットフォームの書式ルール毎ターン固定。プラットフォーム固有
動作ルール毎ターン固定のシステムプロンプトテキスト
スキル本文全体オンデマンド(skill_view)スキルが読み込まれた場合のみ
圧縮サマリーしきい値到達後古いメッセージをサマリーに置き換えます

オンデマンド(ターンごとではありません): skill_view による完全な SKILL.md、tool_describe による遅延読み込みのツールスキーマ、skill_view(file_path=...) による参照ファイル。

健全性比率

健全性の指標はオーバーヘッド比率です。オーバーヘッドのトークン数をモデルのコンテキストウィンドウで割った値です。絶対数はコストに関係し、比率は品質に関係します。

比率評価備考
< 5%優秀ウィンドウの大部分を会話に使用できます
5-15%健全ツール、スキル、メモリを備えた有能なエージェントでは一般的です
15-25%許容範囲上限に近づいています。削減を検討してください。
> 25%不健全会話に使える容量を圧迫します。コストと品質のリスクがあります。

比率が重要な理由: 3つの研究により、コンテンツの品質とは関係なく、入力の長さがモデルの性能を低下させることが確認されています。

  1. Lost in the Middle(Liu et al.、TACL 2023) — モデルの想起率はU字型の曲線を描き、コンテキストの先頭と末尾で最も高く、中間では大幅に低下します。オーバーヘッドは各ターンの先頭に置かれますが、その分、会話履歴が性能低下ゾーンに押し込まれます。arxiv.org/abs/2307.03172

  2. Same Task, More Tokens(Levy et al.、ACL 2024) — 推論性能は、モデルが公称する最大値をはるかに下回る入力長でも低下します。余分なトークンが注意をそらす内容を含まないパディングであっても、性能の低下は発生します。モデルの技術上のコンテキストウィンドウは、実効コンテキストウィンドウではありません。aclanthology.org/2024.acl-long.818

  3. Context Length Alone Hurts(Du et al.、EMNLP 2025) — 検索が完璧な場合、無関係なトークンを空白に置き換えた場合、または関連するトークン以外をすべてマスクした場合でも、入力の長さが増すにつれて性能は14~85%低下します。入力の長さそのものが制約になります。aclanthology.org/2025.findings-emnlp.1264

コストの累積: オーバーヘッドは毎ターン発生します。100ターンでオーバーヘッドが10kトークンなら、オーバーヘッドだけで入力トークンを1M消費します。オーバーヘッドを2kトークン削減すれば、100ターンのセッションごとに200kトークンを節約できます。

研究に基づく緩和策:

研究結果出典対策
モデルはコンテキストの先頭と末尾を最もよく想起し、中間では性能が低下するLiu et al. 2023オーバーヘッドは先頭に配置します(Hermes はすでにこのように動作します)。重要な会話履歴を中間に押し込まないでください。履歴が過度に圧縮されている場合は、圧縮しきい値を下げます
推論性能は、公称のコンテキストウィンドウの最大値を大きく下回る時点から低下するLevy et al. 2024実効コンテキストウィンドウは、公称最大値の50~70%として扱います。実効ウィンドウではなく、公称ウィンドウの10%未満をオーバーヘッド比率の目標にします
検索が完璧で注意をそらすものがなくても、入力の長さそのものが悪影響を及ぼすDu et al. 2025オーバーヘッドを積極的に削減します。オーバーヘッドを1kトークン削減するごとに、コストだけでなく推論品質も向上します。この研究で示された緩和策は、問題を解く前に主要な根拠を列挙するようモデルに指示することです。これは、関連するコンテキストを要約する Hermes の圧縮に相当します
ツールカタログが8kから120kトークンに増えると、ツール呼び出しの性能が7~85%低下するLongFuncEval (arxiv 2505.10570)有効にするツールセットの数を抑えます。常時有効なスキーマより、必要に応じて読み込む遅延読み込みツールを優先します。使用しないツールセットは無効にします

手順

1. 各オーバーヘッドの発生源を測定する

監査スクリプトを実行して、実際の数値を取得します。

python3 -c "
import yaml, pathlib, glob, os, re

# --- Skill descriptions (skill-retrieval index) ---
files = glob.glob(os.path.expanduser('~/.hermes/skills/**/SKILL.md'), recursive=True)
total_desc = 0; count = 0; by_cat = {}
for f in files:
    try:
        text = pathlib.Path(f).read_text()
        m = re.match(r'^---\n(.*?)\n---\n', text, re.DOTALL)
        if not m: continue
        fm = yaml.safe_load(m.group(1))
        if not fm: continue
        desc = fm.get('description', '')
        if not desc: continue
        cat = f.split('/skills/')[1].split('/')[0]
        by_cat.setdefault(cat, [0,0]); by_cat[cat][0] += len(desc); by_cat[cat][1] += 1
        total_desc += len(desc); count += 1
    except Exception: pass
avg = total_desc // max(count, 1)
K = int(os.environ.get('SKILL_RETRIEVAL_TOP_K', '6'))
print(f'Skills: {count} total, {total_desc} chars in descriptions')
print(f'  Top-K per turn: ~{K*avg} chars (~{K*avg//4} tokens) at K={K}')
print(f'  By category (top 5):')
for cat, (sz, cnt) in sorted(by_cat.items(), key=lambda x: -x[1][0])[:5]:
    print(f'    {sz:>6} chars ({cnt:>2} skills) {cat}')

# --- Disabled skills (savings) ---
config_path = os.path.expanduser('~/.hermes/config.yaml')
if not os.path.exists(config_path):
    print('  Config: ~/.hermes/config.yaml not found — skipping disabled/compression stats')
else:
    try:
        with open(config_path) as fh:
            cfg = yaml.safe_load(fh)
        if cfg is None:
            cfg = {}
        disabled = cfg.get('skills',{}).get('disabled',[]) or []
        print(f'  Disabled: {len(disabled)} skills (saves ~{len(disabled)*avg} chars)')
        comp = cfg.get('compression',{}) or {}
        print(f'  Compression: threshold={comp.get(\"threshold\")}, target_ratio={comp.get(\"target_ratio\")}, protect_last={comp.get(\"protect_last_n\")}')
    except Exception as e:
        print(f'  Config parse error: {e}')
"

メモリプロバイダーの数を確認する場合(Mnemosyne がインストールされている場合):

python3 -c "
import sqlite3, os, glob
for db in glob.glob(os.path.expanduser('~/.hermes/**/mnemosyne.db'), recursive=True):
    conn = sqlite3.connect(db); c = conn.cursor()
    for t in ['working_memory','episodic_memory','canonical_facts','memoria_facts']:
        try:
            c.execute(f'SELECT COUNT(*) FROM {t}'); print(f'  {t}: {c.fetchone()[0]} rows')
        except: pass
    conn.close()
"

完了: スキルの説明、無効数、圧縮設定を測定しました。ツールスキーマ(#1)と動作ルール(#2)は固定コストです。モデルのシステムプロンプトから推定するか、セッション中に /tokens を確認して合計を調べてください。スクリプトで測定するのは変動する発生源(#6、#7)です。固定の発生源(#1~#5)はセッション中に確認する必要があります。

2. コスト順に並べる

すべてのソースをターンあたりのトークン数で並べ替えます。一般的な順位は次のとおりです。

  1. ツールスキーマ — 固定コストが最も大きくなります。有効なツールセットの数に応じて増加します。
  2. 行動ルール + システムプロンプト — 固定テキストです。
  3. 必須スキル — 必須スキルごとに、SKILL.md の本文全体が含まれます。
  4. メモリ + ユーザープロフィール — 静的ブロックです。
  5. 遅延読み込みツールカタログ — 遅延読み込み対象の各ツールの名前 + 説明です。
  6. スキルの説明 — スキル検索による上位 K 件の挿入です。
  7. メモリプロバイダーのコンテキスト — 動的な想起です。デフォルトは 5 件です。

完了条件: ソースを順位付けできていること。上位 3 つが最適化対象です。

3. コストの大きい項目に対処する

ツールスキーマ(固定コストが最大):

  • 有効なツールセットを監査します。ダッシュボードで hermes tools を実行してください
  • 使用していないツールセットを無効にします(無効にするごとに、各ターンからツールスキーマが 1~3 個削除されます)
  • config.yaml の platform_toolsets.cli を使って、プロファイルごとのツールセットへのアクセスを制御します
  • 常時有効なツールよりも、遅延読み込みツール(必要に応じて読み込む)を優先します

メモリブロック:

  • 圧縮を調整するには、skill_view(name='hermes-compression-tuning') を読み込みます
  • 古くなった、または重複したメモリエントリを整理します
  • メモリブロックを予算内に収めます。上限に達した場合は、新しいエントリを追加する前に、古くなったエントリをまとめて削除します

スキルの説明:

  • config.yaml の skills.disabled で使用していないスキルを無効にします。スキルを無効にするごとに、検索インデックスから約 200 文字分が削減されます
  • 説明は簡潔にします。スキル検索プラグインは説明を 200 文字で切り詰めます。200 文字を超える説明は、ルーティングの精度を高めずにトークンを浪費します

メモリプロバイダー(インストール済みの場合):

  • 統合作業を実行して、作業メモリをエピソード記憶に移し、作業セットを減らします
  • 古くなった事実を無効化します
  • コンテキストに余裕がない場合は、想起の limit パラメーターを小さくします

完了条件: 上位 3 つの各ソースに対して、少なくとも 1 つの最適化を適用していること。

4. 差分を確認する

手順 1 の監査スクリプトを再実行します。最適化前と最適化後のトークン推定値を比較します。

完了条件: 最適化前後の差分を報告していること。大幅な削減がない場合、残るオーバーヘッドは構造上のものであり(システムプロンプト + 行動ルール)、config を変更しない限り削減できません。

注意点

問題原因対処方法
監査スクリプトがスキル数として 0 を返すスキルのパスが間違っているか、~/.hermes/skills/ が空ですls ~/.hermes/skills/ でディレクトリが存在し、カテゴリ別のサブディレクトリが含まれていることを確認します。スキルがシンボリックリンクされている場合や、カスタムパスにある場合は、glob を調整します
ツールセットを無効にするとワークフローが壊れるそのツールセットに依存するスキルがあります無効にする前に、スキルの frontmatter にある requires_toolsets を確認します
メモリを整理すると必要な事実が削除される最終使用時刻を確認せずに積極的に削除しています削除する前に recall_count と last_recalled を確認します
圧縮が早すぎるthreshold の設定が低すぎますコンテキストウィンドウが長い場合は値を上げます。ただし、品質の低下に注意してください
圧縮が遅すぎるthreshold の設定が高すぎます値を下げます。ただし、圧縮サマリー自体にもトークンが必要です
必須スキルのオーバーヘッドを避けられないように思える行動ルールで設定されていますコストを許容するか、config で必須読み込みの要件を削除します

検証

  • 監査スクリプトを再実行し、トークン推定値が減少したことを確認します
  • hermes tools — 必要なツールセットのみが有効であることを確認します
  • メモリブロック — 予算内であることを確認します
  • メモリプロバイダーの件数 — 統合後に作業セットが減少したことを確認します
  • 次のセッションを監視します。コンテキストを減らしても品質が低下しないことを確認します

コメント