BEACHSIDE BLOG

Azure と GitHub と C# が好きなエンジニアの個人メモ ( ・ㅂ・)و ̑̑

VS CodeにおけるGitHub Copilotのトークン効率の向上の取り組み (日本語訳)

GitHub Copilot の課金方法が Usage-based billing に変わったことでトークンの節約方法が注目されている昨今ですが、VS Code 公式の 6/17 にブログで、VS Code がどのようにトークン効率の向上をしたかを公開していました。

これらのナレッジを GitHub Copilot ユーザーとしてのノウハウになるわけではないですが、エージェント開発をする立場として把握しておこうという意図で日本語に残してみました。

Improving token efficiency for GitHub Copilot in VS Code

以下、日本語にしたものです。


最近の GitHub Copilot の usage-based billing への移行に伴い、agentic session におけるすべての token が重要になります。これらは credits、latency、そして agent が task を完了するために残された context window に影響を与えます。自社のデータでも確認されているように、新しい model generation はそれぞれ、前の世代よりも task あたりに多くの tokens を消費する傾向があります。これは、この傾向に対抗するために harness-level の効率性がますます重要になっていることを意味します。agents がより長く、より autonomous な作業を担うようになるにつれて、非効率な harness による負担は急速に蓄積されていきます。

VS Codeにおける GitHub Copilot の agentic harness をより token-efficient にすることは継続的な取り組みであり、この傾向に対抗するための最善の方法です。ほとんどの変更において、私たちは本番環境での A/B experiments や、task suites に対するオフラインの evaluations を実行し、token usage が減少する一方で task の success rate が維持または向上することを確認しています。一度に大きな成果が得られることは滅多になく、通常は小さな改善が着実に積み重なっていくものです。以下では、最近の成果について、まずは OpenAI models、次に Anthropic models の順で詳しく説明します。

agentic requests がどのように tokens を消費するか

すべての agentic request の核心には2つの costs があり、2つの ideas がそれらの削減に役立ちます。各プロバイダーによる公開(expose)のされ方は異なりますが、これらは OpenAI と Anthropic の両方の models に適用されます。

prompt の各部分をハイライトした prompt signature のグラフィカルな概要。

prompt prefix と caching。agentic coding session において、各 request の大部分はターンをまたいで繰り返されます。これには system instructions、tool definitions、repository context、および conversation history が含まれます。この繰り返される先頭部分が prompt prefix です。requests が全く同じ prefix を共有する場合、inference provider は request ごとにゼロから再計算する代わりに、cached model state を再利用できます。名前に反して、cached artifact は人間が読めるような prompt のコピーではありません。これは、その prefix を処理する過程で計算された model state であり、内部的には key/value tensors として表現されます。prefix を再利用することで、cost(cached tokens は最大10倍安価になる場合があります)と latency の両方を削減できるため、私たちは prompt cache hit-rate を高く維持するように努めています。

Tool-definition のオーバーヘッド。Agents は、MCP servers によって公開されたもの、built-in tools、または extension-provided tools など、多数の tools を取り込むことができます。各 tool は完全な定義(name、description、および完全な JSON parameter schema)とともに model に送信され、従来はすべての request においてこれらすべてが context に読み込まれていました。そのデータが cached されている場合でも、各ターンにおける context window のオーバーヘッドは固定されており、toolset が拡大するにつれて増加します。

Tool search。Tool search は、model がすべての tool definitions を一度に読み込むのではなく、オンデマンドで読み込めるようにすることで、その overhead を削減します。最初、model には見やすくて軽量な metadata(各 deferred tool の name と description)のみが提示され、より重い parameter schemas は、model が tool を検索して読み込むまで context の外に置かれます。deferred tools は prefix ではなく context window の最後に追加されるため、cached prompt prefix の再利用性が維持され、caching gains がターンをまたいで機能し続けます。その成果として、より無駄のない context window が実現します。model は使用しない tools に消費する tokens を減らすことができ、実際の task により多くのスペースと budget を残せるようになります。

OpenAI models における効率性の向上

