Hermes Agent で context を使い切ったときの対処 — 中途半端は捨て、クリーンなセッションで作り直す
Hermes Agent に Issue を渡し、PR を作成してもらう loop を回している。実装が佳境に入ったところで、こんなメッセージが返ってきて手が止まる。
Context length exceeded (301,411 tokens). Cannot compress further./compress を叩いても効かない。何度やっても同じ行が返るだけで、会話は 1 トークンも縮まない。仕方なく状態を保存して新しいセッションを開き直すと、今度は積み上げた文脈がまるごと消える。Hermes Agent で長い作業をさせていると、誰もが一度はぶつかる壁です。
この記事は、Nous Research の Hermes Agent が context を使い切り、圧縮まで効かなくなった状態から、書きかけの PR を仕上げて Issue を close できるところまで継ぎ直すための、トラブルシューティング Tips です。要点は一つだけで、頼るべきは会話の中の記憶ではなく、context の外に残るコミット済みの進捗と Issue だ、ということです。Hermes Agent のローカルセットアップは 別記事 にまとめています。
結論を先に
いま困っているなら、これだけで抜けられます。
- まず
/compressを試す。context に余裕が戻れば、そのまま作業を続行する Cannot compress furtherで効かないなら、粘らず/newする。中途半端な変更はgit restore .(未追跡ファイルも消すならgit clean -fd)で捨て、クリーンなセッションに切り替える- 新しいセッションで同じ Issue をもう一度渡し、続きを実装してもらう。コミット済みの差分や Issue の内容は Hermes Agent がよしなに読み取ってくれる。PR を仕上げれば、
Closes #123で紐づけてある限りマージ時に Issue は自動で close される
コツは、溢れた会話を無理に生かそうとしないことです。頼るべき状態(コミット済みの進捗と Issue)はもともと context の外にあるので、会話は捨ててクリーンに作り直したほうが速い。以降は、なぜこれで十分なのかを掘り下げます。急いでいなければ、そのまま読み進めてください。
なぜ Cannot compress further が起きるのか
まず、Cannot compress further がどういう状態かを押さえておきます。これは context を使い切ったという単純な話ではなく、圧縮機構が自分で自分を止めた状態です。
Hermes Agent は二層の圧縮を持っています。一つは Agent ContextCompressor で、エージェントのループの内側で動き、API が返す正確なトークン数を見て、既定では context の 50%(threshold: 0.50)に達したところで発火します。もう一つは Gateway Session Hygiene で、こちらは Telegram・Slack などの常駐セッションが一晩で膨らんで API エラーになるのを防ぐセーフティネットとして、85% で発火します。普段の会話で効いているのは前者です。
圧縮そのものは 4 段階で進みます。長い tool の出力(200 文字超)をスタブに置き換え、保護する先頭(system prompt と最初のやり取り)と末尾(直近 protect_last_n: 20 件)の境界を決め、真ん中を補助 LLM が構造化サマリに畳み込み、最後に先頭・サマリ・末尾を組み直す。サマリには Goal・Constraints・Progress(Done / In Progress / Blocked)・Key Decisions・Relevant Files・Next Steps・Critical Context が入ります。要するに、圧縮とは「会話を、続きに必要な引き継ぎメモへ畳む」処理です。
問題は、畳んでも縮まなくなったときに起きます。Hermes Agent には、圧縮が 2 回連続で 10% 未満の削減しか生まなかった場合、should_compress() が /new でセッションをリセットするまで永続的に False を返す、というアンチスラッシングロックがあります。タイムアウトも減衰もありません。会話の中身がすでに「これ以上は要点しか残っていない」ところまで凝縮されていると、圧縮を走らせても実質減らないので、このロックが噛みます。/compress を叩いても動かないのは、故障ではなくこの設計上の帰結です。長い実装セッションで context を目一杯まで使うと、わりと自然にここへ着地します。
/save しても “Context length exceeded” は解けない
ここで、多くの人がやりがちな次の一手が /save です。Hermes Agent には /save があり、「現在の会話を保存する」コマンドとして実在します。加えて Hermes Agent は、そもそもすべての会話を ~/.hermes/state.db(SQLite、FTS5 全文検索付き)に逐次自動保存しています。セッション ID・モデル構成・system prompt のスナップショット・トークン数付きの全メッセージ履歴が残り続けるので、あとから会話を呼び戻す手段は手厚く用意されています。
| コマンド | 効果 |
|---|---|
/save | 現在の会話を明示的に保存する |
/compress [here N] | 会話を手動で圧縮する(既定では直近 2 往復を残す) |
/model <name> | 会話の途中でモデルを切り替える |
/usage | 現在のセッションのトークン消費を表示する |
/new(別名 /reset) | まっさらな新しいセッションを始める |
/resume [name] / hermes --continue / -c | 保存済みのセッションを再開する |
問題は、保存できても「続けられる」わけではないことです。/save が保存するのも、自動保存が残すのも、いま溢れさせた巨大な会話履歴そのものです。それを /resume や hermes --continue で読み戻せば、あなたはまた context を使い切った状態に逆戻りするだけで、次の一手を打つ余地はありません。「会話を保存する」ことと、「続きに必要な状態を context の外へ絞り出しておく」ことは、別の作業です。本題は後者にあります。
/new は文脈を引き継がない
では /new で仕切り直せばよいのか。ここに、見落としやすい落とし穴があります。/new は本当にまっさらなセッションを始めるコマンドで、直前の会話の memory も context も引き継ぎません。/new payments-refactor と打った瞬間、それまでのやり取りには一切アクセスできない別スレッドが立ち上がります。
これは裏を返すと、/new の直後のエージェントが知っていることは、context の外に永続化されているものだけ、ということです。Hermes Agent の場合、セッションをまたいで生き残るのは次のものです。
- memory: 利用者の事実や好みを覚えていて、関連性に応じて自動で呼び戻される
- skills: 手順やステップを覚えていて、似たタスクで再利用される
- 過去セッション:
session_searchツールで全文検索でき、エージェントが自力で過去の会話を引ける - そして何より、リポジトリそのもの: ブランチ・コミット・PR・Issue・作業ツリーのファイル
ここが本質です。書きかけの PR というタスクにおいて、いちばん確実に context の外に置かれている状態は、エージェントの記憶ではなく Git のブランチと PR です。実装の途中経過はコミットに刻まれ、何をやろうとしているかは Issue に書かれている。これらは token を 1 つも消費せずに、/new の向こう側へ渡っていきます。だから継ぎ直しの設計とは、「続きに必要な状態を、いかに会話の中ではなく context の外側へ逃がしておくか」という設計に等しくなります。
継ぎ直しの型 — PR を仕上げて Issue を close する
以上を踏まえると、Cannot compress further から復帰する動きは、意外なほど身も蓋もない形に落ちます。無理に今の会話を延命させるより、思い切って作り直すほうが速い、という割り切りです。
flowchart TD
A["Context length exceeded"] --> B{"/compress は効くか"}
B -- "効く" --> H["context に余裕が戻り<br/>そのまま作業を続行"]
B -- "効かない(ロック)" --> C["Cannot compress further"]
C --> C2["中途半端な変更は破棄<br/>git restore ."]
C2 --> D["/new でクリーンなセッション"]
D --> E["Issue とコミット済みの差分を読み直す"]
E --> F["残りをクリーンに実装してコミット"]
F --> G["PR を仕上げる<br/>マージで Issue は close"]
具体的な動きは、拍子抜けするほどシンプルです。作業ツリーに残った中途半端な変更は、無理に引き継ごうとせず捨てます。
context を使い切ったエージェントの手元は、書きかけ・消しかけの編集が入り混じった不安定な状態になっていることがほとんどです。それを WIP コミットで丸ごと抱え、引き継ぎメモまで書かせて次のセッションへ渡す、というのは手間のわりに引き継ぎの質が上がりません。中途半端な差分は git restore .(未追跡ファイルも含めて消すなら git clean -fd)でいったん捨て、クリーンな作業ツリーに戻したうえで、まっさらなセッションから実装をやり直したほうが、速いし結果もきれいです。
頼るべき状態は、もともと context の外に揃っています。すでにコミット済みの進捗(ブランチと PR)と、ゴールを書いた Issue です。これらは会話が消えても残るので、/new で開いた新しいエージェントに同じ Issue を渡せば、コミット済みの差分や Issue の内容はよしなに読み取り、「どこまで進んでいて、残りは何か」をクリーンな状態から把握してくれます。あとは残りを実装させ、コミットして PR を仕上げれば、Closes #123 のように PR と Issue を紐づけてある限り、PR がマージされた時点で Issue は自動的に close され、当初のゴールにたどり着きます。捨てた中途半端な差分も、クリーンな頭で書き直せば、たいていむしろ素直なコードになります。
なお、Cannot compress further のロックが噛む前で、まだ会話の記憶を捨てたくないなら、/new の代わりに /model でより context の大きいモデルへ切り替える手もあります。会話履歴は保たれたまま器だけが広がるので、そのまま走り切れることも多い。ロックはあくまで「同じ器の中でこれ以上畳めない」という宣言であって、器を替える選択肢を塞ぐものではありません。
より根本的な対処 — そもそも context を溢れさせない
継ぎ直しの型を持っておくのは大事ですが、毎回これをやるのは面倒です。根本的には、一つのセッションで context を使い切らない設計に寄せるほうが効きます。
- タスクを小さく切る: 1 つの Issue を 1 セッションで丸ごと片付けようとせず、下調べ・実装・テストのように区切って、区切りごとにクリーンにコミットしておく。こまめにコミットしてあれば、途中で context が溢れても、捨てて作り直すのは直近の一区切りだけで済みます
- サブエージェントに逃がす: Hermes Agent は独立した会話・実行環境を持つ subagent にタスクを委譲できます。調査のようにトークンを大量に食う工程を隔離された context で回させれば、親セッションには結果だけが返り、本体の context は温存されます
- tool の出力を抑える: 圧縮の第 1 段階が長い tool 出力の刈り込みだったことからも分かるとおり、巨大なログやファイル全文の垂れ流しが context を最も速く食います。必要な範囲だけ読ませる癖をつけるだけで寿命が伸びます
- 器を最初から大きく取る: 長丁場が読めているなら、
--modelや config のcontext_lengthで最初から context の大きいモデルを選んでおきます
どれも根っこは同じで、context を有限で貴重な資源として扱う、という一点に尽きます。エージェントに長い仕事をさせるほど、価値のある状態を会話の中に溜め込まず、コミット・PR・memory・ファイルといった context の外の永続層へこまめに書き出しておくことが効いてきます。会話は消えても、外に逃がした状態は残る。これは Hermes Agent に限らず、context window を持つあらゆるコーディングエージェントに共通する構えです。
まとめ
Context length exceeded. Cannot compress further. は、エージェントが会話をこれ以上要点に畳めなくなったという設計上の到達点です。そこからの継ぎ直しを、次のように整理しました。
/compressが効かないのはアンチスラッシングロックの帰結であり、故障ではない。/saveや自動保存で会話は残せるが、保存した会話を読み戻せば context を使い切った状態に戻るだけで、保存それ自体は続きを解決しない/newは memory も context も引き継がない。頼れるのは、もともと context の外にあるコミット済みの進捗(ブランチと PR)とゴールを書いた Issue で、中途半端な作業ツリーは無理に引き継がず捨てる- 新しいクリーンなセッションで Issue とコミット済みの差分を読み直し、残りをやり直す形で実装して PR を仕上げる。PR と Issue を紐づけておけば、マージ時に Issue は自動で close される
- そもそもの対策は、タスクを小さく切る・サブエージェントに逃がす・tool 出力を抑える・器を大きく取る、で context を溢れさせないこと
エージェントに任せる仕事が長く重くなるほど、「会話は揮発する。永続する状態は外に置く」という原則が効いてきます。溢れたセッションは、失敗ではなく、状態を外へ逃がす合図として扱えばよいのです。
以上、AI エージェントに長い実装を任せて何度も context の壁にぶつかってきた立場から、Cannot compress further との付き合い方を現場からお送りしました。