Context Engineering: Turn 40でagentが鈍る理由
windowの2.6 %しか使っていないpromptで、事実を3行下げただけでretrievalは84 %から19 %へ。問題はwindowではありません。
このページの内容
同じモデルに、greedy decodingで同じpromptを288回送りました。長さは853 tokensです。そこには25件のサポートチケットの台帳 — 都市、キュー、優先度、担当者、内線 — と、1つの質問が入っています。Marta Ferreira needs a call back about her ticket. What is the direct line extension for that ticket?
台帳は毎回同じです。モデルも毎回同じです。変わるのは、25行のうちどの行に答えがあるかだけです。
| 答えのslot | hits | retrieval率 | 95 %区間 |
|---|---|---|---|
| 1 of 25 | 27/32 | 84 % | 68–93 % |
| 4 of 25 | 6/32 | 19 % | 9–35 % |
| 7 of 25 | 6/32 | 19 % | 9–35 % |
| 10 of 25 | 9/32 | 28 % | 16–45 % |
| 13 of 25 | 8/32 | 25 % | 13–42 % |
| 16 of 25 | 6/32 | 19 % | 9–35 % |
| 19 of 25 | 6/32 | 19 % | 9–35 % |
| 22 of 25 | 3/32 | 9 % | 3–24 % |
| 25 of 25 | 7/32 | 22 % | 11–39 % |
各行32試行、各試行で別のチケットです。20回中17回では何も区別できないので、Wilson区間はChapter 4に従いました。
slot 1は**84 %**の確率で答えられます。他の位置はすべて9 %から28 %の間で、8つの区間はすべて重なっています。正直な読み方は、最初、そしてそれ以外すべてです。LiuらはU字を見つけました — 両端が高く、中央が低い — しかしここではrecency側の腕は明確ではありません。最後のslotの22 %は中央群のばらつきの中にあります。どのばらつきにも収まらないのは、slot 1からslot 4への落ち込みです。3行です。
このモデルのcontext windowは32,768 tokensです。promptが使っているのは853 tokens、**2.6 %**です。何もあふれていません。何も切り詰められていません。上限には達していません。警告も出ていません。手渡された行が、25行のリストの中で3つ下に動いただけで、モデルはそれを見つけなくなりました。
Chapter 16はcontext windowに値段を付け、100万tokensを持っていることは、それを使えていることではないと警告して終わり、ここを指しました。ここがその場所です。
詳細を表示
この章が前の章から必要とするもの。
- **Chapter 9**ではself-attentionとそのコストを導出しました。すべてのtokenは他のすべてのtokenにattentionするため、pairwiseな関係の数は長さの二乗で増えます。この事実は以下で使いますが、再導出はしません。
- Chapter 16では課金対象になる5つのtokenバケットを数え、会話の請求が二次的に増えることを示しました。この章は、agentを壊さずにそれへどう対処するかです。
- **Chapter 18**ではツールカタログを作り、20個のツールは選択を悪化させなかったもののpromptを6倍にしたことを測りました。ここではその請求書を見ます。
- **Chapter 19**ではretrievalを作りました。以下のjust-in-time retrievalは、その章をagent自身の履歴に適用したものです。chunkingは再説明しません。
- **Chapter 23**ではharnessを作りました。この章のすべては、そのループ内で走るポリシーです。だからTypeScriptなのです。成果物はtensorを持つノートブックではなく、状態を保持する長寿命のサービスです。
似た名前の2つの仕事
セクション「似た名前の2つの仕事」へのリンクAnthropicは2025年9月に線を引きました。この2つの文は並べて読むべきです。Prompt engineeringとは「最適な結果のためにLLMへの指示を書き、整理する方法」です。Context engineeringとは「LLM inference中に最適なtoken(情報)の集合をcurateし、維持するための戦略の集合であり、promptの外からそこへ入り得る他のすべての情報を含むもの」です。1
実際の違いは、いつ、そして誰が行うかです。promptは人が一度書き、レビューします。contextは毎回の呼び出しで、誰も見ていないコードが組み立てます。材料は手で書かれたものではありません。40 turnの履歴、6つのツール結果、4つの取得済みpassage、ユーザープロファイル、12個のJSON schemaです。Chapter 15は、より良い指示で何が買えるかを測りました。この章は、自動的にやって来る残り90 %のtokensについてです。
同じ文書は、それらすべてが消費する資源の名前も挙げています。モデルには「attention budget」があり、大量のcontextをparseするときにそこから引き出す。「導入される新しいtokenはすべて、このbudgetをいくらか消耗させる」。そして症状にも名前を付けています。「context window内のtokens数が増えるにつれて、モデルがそのcontextから情報を正確に思い出す能力は低下する」 — context rotです。1
最後の文は挙動についての主張です。つまり検証できます。そしてこのページ冒頭の表が、その検証です。
その表をどう作ったか
セクション「その表をどう作ったか」へのリンクChapter 22のローカルendpointに対して40行です — CPU上でQwen2.5-0.5B-Instructを保持し、chat-completions形式で話す小さなPythonサーバーです。ループはTypeScriptに置いたまま、tensorはポートの向こう側に置きます。
const DEPTHS = [0, 0.125, 0.25, 0.375, 0.5, 0.625, 0.75, 0.875, 1];
for (const d of DEPTHS) {
const slot = Math.round(d * (N - 1));
let hits = 0, other = 0;
for (let t = 0; t < TRIALS; t++) {
const recs = buildRecords(N, 1000 + t); // 25 unique tickets
const gold = recs[Math.floor(rng(7 + t)() * N)]; // a different one each trial
const rest = recs.filter((x) => x.ticket !== gold.ticket).slice(0, N - 1);
const lines = [...rest.slice(0, slot).map((x) => x.line),
gold.line,
...rest.slice(slot).map((x) => x.line)];
const r = await complete(prompt(lines, ask(gold.owner)), { maxTokens: 12 });
const said = /\d{4}/.exec(r.text)?.[0];
if (said === String(gold.ext)) hits++;
else if (said && recs.some((x) => String(x.ext) === said)) other++;
}
}otherカウンターは、がっかりする結果を有用な結果に変えるものです。モデルが間違ったとき、それは迷子なのか、それとも自信満々なのか。
答えは、自信満々です。最初以外の8つの位置全体で、205件の誤答のうち136件は別のチケットの内線番号でした。実在する4桁の数字で、形式も正しく、間違った行から読み取られたものです。slot 1では5回のmissのうちそれは1回だけでした。slot 7では26回中21回でした。
本番で重要なのはこの区別です。見つけられませんと言うモデルは、気づけるバグです。隣の行の番号を返すモデルは、出荷してしまうバグです。画面上では2つが同じに見えるからです。これはChapter 19が検証可能な引用で防ごうとした失敗であり、indexからではなくpromptの内側からやって来ています。
場所だけではありません。量でもあります。
セクション「場所だけではありません。量でもあります。」へのリンク位置は1つの軸です。もう1つは長さで、こちらの方がテストしやすいです。答えを中央に置いたまま、リストを伸ばします。
| records | prompt tokens | hits | rate | 95 %区間 | wrong line | neither |
|---|---|---|---|---|---|---|
| 1 | 97 | 18/20 | 90 % | 70–97 % | 0 | 2 |
| 3 | 159 | 11/20 | 55 % | 34–74 % | 9 | 0 |
| 8 | 315 | 3/20 | 15 % | 5–36 % | 17 | 0 |
| 20 | 695 | 2/20 | 10 % | 3–30 % | 16 | 2 |
| 40 | 1,324 | 3/20 | 15 % | 5–36 % | 15 | 2 |
| 80 | 2,587 | 1/20 | 5 % | 1–24 % | 18 | 1 |
| 140 | 4,477 | 2/20 | 10 % | 3–30 % | 18 | 0 |
1 recordで97 tokensなら90 %。3 recordsで159 tokensなら55 %。8 recordsで315 tokensなら15 %で、そこから140 records、4,477 tokensまでずっと低く横ばいです。崩壊はすべて、リストの1行目から8行目までの間で起きています。
最後の列は、正しい内線でも別recordの内線でもないものすべてです。ページ上にrecordが1つしかない場合、誤答が着地できる場所はそこだけです。1 recordでの2つのmissは、丸めて消すのではなく報告する価値があります。どちらも拒否ではありませんでした。片方は、唯一の行に5805と書かれた台帳に対して5806と答えました。97 tokensで候補が1つだけでも、このモデルは20回に2回、数字を写し間違えます。それが、他のすべてを測る床です。
ここから2つのことが続きます。大きなcontextは、より多く送る権利を買うだけで、読まれる確実性は買いません。このモデルには32,768-token windowがありますが、このタスクでの有効範囲は数百tokensです。そして閾値も、崖も、「contextが満杯」という状態もありません。劣化は3 record目で進行中で、8 record目には完了しています。windowの1 %の地点です。context limitが何であれ、これを支配しているのはそれではありません。
通常、2つのメカニズムが挙げられます。1つ目はChapter 9の算術です。Anthropicもこの講座と同じ言葉で述べています。モデルは「transformer architectureに基づいており、すべてのtokenがcontext全体にわたって他のすべてのtokenへattentionできる。これにより、n tokensに対してn²のpairwise関係が生じる」。1 長いsequenceへのattentionは、同じ操作をより多くの材料に適用することではありません。probability massという固定budgetを、より多くの競合相手に広げることです。2つ目はtrainingです。モデルは長いsequenceより短いsequenceをはるかに多く見るため、長距離のposition patternはnetworkで最も練習量の少ない部分になります。これは議論であって測定ではなく、この章で決着はつけられません。
決着しているのは形であり、それは2023年からです。Liuらは、複数文書の質問応答とkey-value retrievalを、モデルファミリーとサイズをまたいでテストしました。そして「関連情報が入力contextの冒頭または末尾にあるときperformanceはしばしば最も高く、モデルが長いcontextの中央にある関連情報へアクセスしなければならないとき大きく劣化する。明示的にlong-contextなモデルであっても」と見つけました。2 Chapter 15はその論文から位置のルールを取り、Chapter 19は、取得した20 chunksが4 chunksより悪いscoreになり得る理由をそこから取りました。この事実の実用形は、ここで行動に移すべき唯一の文です。これは自分のモデルと自分のデータで5分で測れます。公開されたcurveは、あなたのcurveの代わりにはなりません。
誰も自分のwindowに何が入っているか知らない
セクション「誰も自分のwindowに何が入っているか知らない」へのリンクチームにagentのcontextを何が埋めているか聞くと、返ってくるのは見積もりです。答えを返すAPIがないからです。responseがくれるのはprompt_tokens、すべてをまとめた1つの数字だけです。
内訳は4つのcountと3つの引き算で復元できます。render済みprompt全体、ツール定義を除いた同じもの、ツール定義あり・なしのsystem message単体、そしてツール結果を取り除いた全体です。
async function buckets(messages: Msg[]) {
const sys = messages.slice(0, 1);
const withoutResults = messages.filter((m) => m.role !== "tool");
const [total, sysWithTools, sysNoTools, noResults] = await Promise.all([
countPrompt(messages, CATALOGUE), // everything
countPrompt(sys, CATALOGUE), // system + scaffolding + schemas
countPrompt(sys), // system + scaffolding
countPrompt(withoutResults, CATALOGUE), // everything but tool output
]);
return {
system: sysNoTools,
tools: sysWithTools - sysNoTools,
toolResults: total - noResults,
conversation: total - sysWithTools - (total - noResults),
total,
};
}countPromptはtokenizeの前にモデル自身のchat templateを適用します。これは思った以上に重要です。数えられるのは、あなたのtextそのものではありません。role marker、tool-calling preamble、schema renderingはすべて、あなたが入力していないのに支払うtokensです。Chapter 7ではtokenizerを作り、Chapter 16ではjs-tiktokenで数えました。ここでのcountは、promptを読む同じモデルから来ます。正確に正しいcountはそれだけです。
では本物のagentを通してみます。インシデント調査の40 turn、12個のツール、現実的なログdumpとmetric seriesを返す偽のoperations環境です。
| turn | system | tool definitions | conversation | tool results | total prompt | このturnで課金されたinput |
|---|---|---|---|---|---|---|
| 1 | 85 | 1,817 | 155 | 490 | 2,547 | 4,370 |
| 2 | 85 | 1,817 | 282 | 529 | 2,713 | 5,275 |
| 5 | 85 | 1,817 | 647 | 1,870 | 4,419 | 8,093 |
| 10 | 85 | 1,817 | 946 | 2,141 | 4,989 | 4,951 |
| 20 | 85 | 1,817 | 1,500 | 2,943 | 6,345 | 6,316 |
| 30 | 85 | 1,817 | 2,187 | 4,000 | 8,089 | 8,059 |
| 40 | 85 | 1,817 | 3,053 | 5,677 | 10,632 | 21,090 |
最初の行を最後の行と比べて読んでください。
turn 1ではpromptは2,547 tokensで、その71 %がtool definitionsです。system promptは3 %です。ユーザーが入力したものは6 %です。agentはまだ何もしていないのに、すでに1,817 tokens分のJSON schemaを抱えています。
turn 40までにpromptは10,632 tokensになり、比率は反転しています。definitionsは17 %、conversationは29 %、tool resultsは53 %です。tool outputはturn 5でdefinitionsを追い越しました。conversationが追い越したのはturn 25です。つまりsessionの最初の60 %では、ツールカタログの方が、それまでに話されたすべてより大きかったのです。
次にtotalです。57回のモデル呼び出し全体で、このrunは最終context 10,632に対して370,291 input tokensを課金しました。最後のpromptを約35回分支払ったことになります。Chapter 16の二次増加に、agentの倍率が乗っています。その370,291のうち、103,569、つまり課金全体の28 %は12個のtool definitionsでした。毎回byte-identicalに再送されたものです。
ツール定義はいくらかかるか
セクション「ツール定義はいくらかかるか」へのリンクツールカタログはagentで最大の固定費であり、見えません。配列のobjectを渡すだけで、providerがそれをpromptにrenderするからです。同じ12個のツールで測ると、こうです。
system prompt + chat scaffolding, no tools: 85 tokens
all twelve definitions: 1,817 tokens
of which fixed tool-calling scaffolding: 126 tokens
three tools instead of twelve: 605 tokens
same twelve, one-sentence descriptions,
no parameter prose: 1,291 tokens (-29 %)ツールごとのmarginal costは、1つのstringを取るget_current_timeの80 tokensから、enumとそれぞれ1文のガイダンスを持つ4つのparametersを取るsearch_ticketsの263 tokensまでです。これが、Chapter 18の中心的助言であるdescription is the APIの裏にある為替レートです。良いdescriptionは、agentの残りの生涯にわたり、すべてのrequestで約100 tokensかかります。帰結は3つです。
使わないツールも課金されます。 agentは12個のうち7個を呼びました。残り5個は57 requestそれぞれで697 tokensを消費しました。合計39,729です。run全体の課金の10分の1を超えますが、その能力には一度も触れていません。その5個のうち1つには、traceで最も鋭いdetailがあります。モデルは存在しないread_logを3回呼ぼうとしました。欲しかったツールはsearch_logsで、カタログで2番目に高価なdefinition、237 tokensです。そのdefinitionに57回支払い、一度も使わず、その名前も見つけませんでした。
文章を削るのは、使える中で最も安い最適化であり、trade-offです。 descriptionを1文に削り、parameter documentationを落とすと、logicには1行も触れずに1 callあたり526 tokens、29 %を節約できました。そしてモデルのツール呼び出しは悪化しました。それがChapter 18で測ったことです。要点は、そのtradeの両側が今や同じ単位で表せることです。
ある規模になると、definitionsをそもそも送ることが意味を失います。 Anthropicは2025年11月に数字を出しました。接続されたserverの大きな集合では、requestが読まれる前にdefinitionsの「数十万tokens」を処理することになります。それをcode executionに置き換え、agentが必要なdefinitionsだけを発見してloadするようにすると、「token usageは150,000 tokensから2,000 tokensへ減り、時間とコストを98.7%節約する」。3 この章の残りと同じ考えを、履歴ではなくschemaに適用したものです。indexを保持し、entryは必要時に解決する。
わざと壊す
セクション「わざと壊す」へのリンクその40 turnのtranscriptには2つのものを仕込みました。turn 2、本格的な作業の前に、ユーザーは恒久ルールを述べます。any ticket you open must be filed under my employee number, 4417. turn 19、インシデントの途中で、事実を述べます。the affected shard is pay-shard-7, confirmed by the payments team. turn 40でユーザーはagentにインシデントチケットを開くよう頼みます。そこには両方が必要です。各probeは6通りの言い回しで尋ね、6点満点でscoreします。greedy decodingはdeterministicなので、1回のcallでは繰り返せないyes/noしか得られませんが、6回ならrateが得られます。
次にtranscriptを7つのcontext policyでreplayします。意図的にre-runではなくreplayです。messages、tool calls、tool resultsは7つすべてでbyte-identicalなので、唯一の変数は各policyが何を保持することにしたかです。Chapter 16は、sliding windowが悪い経済的手である理由を示しました。cacheable prefixを破壊するからです。では挙動には何が起きるでしょうか。
| context policy | 40 turns全体のinput tokens | turn-40 prompt | turn-2 rule | turn-19 fact |
|---|---|---|---|---|
| full history | 370,291 | 10,632 | 6/6 | 5/6 |
| sliding window, last 12 messages | 157,578 | 2,922 | 5/6 | 0/6 |
| elide tool results older than 4 turns | 243,445 | 6,311 | 6/6 | 3/6 |
| compaction every 6 turns | 195,515 | 3,220 | 6/6 | 0/6 |
| compaction plus model-written notes | 200,849 | 3,286 | 6/6 | 0/6 |
| pin the user's own turns, at the front | 168,550 | 3,559 | 6/6 | 5/6 |
| pin the user's own turns, at the back | 168,835 | 3,564 | 6/6 | 6/6 |
| control: the two turns and nothing else | — | 1,981 | 6/6 | 6/6 |
compactionの行には、compactするコストも含めています。7つのsummaryに18,581 input tokens、note-takerにさらに3,392です。control行があるのは、0を0として読めるようにするためです。2つのmessageだけを1,981-token promptに入れると、このモデルは両方のprobeに完璧に答えます。つまり、どの行もtaskが難しすぎるわけではありません。
Full historyは覚えており、表の中で最も高価です。sessionのdurable contentが2文だけなのに、370,291 input tokensです。
これで冒頭が残していた問いに答えられます。なぜ10,632-token transcriptは、853-tokenの台帳が失う事実を保持できるのでしょうか。長さが間違った変数だからです。台帳には25個の4桁内線が、25個の同一に近い文の中にあります。欲しい1つに対して、24個のほぼ完全なdecoyです。transcriptにはemployee numberが1つ、shard nameが1つだけあります。Context rotは、volumeである前にinterferenceです。だから上の205件の誤答のうち136件は隣の値だったのです。windowについて有用な問いは、どれだけ長いかではありません。その中に答えに見えるものがいくつあるかです。
sliding windowは57 %安く、インシデントを失っています。 employee numberが生き残るのは、agentがそれを最近のturnに繰り返していたからだけです。shardはturn 19で一度述べられたきりで、最後の12 messagesにはありません。そしてモデルはそうは言いません。6回尋ねると、*「the affected payment shard is shard 4417」と答えました。windowに残っている唯一の別identifierであるemployee numberに手を伸ばしたのです。さらに2回は、log line内の文字列pool_exhaustedから拾った「pool」*でした。
Compactionは安く、同じ事実を失いました。 7つのsummaryは、identifiers、numbers、standing instructions、open questionsを保持するという明示的な指示のもとでモデルが書きました。それでもpay-shard-7は、重要なsummaryのどれにも入っていません。6つの推測はshard 1、pay_shard_1、poolでした。Compactionは大きな音を立てて失敗しません。流暢で、もっともらしく、ずっと短いsessionを作り、1行を静かに落とします。
turn-19 factで0/6だった行は3つあります — sliding window、compaction、notes付きcompactionです。それらの18件の誤答のうち、「分かりません」は1つもありませんでした。
次に、恥ずかしくなるべき行です。ユーザー自身の40 messagesをverbatimで保持し、さらに最後の4 turnsをfullで保持し、それ以外を捨てるだけで、コストは168,550 tokens — full historyより54 %少ない — になり、両方のprobeにfull history同等以上に答えます。 summariserも、note-takerも、2つ目のモデルもありません。role === "user"上のfilterだけです。ユーザーの言葉はagentのwindowで最も安い高価値tokenであり、多くの設計はそれを他のものと一緒に捨てています。
最後の2行は、冒頭の表がagentの中で再現されたものです。同じpinned blockをsystem messageからpromptの末尾へ動かすと、5/6が6/6になります。6試行では有意差ではなく、そう主張するものでもありません。ここで示しているのは、whereは、あなたが自覚しているかどうかに関係なく設定しているparameterだという reminderです。
windowを節約する4つの方法
セクション「windowを節約する4つの方法」へのリンク下の4つのstrategyはAnthropicのもので、順序も同じです。ただし最後の3つだけが同社のlong-horizon listです。1 4つすべては1つの指示の変奏です。取得できるものを持ち運ばない。圧縮して持てるものをrawで持ち運ばない。
Just-in-time retrieval
セクション「Just-in-time retrieval」へのリンクcontentをpre-loadしません。identifier — file path、query、ticket number、tool nameとそのarguments — を保持し、必要になったら解決します。上のagentで最大のbucketは、一度読まれ、一度使われ、その後さらに30 turns持ち運ばれたtool outputです。4 turnsより古いresultをすべて、それが何で、どう取り戻すかを示すstubに置き換えるのは6行です。
const elide: Policy = (h) => [SYSTEM, ...h.flatMap((turn, ti) =>
turn.map((m) => (ti < h.length - 4 && m.role === "tool"
? { role: "tool", name: m.name,
content: `[${m.name} result from turn ${ti + 1}, ${m.content.length} chars, ` +
`elided; call ${m.name} again with the same arguments to re-read it]` }
: m)))];これはChapter 19で、corpusをagent自身の過去に置き換えたものです。retrieval machineryはすでにあります — それはツールカタログです。
Compaction
セクション「Compaction」へのリンクtranscriptが閾値を超えたら、最も古い部分をモデルが書いたsummaryに置き換えて続行します。summaryを書くpromptが設計のすべてであり、compactionの勝敗はそこで決まります。identifiers、numbers、standing instructions、open questionsを保持する。挨拶や、再取得できるtool outputは捨てる。
Compactionは構造上lossyであり、何を失うかはモデルがあなたの代わりに選びます。そして間違って選んでも何もerrorになりません。無料でもありません。すべてのcompactionは追加callで、そのinputはcompactされる対象そのものです。
Structured note-taking
セクション「Structured note-taking」へのリンクcontextの外に小さなstoreを維持し、毎turnまるごと再注入します。summaryと違い、append-onlyでaddressableです。turn 2で書かれたruleはturn 400でもverbatimに残っています。ここで測ったversionは、各user messageの後に、それがdurableなものを含むかモデルへ尋ねます。
const r = await complete([
{ role: "system", content:
"You keep a durable note file for a support session. Given one user message, " +
"output one short note ONLY if it states a standing rule, an identifier or a fact " +
"that must survive the rest of the session. Otherwise output exactly NONE." },
{ role: "user", content: `Turn ${i + 1}: ${user}` },
], { maxTokens: 40 });
if (!/^none\b/i.test(r.text.trim())) notes.push(`turn ${i + 1}: ${r.text.trim()}`);ここで最も天井が高いstrategyであり、測定で失敗したのもこれです。40件のuser messagesで、note-takerは3つのnotesを保持し、重要だった2つはどちらも保持しませんでした。runbook adviceの1行、sessionが終わるという告知、そしてEurope/Madrid is currently 13:45です。これはinventedした時刻です。paraphrase対象のツールは09:52 UTCを返していたからです。note-takerはモデルであり、この章のすべてはそれにも当てはまります。
Sub-agents
セクション「Sub-agents」へのリンクfocused taskに専用のwindowを与えます — 専用のsystem prompt、専用の小さなカタログ、parentのhistoryなし — そしてtranscriptではなく短い答えを返します。Chapter 23ではそれをtool schemaの裏に置き、請求書をここに残しました。その請求書とは、childのwindowのうちparentが支払うのはchildのanswerだけだということです。
sub-agentは上の表にありません。40 turns走らないからです。誰かがscopeしたwindowの中で一度だけ走ります。system prompt、turns 17から19、そしてそれ以外なし — 2,737 tokens — を与えると、shard probeには6/6で答えました。表のすべてのpolicyより良いです。そしてemployee probeは0/6でした。渡された3 turnsにそのnumberがないからです。
これが2つの数字で見るsub-agentsです。clean windowはintelligenceではなくscopeです。そしてscopingは、どのturnが重要かをすでに知っていなければならないコードが事前に行います。これらの答えでもう1つ残す価値があることがあります。このpolicyだけが、何かをinventする代わりに*「None available」*と答えました。小さく一貫したcontextを持つモデルは、自分に何が欠けているかを知っています。大きくnoisyなcontextを持つモデルは知りません。
3つの記憶
セクション「3つの記憶」へのリンクagent memoryについての混乱した会話のほとんどは、1つの言葉をまとった3つのmechanismsです。それらはlifetimes、owners、failure modesが違います。同じ場所に置いているsystemは、まだ気づいていない問題を抱えています。
| conversation history | retrieval | persistent user memory | |
|---|---|---|---|
| holds | このsessionで言われたこと | 所有しているdocuments | personについてのfacts |
| lives | 1つのsession | re-indexされるまで | 全sessionsをまたいで、永続 |
| written by | loopが自動で | ingestion pipeline | modelが意図的に |
| enters the prompt | 毎call、fullで | queryがmatchしたとき4 passages | 毎call、fullで |
| fails by | rotするまで成長する | wrong chunkを取得する | あなたについて間違ったことを覚える |
| built in | Chapter 23 | Chapter 19 | この章 |
学術的なframeはCoALAのものです。language agentsを「modular memory components」を中心に整理し、working memoryをepisodic、semantic、procedural storesから分けます。4 MemGPTは同じ考えを文字通りに取り、operating systemsのvirtual memoryを借ります。window内のfast tier、その外側のslow tier、そしてfunction callsでモデル自身がdataをその間で動かします。5 どちらも、productがいずれにせよ答えなければならない問いを強制します。どれだけ保持できるかではなく、これはどのstoreに属し、いつexpireするのかです。
実用上のtestは、factごとに1つの質問です。明日も真であるべきものは何か。 turn 12のtool resultなら、何もありません。sessionのsummaryなら、sessionが終わるまでです。ユーザーのemployee numberが4417であることなら、その人が転職するまでです。3つの答え、3つのstoresです。
次にどこへ進むか
セクション「次にどこへ進むか」へのリンクこれで、windowの中に何があるかを測り、何をそこに残すかを決め、何かを忘れたagentと、それを持っていたのに見なかったagentを区別できるようになりました。
4つのstrategyの最後は、ここには収まりません。sub-agentはcontext policyではなく、2つ目のagentです。そして2つになった瞬間、両者の間で何を渡すか、どちらが責任を持つかを決めなければなりません。Chapter 25がそれです。5つのorchestration patternsと、それぞれの名前が実際にはどこから来たのか。混同される2つのtopologies — sub-agentに尋ねて答えを返してもらうことと、conversationを渡して戻してもらわないこと — そして、そこで値付けされるtaskでは、より単純な構成が勝つという測定結果です。その後に、それが勝たなくなる時を調べるtestが続きます。
それはまた、この章が測ったものをそのまま継承します。sub-agentはsummaryを返します。summaryとは、あなたが書いていないcompactionであり、見えないwindowを持つモデルが生成したものです。そしてparentには、それが良いものか、自信満々に間違ったものかを見分ける方法がありません。ページ上部で84 %と19 %を分け、18個のmissing factsを18個のinvented factsに変えたのと同じ区別です。では、sub-agentが間違ったとき、parentはいったい何を見られるのでしょうか。
Sources and method
セクション「Sources and method」へのリンクここにある数字はすべてこのmachine上で生成され、推定はありません。モデルはCPU上のfloat32で動くQwen2.5-0.5B-Instructで、greedy decodingです。chat-completions形式を話し、token-count routeを公開する小さなPython endpointによりloopbackでserveしました — Chapter 14のseam再びです。tensorはPython側、loopはTypeScript側です — したがってすべてのcountは、そのモデル自身のtokenizerを、そのモデル自身のchat templateに適用したものです。position tableは288 calls、9 positions × 32 trialsで、各trialは別ticketです。length tableは140 callsです。agent runはwall clock 43分にわたる57 model callsです。policy tableは、その1つのtranscriptを7つのpoliciesでreplayしたものです。IntervalsはChapter 4からのWilsonです。有料APIは呼んでいません。そのためこの章にpriceは1つもありません。token countsは正確で、それに掛けるratesはChapter 16のものだからです。
参考文献
セクション「参考文献」へのリンク-
Anthropic, Effective context engineering for AI agents, 29 September 2025,
anthropic.com/engineering/effective-context-engineering-for-ai-agents, read 7 September 2026. 冒頭で引用した2つの定義、「attention budget」と、new tokenがそれを消耗させるという記述、context rotの説明、n² pairwise-relationshipsというframe、そしてこの章の背骨として使ったstrategyの出典です。そのうち3つ — compaction、structured note-taking、multi-agent architectures — は同記事のlong-horizon listです。just-in-time retrievalは同じ記事の前半、context retrievalとagentic searchの下に出てきますが、ここではそれらとまとめています。 ↩ ↩2 ↩3 ↩4 -
Liu, N. F., Lin, K., Hewitt, J., Paranjape, A., Bevilacqua, M., Petroni, F. and Liang, P. Lost in the Middle: How Language Models Use Long Contexts. arXiv:2307.03172 (v1 July 2023, v3 November 2023). Chapters 15、16、19で引用し、ここで測定しました。引用文はabstractからです。このpaperの2つのtasksはmulti-document question answeringとkey-value retrievalであり、そのeffectが明示的なlong-context modelsでも持続するというfindingこそが、product decisionにとって重要な部分です。 ↩
-
Anthropic, Code execution with MCP: building more efficient agents, 4 November 2025,
anthropic.com/engineering/code-execution-with-mcp, read 7 September 2026. 150,000から2,000 tokensへの削減、98.7 %という数字、そしてrequestが読まれる前にup frontでloadされたtool definitionsがcontextを占有するというobservationの出典です。 ↩ -
Sumers, T. R., Yao, S., Narasimhan, K. and Griffiths, T. L. Cognitive Architectures for Language Agents. arXiv:2309.02427 (2023). language agentsを「modular memory components, a structured action space to interact with internal memory and external environments, and a generalized decision-making process to choose actions」を中心に整理し、memoryをworking、episodic、semantic、proceduralに分割しています。Chapter 22ではlearning agentのためにそのtaxonomyを使いました。上の3-store tableはその実用上の影です。 ↩
-
Packer, C., Wooders, S., Lin, K., Fang, V., Patil, S. G., Stoica, I. and Gonzalez, J. E. MemGPT: Towards LLMs as Operating Systems. arXiv:2310.08560 (October 2023). 「virtual context management, a technique drawing inspiration from hierarchical memory systems in traditional operating systems」を提案し、モデル自身がwindow内のfast tierと外側のslow tierの間でdataを動かします。windowはmemoryではなくcacheである理由を、どこよりも明快に述べています。 ↩