OpenAI の models について、VS Code の最近の取り組みは、token efficiency の向上を通じて Copilot ユーザーの usage costs と latency を削減することに焦点を当てていました。私たちは、cached model state の保持期間の延長、tool-definition overhead の削減、そして繰り返される HTTP requests から持続的な WebSocket connections への置き換えという3つの変更を通じて、これを追求しました。

prompt caching の拡張

OpenAI models は prompt prefix を自動的に cache します。provider は再利用可能な prefix を推論し、requests をまたいでその model state を再利用します。この再利用には直接的な cost benefit があります。cached input pricing をサポートするほとんどの OpenAI models において、uncached input tokens は cached input tokens の10倍のコストがかかります。

prefix の caching は自動的に行われますが、その cache がどのくらい持続するかは構成(configure)可能です。慎重な評価の結果、私たちは prompt_cache_retention body parameter を通じて、サポートされている models 向けに extended prompt caching を有効にしました。デフォルトでは、cache は高速な GPU memory 上に存在しますが、他の作業のスペースを空けるため、約5〜10分間(場合によっては最大1時間)非アクティブな状態が続くと破棄されます。"prompt_cache_retention": "24h" に設定することで、cache は低速ながらも大容量な GPU-local storage に移動し、最大24時間保持されます。

この利点はシンプルです。デフォルトの cache では、数分以上中断すると cache が破棄されるため、次の request では、割引のない uncached price で prefix 全体を再処理する必要があります。Extended retention によって cache が warm な状態に保たれるため、長時間の休憩後であっても、中断したところから高速かつ安価に作業を再開できます。

VS Code でサポートされている OpenAI models に対して extended prompt caching を有効にした後、私たちは cache hit rate の相対的な増加を測定しました。これらは relative changes(相対的な変化)であり、パーセンテージポイントの増加ではありません。つまり、919%の増加とは、cache hit rate が以前の値の10.19倍になったことを意味します。

Time between requests GPT-5.2 GPT-5.3-Codex GPT-5.4
10-20 min +13% +32% +10%
20-30 min +135% +142% +137%
30-40 min +301% +203% +679%
40-60 min +338% +279% +919%

この増加は、requests 間の間隔が長くなった場合に最も大きくなりました。これは、通常であれば期限切れになっていたはずの cached model state が、再利用可能な状態のまま維持されたためです。実際には、この増加により、prompt のより多くの部分がより安価な cached-input rate で処理されることになり、長時間の休止後であっても requests の cost が削減されます。

すべての request においてすべての tool definitions を送信することを避けるため、tool search はこれをオンデマンドにします。GPT-5.4 以降の models で利用可能な OpenAI の native tool search は、defer_loading flag を使用してこの deferral (遅延して読み込む、ようは必要な段階になったら読み込む) を実装しています。

最初、model には軽量な metadata のみが提示されます。つまり、各 deferred function の name と description、あるいは deferred functions が namespace にグループ化されている場合は、その namespace の name と description のみです。

GPT-5.4 および GPT-5.5 を使用した4日間の VS Code experiment において、tool search は、turn あたりの token utilization、time to first token、および time to complete を削減しました。

Metric Model Delta
P50 Total tokens used per turn GPT-5.4 -9.81%
P50 Total tokens used per turn GPT-5.5 -8.61%
P50 Time to first token (TTFT) GPT-5.4 -6.88%
P50 Time to first token (TTFT) GPT-5.5 -7.34%
P50 Time to complete (TTC) GPT-5.4 -5.31%
P50 Time to complete (TTC) GPT-5.5 -5.42%

セッション全体で集計すると、中央値の Copilot ユーザーにおける total token usage は、GPT-5.4 で 8.97%、GPT-5.5 で 10.92% 減少しました。

WebSockets

agentic coding のターンには、inference provider に対する多数の連続した requests が含まれる場合があります。これは、model が tools を呼び出して解決に向けて作業を進める各ステップにつき、1つの request が発生するためです。基盤となる HTTP connection が再利用される場合でも、各ステップは個別の API request のままです。

Responses API の WebSocket mode は persistent connection を開いたままにし、それらの連続した requests に対して lower-latency な continuation path を提供します。アクティブな connection においては、OpenAI は connection-local の in-memory cache から最新の response state を再利用することもできるため、長い tool calling の連鎖における continuation overhead を削減します。

数ヶ月前、OpenAI は Responses API での WebSocket サポートを発表しました。初期のドキュメントで大幅な latency の改善が示されていたため、私たちは早期に実験を行い、独自の A/B test においても一貫した latency reductions を確認しました。これは、振り返ってみれば当然と思えるアイデアの一つでした。agentic coding sessions は long-lived interaction にわたって requests を繰り返しますが、これはまさに WebSockets が処理するように設計されているものだからです。

VS Code Stable への WebSockets の初期 rollout 期間中、A/B experiment で得られた latency gains は production 環境でも維持されました。以下の表は、その rollout 中の HTTP に対する WebSockets の相対的な latency gains を示しています。それ以降、improved prompt caching を含むスタックの他部分での改善により、latency と usage costs はさらに削減されています。各 metric において、値は低いほど良好(lower is better)であることを示します。

Tracking metric Percentile GPT-5.3-Codex GPT-5.4
Time to first token (TTFT) p50 -19.46% -16.37%
Time to first token (TTFT) p95 -12.92% -15.78%
Time to complete (by turn) p50 -13.55% -11.74%
Time to complete (by turn) p95 -7.86% -6.26%

また、user engagement においても、統計的に有意な相対的な増加が確認されました。GPT-5.3-Codex および GPT-5.4 では、active users がそれぞれ 1.27% および 2.17% 増加した一方で、two-day engagement は 1.90% および 3.14% 増加しました。

これらの成果を受けて、VS Code、Copilot CLI、GitHub app などの Copilot products 全体において、GPT-5.2 以降の OpenAI models に対する default transport を WebSockets に設定することになりました。

Anthropic models における効率性の向上

Anthropic models について、私たちの最近の取り組みは、同じ2つの繰り返される costs に焦点を当てました。それは、cache 内で warm な状態に保つ prompt prefix と、すべての turn で送信する tool payload です。私たちは2つの変更を通じてこれを追求しました。prompt-cache breakpoints をより意図的に消費することと、tool search を通じて tool definitions を defer させることです。

よりスマートな prompt caching

Anthropic の prompt caching は、OpenAI models が使用する automatic prefix caching とは異なる働きをします。provider が再利用可能な prefix を推論するのではなく、caller が明示的に cache_control breakpoints を配置し、API は各 marker までのすべてを cache します。 request あたりの breakpoints の budget は小さく固定されているため、それらをどこに配置するかは、それらを使用するかどうかと同じくらい重要です。私たちは Messages API caching を改修し、prompt の最も安定した境界にアンカーを置いて、最大4つの breakpoints を意図的に消費するようにしました:

  • tool definitions の末尾および system prompt の末尾(これらは turns 間で最も変化の少ない部分です)。
  • 直近の2つの cacheable messages に配置された、一対の rolling anchors。

2つ目の、より古い anchor は安全網(safety net)です。最新の anchor が miss した場合(遅い tool call によって cache が失効したり、content がわずかにずれたりした場合)、古い anchor がそこまでのすべてをカバーする hit として機能します。通常、会話の cache 全体を cold-start する代わりに、1回のやり取り(exchange)を放棄するだけで済みます。

これらの変更により、cache hit rate は数パーセントポイント着実に増加しました。prefix が長く、turn が連続して発生する agentic workloads においては、現在約94%に達しており、これは、各 request の input のごく一部のみが再計算を必要とし、残りは cache から提供されることを意味します。これにより、usage cost と time to first token の両方が削減されます。

Tool search

Anthropic の tool search tool にも、同じ deferral のアイデアが適用されています。Tools には defer_loading: true が設定されており、deferred catalog と並行して、小さく厳選された core tools のセット(ファイルの読み書き、ターミナルコマンドの実行、ワークスペースの検索など)を常にロードしておくことで、最も一般的なアクションで余分なステップを必要としないようにしています。

私たちは最初、Anthropic の server-side tool search を使用してこれを rollout しました。model は Anthropic 側で deferred catalog を検索し、API が match したものをインラインで tool_reference blocks に展開します。7日間の VS Code experiment において、tool definitions を defer させることで、prompt-token と total-token 両方の usage が減少し、time to first chunk が短縮されました。

Metric Percentile / scope Delta
Time to first chunk p50 (by turn) -2.45%
Total prompt tokens p50 (by turn) -11.30%
Total prompt tokens p95 (by turn) -8.85%
Total prompt tokens p50 (by user) -18.32%
Total tokens p50 (by turn) -11.09%
Total tokens p95 (by turn) -8.74%
Total tokens p50 (by user) -18.03%

中央値の Copilot ユーザーにおいて、セッション全体で全体的な prompt-token および total-token の usage はそれぞれ約18%減少しました。

このアプローチの有効性が実証されたため、私たちは search 自体を client-side に移行し、VS Code の縮小された toolset のために構築したものと同じ tools-grouping system でそれをバックアップしました。model は引き続き tool_search tool を呼び出しますが、Anthropic が deferred catalog に対して matching を行う代わりに、私たちがローカルで search を実行し、最適な matches に対して tool_reference blocks を返します。

この local search はよりスマートでもあります。tool の names や descriptions に対する lexical matching ではなく、内部の Copilot embedding model(embedding-guided tool routing を駆動しているのと同じ model)を使用して、query を利用可能なすべての tool の vector representations と比較します。文字通りの keywords ではなく intent(意図)を match させるため、「find all references to this symbol」のような request では、その name や description が query と共通の単語を一切持たない場合でも、適切な tool が提示されます。

この背後にある grouping および embedding-guided tool routing の詳細については、How we're making GitHub Copilot smarter with fewer tools を参照してください。

search を client-side に移行したことで、当初の token savings 以外にも、いくつかのさらなる利点が得られました:

  • Responsiveness:search は cached embeddings に対してローカルで実行されるため、tool の発見はサーバー側の search round trip に依存しなくなりました。
  • Dynamic MCP tool discovery:私たちが候補セット(candidate set)を管理しているため、接続された MCP servers がセッションの途中で追加または削除した tools が、固定されたサーバー側のカタログを待つことなく即座に反映されます。
  • Better quality:embedding-guided search により、特定の query に対して適切な tool が提示される可能性が高くなり、以下の metrics に示されているように、ユーザーエラーの減少と task success の向上につながりました。
Metric Model Delta
Time to first token (p50) Claude Opus 4.6 -1.91%
Time to complete (p50) Claude Opus 4.6 -1.97%
Time to complete (p95) Claude Opus 4.6 -2.57%
Time to complete (p50) Claude Sonnet 4.6 -1.30%
Time to complete (p95) Claude Sonnet 4.6 -3.35%
User error rate Claude Sonnet 4.6 -4.01%

どちらのバリアントでも、deferred tools は cached prompt prefix の外側に配置されるため、prefix が書き換えられることはなく、上記の caching gains は turns をまたいで機能し続けます。そして、一度 tool が発見されれば、それは会話の残りの期間中利用可能な状態が維持されるため、model がそれを再び検索するためにコストを支払う必要はありません。

What's next

上記の取り組みにより、私たちの agentic harness はより無駄のないものになります。すなわち、cache hit rate の向上、request あたりの tool definitions の削減、そして transport overhead の減少です。次のステップは、特定のカテゴリーの作業全体をメインの agent から完全に切り離すことです。私たちは、ワークスペースの検索、コマンドの実行、結果の要約といった限定的な tasks のために、特化した subagents を構築しており、カスタムトレーニングされた subagents も探求しています。それぞれ、その job をこなせる最も小さく安価な model 上で実行されるため、メインの model が自身の context 内でその作業のコストを支払う必要がなくなります。その結果、task あたりの全体的な cost が削減されます。

さらに、私たちは product 内での token usage や cache state に関する透明性を向上させる取り組みも行っています。これには、長時間の休止後に cache が切れた状態でセッションを再開したり、セッションの途中で reasoning effort を変更したりするなど、気付かないうちに cost を押し上げる原因となる actions へのフラグ立てが含まれます。これにより、ユーザーは cache の cold start に対するコストを支払う前に、情報に基づいた選択ができるようになります。

agentic harness をより token-efficient にすることは継続的な取り組みであり、私たちは今後も小さな改善を一つずつ積み重ねながら、投資を続けていきます。

Happy coding! 💙