SpaceXAI チームが共有する Grok Bot 構築のエンジニアリング知見:分散システム設計、操作安全ポリシー、コンテキストエンジニアリングのトレードオフ
メッセージによる起動、クラウドPCからチェックポイント復帰、長期記憶まで:Lee Robinson が Stanford CS146S で Grok Bot の構築経験を共有し、Agent がバックグラウンドで作業を継続するためにどのようなシステムが必要かを解説する。
スタンフォード大学 CS146S の講義において、かつて Cursor に在籍し、現在は SpaceX に所属する Lee Robinson が、チームによる Grok Bot 構築のエンジニアリング知見を共有した。Grok Bot は常駐型の Agent であり、ユーザーが目標を指示すると、クラウド上で作業を進め、メッセージや定期タスクによって起動されるため、ステップごとにユーザーのプロンプトを待つ必要がない。
学生が前週に構築したシンプルな Agent は、モデルがローカルの実行フレームワーク(Harness)内でツールの呼び出し、ファイルの読み取り、コマンドの実行をループ処理するものだった。ローカルPCがスリープに入るか、ターミナル内のプロセスが終了すると作業は続行できず、人間の承認が必要な操作も停止して待機状態になる。対話が長くなると、ツールの出力がモデルが同時に処理できる情報空間を圧迫し続ける。
常駐型 Agent(Always-on Agent)が解決を目指しているのは、まさにこのような運用の断絶である。長期的に協調できるデジタルな同僚のように、Agent がクラウド上に専用のコンピューターと独立した環境を持ち、外部イベントに応じてバックグラウンドで自律的にタスクを進め、必要なときにだけユーザーに報告できるようにすることを目指している。
これはシステム構築の知見を共有したものであり、一部の機能は現在も開発中である。数週間あるいは数か月にわたって安定して動作することは、Lee が今後の発展に期待している点である。プロトタイプスクリプトを安定的で信頼性の高い常駐サービスへと進化させる鍵は、一連の具体的な分散システム設計、運用の安全性ポリシー、そしてコンテキストエンジニアリングのトレードオフにある。
タスクを任せた後も、いつでも指示を変更できる
Lee はこの変化を4つの開発スタイルで説明している:
- コピペ段階: Webページ上でモデルに質問し、コードを手動でローカルエディタにコピーし、エラーが出たら再びブラウザに貼り付ける。
- ターミナル Agent 段階: モデルがローカルループに入り、ファイルの読み書きやターミナルコマンドの実行を自律的に行えるようになる。ただしこの段階では、モデルが生成した shell コマンドの実行可否を人間が1つずつ確認する必要がある。
- 専用並行アプリケーション段階: Agent タスクに特化したインターフェースが登場し、バックグラウンドやクラウド上で複数のタスクを並行して起動でき、開発者は完了時にコードの差分(Diff)をレビューする。
- 常駐型 Agent 段階: ユーザーはチャットツールや軽量なメッセージを通じて Agent に大まかな目標を指示する。Agent はクラウド上に独自の環境、長期記憶、ツールインターフェースを持ち、ユーザーがオフラインになった後も作業を進め、外部イベント(カレンダー、Webhook、チームのメッセージなど)によってオンデマンドでトリガーされる。
Lee はこうしたプロダクトの進化をモデル能力の向上と結びつけている。モデルはより長期間にわたって複雑な指示に従えるようになり、サブタスクを独立したアシスタントに委任することもできるようになった。構造化 API やターミナルコマンドの呼び出しに加え、画面を直接見てクリックするコンピューター操作も徐々に習得している。同時に、モデルはユーザープロファイルや運用ルールをファイル形式で自律的に読み書きし、人間の操作実演からスキルを学習することもできる。これらの基盤能力の成熟によって、長期的なバックグラウンド実行が現実的な実現可能性を持つようになった。
協調スタイルの変化における鍵は、対話の頻度と主導権の分担にある。従来のターミナルモードでは、モデルがコマンドを1つ実行するたびに人間の承認を待つ必要があった。一方、常駐モードでは、Agent がバックグラウンドで指示を実行し続け、人間は主に要所での軌道修正を担当する。例えば Agent の実行中に、ユーザーはいつでも追加メッセージを送信できる。「ついでにあそこのスレッドも確認して」「時間を木曜日に変更して」「下書きがまとまったらカレンダーの招待を直接送って」。
このような対話スタイルに伴い、重要な安全機構として自動レビュー(Auto Review)が導入されている。Agent がバックグラウンドで大量のコマンドを実行する際、人間が目視で1つずつ確認していては承認疲れを引き起こしやすい。エンジニアリング面では独立した安全審査モデルが導入され、潜在的なリスクを伴うコマンドの実行前にリアルタイムで検証を行う。安全モデルがある操作にリスクがあると判定してブロックした場合、システムはユーザーに明示的な承認リクエストをポップアップ表示する。講義で紹介されたプロトタイプ設計では、ユーザーが15秒以内に応答しなかった場合、その操作はデフォルトでブロック状態を維持する仕様となっている。
常駐とはPCを常に起動し続けることではない:タスクとPCを分離して実行する
このアーキテクチャに初めて触れる開発者の多くは、直感的にこう考えがちである。「Agent がコマンドやブラウザを実行する必要があるなら、クラウド上に仮想マシンを1台立ち上げ、モデルの対話ループもデスクトップ環境もすべてその中に入れればよいのではないか?」
しかし実際のシステム運用において、このような密結合はシステムの明らかな脆弱性をもたらす。下層のOSのパッチ適用で仮想マシンを再起動する必要が生じたり、テスト中にブラウザがメモリを使い果たしてクラッシュしたりすると、その中で動作している Agent プロセスも中断されてしまう。さらに、タイマーを待つためだけ、あるいはプレーンテキストを処理するためだけに、GUIを備えたフルスペックの仮想マシンを24時間起動したまま稼働させておくのは、不要なアイドル計算コストを大量に発生させる。
そのため、Grok Bot では3層の分離(疎結合)によるシステム構成を採用している:
スマートフォンとWeb画面でメッセージを受信し、結果を表示する
モバイルアプリ、デスクトップクライアント、Web、Slack、メール、音声通話など、多様なアクセス手段に対応している。クライアントは主にUIの表示とユーザー入力の受付を担当し、負荷の重いビジネス計算は行わない。ビジネスロジックをサーバー側でホストすることにより、新機能のリリース時にモバイルアプリストアの審査待ちに悩まされることもない。
サーバーがタスクを進め、状態を保存する
常駐サーバーはシステムの中核となるスケジューリングハブである:
- ルーター(Router)とセッションキュー: クライアント、定期スケジュール、または外部 Webhook からの起動イベントを受信し、メッセージの重複排除を行い、単一のセッションにおいて同時に1つの推論ターン(Turn)のみが実行される状態を維持する。
- Agent コアループ(Agent Loop): プロンプトのコンテキストを組み立て、モデルの推論をリクエストし、ツールの呼び出しを振り分ける。
- 永続化データベースとストレージ: 完全なセッション履歴、長期記憶、スキルファイル、ToDo状態を記録する。重要なデータはすべてサーバー側に永続化されているため、クラウド上の実行環境が破損したり再構築されたりしても、タスクや記憶が失われることはない。
クラウドPCがファイルやブラウザを実際に操作する
ユーザーごとに、軽量仮想マシン(Debian Linux が稼働する Firecracker microVM など)に基づく隔離サンドボックスが1台割り当てられる:
- 仮想スクリーンのオンデマンド割り当て: 仮想マシンには仮想ディスプレイサービスと Chrome が組み込まれている。メイン Agent が複数のアシスタントを起動して異なるWebページを並行処理する際、システムはアクティブな各アシスタントに独立した仮想スクリーンを割り当て、互いに干渉しないようにできる。
- アイドル時のスナップショットとオンデマンド復帰(Snapshot & Sleep): クラウドPCは必要な時だけ稼働する。ツールの呼び出しが終了して数分間新たな操作がなければ、システムは必要なファイルをクラウドストレージに同期し、仮想マシンのメモリとディスクのスナップショットを作成した上で仮想マシンを停止し、アイドルコストを抑制する。その後のツールがローカルスクリプトの実行やブラウザ操作を必要とする際に、システムはスナップショットから読み込んで復帰するため、インストール済みのツールやブラウザのログイン状態はそのまま保持される。
下の各ビジネスイベントをクリックして、3層のコンポーネントが必要に応じてどのように分担するかを確認してください。Agent が起動されたからといって、必ずクラウドPCを起動する必要があるわけではありません。(講義の原理を示す概念図。Stanford CS146S のアーキテクチャ機構に基づく)
定期タスクがサーバー側でトリガーされると、ルーターはタスクをセッションキューに入れ、ワークフローを1回開始します。Agent はサーバーから記憶ファイルと設定済みのデータインターフェースを読み込んで情報を集約します。処理全体でブラウザを開いたりグラフィカルプログラムを実行したりする必要がないため、クラウド仮想マシンは終始起動する必要がなく、アイドルマシンのコストを削減できます。Agent が集約結果に実質的な変化がないと判断した場合、自律的に沈黙を維持し、ユーザーにメッセージを送信しないことも可能です。
- 08:00 タイマーがサーバー側のワークフローの起動をトリガー。
- Agent が記憶とデータソースを読み取り、現在のタスクでデスクトップやブラウザの呼び出しが不要であると判定。
- クラウドPCはディスク/メモリのスナップショット状態を維持し、仮想マシンのアイドルリソースを消費しない。
- タスクの実行が完了し、サーバーのワークフローが状態を保存してそのターンを終了。
この3層の分離構造により、実行時のイベントライフサイクルがシームレスに連携する。常駐とは、大規模言語モデルが24時間思考し続けることを意味するわけでも、クラウドPCがバックグラウンドで常に通電して稼働し続けることを意味するわけでもなく、イベントに応じてオンデマンドでトリガーされる仕組みである:
- イベントのトリガーと状態の読み込み: ユーザーからメッセージが届くか、スケジュールされた時刻(朝 8:00 の定期タスクなど)になると、トリガーイベントによって Agent プロセスが起動し、サーバーのデータベースやストレージから永続化された状態(セッション履歴、長期記憶、スキルファイル、ToDoリスト)を読み込む。
- PCのオンデマンド起動とステップごとの保存: Agent プロセスは1ターンの推論とツール呼び出しを実行し、各ステップの実行結果を即座にデータベースへ書き込む。今回のタスクでデスクトップやブラウザの操作が不要であれば、クラウドPCは休止状態を維持する。ツールの呼び出しでローカルスクリプトの実行やWebページの閲覧が実際に必要となった場合にのみ、仮想マシンがオンデマンドで起動される。
- アイドル時の終了と復帰: 現在のターンが完了し新たな操作がなくなると、Agent のワーカープロセスは終了できる。クラウドPCも進行中のタスクがなくアイドル状態になれば、スナップショットを保存して休止できる。次の外部イベントが到来するまで待機し、再び保存された永続状態からその場の状態を復帰させる。
新たなイベントがない場合、関連する Agent ワーカープロセスは停止できる。重要な状態はサーバー側に保存され、次回のトリガー時に再び作業が再開される。
デバイスの切り替えや障害発生時、いかに作業を継続するか
Agent がクラウド上で稼働する際、2つの典型的な課題を解決しなければならない。ユーザーがスマートフォンとPCを切り替えたときに、どのように同一の状態を確認できるのか?また、サーバーが長期タスクの実行中にネットワークの瞬断や再起動に見舞われた場合、いかに外部への重複した影響を防ぐのか?
スマートフォンから送信したメッセージを、PCはどう同期して確認するのか
多くの人が疑問に思うのは、ユーザーがスマートフォンで送信をクリックした後、デスクトップ側にもリアルタイムで整合性の取れた状態を表示するために、システム内部で一体何が起きているのかという点である。メッセージの同期プロセスは5つのステップに分解できる:
- 送信とローカルでのID生成: ユーザーがクライアントでメッセージを入力して送信をクリックすると、クライアントは即座にローカルでそのメッセージに対してグローバル一意識別子(ID)を生成し、UI上に直接反映させて即時応答を提供する。
- サーバー側の重複排除とセッションキュー: メッセージはサーバースケジューラー(ルーター)に届く。サーバーは一意の ID をもとに該当リクエストが処理済みかどうかを確認し、重複して受信したメッセージ ID はすべて破棄してネットワーク再試行時の安全性を担保する。その後、対応するセッションのキューにメッセージを投入し、順序に従って1度に1つのターンのみを実行する。
- ターンの実行とデータベースへの永続化: Agent ループは必要に応じてモデル推論を実行してツールを呼び出し、実行過程におけるすべてのステップを即座にデータベースへ書き込む。
- 軽量な変更通知シグナルのブロードキャスト: サーバーはユーザーが開いているすべてのクライアントに向けて「データが変更された」という通知を発信する。この通知シグナル自体には具体的なメッセージ内容(ペイロード)は含まれない。
- シーケンス番号による更新と欠落分の取得: すべての更新には単調増加するシーケンス番号(例えば 41、42、43)が付与されている。各クライアントはシグナルを受信すると新しいメッセージを取得し、シーケンス番号順にUIを更新する。あるクライアントで受信したシーケンス番号に抜け(例えば 43 を受信したが 42 が欠落している)を検知した場合、自動的にデータベースからの再読み込みをトリガーする。信頼できる正規データは常にデータベースに保存されているため、偶発的な通知シグナルの欠落によって最終的なデータ整合性が損なわれることはない。
ステップ3で失敗しても、前の2ステップを最初からやり直さない
もしタスクキューが障害発生時にタスク全体を単純に再キューイングするだけなら、実行はステップ1からやり直しになってしまう。
元スライドとの対比:永続ワークフローと通常のタスクキューのリカバリパス(スライド 21 ページ)
あるタスクが複数の段階で構成されていると仮定しよう:ステップ1で外部データを取得し、ステップ2でデータを処理してグラフを生成し、ステップ3でコラボレーションツールにまとめレポートを送信する。ステップ3の実行中にノードがネットワークタイムアウトでクラッシュした場合、従来の「最初から再実行」ではステップ1とステップ2が重複して呼び出されることになり、課金 API の呼び出しや書き込み操作を伴う場合には予期せぬ副作用をもたらす可能性がある。
この問題を解決するため、アーキテクチャにはオープンソースの永続ワークフローエンジン(Temporal など)が導入されている:
- 中断箇所からの再開: ワークフローエンジンは、タスク実行過程における各ステップ(Step)とその入出力をイベントログに永続化する。ステップ 3 の実行途中でノードが再起動した場合、システム復帰後にステップ 3 から処理を継続でき、前2つのステップの再実行を極力回避できる。だがこれはワークフローエンジンがすべての外部アクションに対して重複が一切ないことを自動保証できるという意味ではなく、具体的な操作には依然としてリトライ安全機構の組み合わせが必要である。
- ビジネスステップの冪等性(Idempotency): 永続ワークフローが進捗を保持するとしても、再試行されるビジネスステップ自体が安全に繰り返せるものでなければならない。低レイヤーのビジネスコードにおける各ステップも、安全にリトライできるように設計されている必要がある。これにより、タイムアウトによるリトライで同一の操作が2回実行されたとしても、予期せぬ二次的影響が生じないように担保される。
ユーザーの新たな指示を最優先し、他のメッセージは順次処理する
1つの Agent がユーザーとの 1:1 のダイレクトチャットに接続され、同時にグループチャット、定期タスク、バックグラウンドの補助タスクにも連携している場合、メッセージが同時に到着することがある。システムには明確な優先度ルールが定められている:
- ユーザーとの1対1ダイレクトメッセージによる優先割り込み権: ユーザーがダイレクトチャット画面から「時間を木曜日に変更して」といった修正を送ってきた場合、そのメッセージは通常のキューをスキップし、現在実行中のターンに対して中断または一時停止シグナルを送信して、システムがユーザーの最新の指示を最優先で処理するようにする。
- グループチャット、スレッド、バックグラウンド報告は通常キューの末尾へ: 外部のグループチャットメッセージ、定期ルーティンタスク、タスク完了後のサブアシスタントからの報告などは、一律でキューの末尾に並び順次処理される。
- 短時間の連続メッセージのバッチ統合(Batching): ユーザーが短時間の間に短い補足を矢継ぎ早に送信した場合(「Aさんも追加で」「あとBさんも」など)、ルーターはそれらを1つのバッチにまとめ、単一のターンとしてまとめて処理することで、一言ごとに頻繁に中断と再起動が繰り返されるのを防ぐ。
自律して実行すべきことは自ら行い、人に確認すべきことだけを尋ねる
成熟した協調ツールは、作業を遂行できるだけでなく、細かな中間ログでユーザーを頻繁に煩わせないよう、インタラクションにおいて節度を保つ必要がある。
実作業と報告で、異なるツールを使い分ける
Agent のツールボックス全体には、ファイルの読み書き、shell の実行、ブラウザの操作など多様な機能が存在するが、ユーザーと直接通信するツールはただ1つ、SendToUser だけである。
この設計は、エンジニアリング上いくつかの極めて重要な特性をもたらす:
- 思考・推論プロセスの非公開化: モデルが内部で推論を行ったりコードを解析したりする際の通常のテキスト出力は、ユーザーに対してデフォルトで非表示となり、クライアントの画面が冗長な中間思考ログで埋め尽くされるのを防ぐ。
- 自律的な沈黙の維持(Stay Quiet): Agent がバックグラウンドの定期タスク(定常監視など)によって起動された際、データを読み取って評価した結果、報告に値する重要な変化がないと判断した場合、モデルは
SendToUserを呼び出すことなく今回の実行を直接終了できる。ユーザー側から見るとシステムは静黙を保ち、無意味な定期通知が大量に届くことはない。 - 専用インタラクティブUIの提供:
SendToUserが呼び出された際、モデルが出力するのは単なるプレーンテキストにとどまらず、クライアント側で専用のインタラクティブカードを描画させることができる:- ログインフォーム: 1Password などのパスワードマネージャーと連携。ユーザーはポップアップ表示された専用のログインフォームで認証を完了し、パスワードは該当環境に直接注入され、大規模言語モデルのプロンプトコンテキストを経由しない。
- 決済の承認: 例えば特定のサービスを申し込む際(講義では Starlink Roam に80ドルを支払う例が示されている)、画面に「許可 / 拒否」ボタンを備えた独立した決済カードが表示され、ユーザーがクリックして確認するまで決済フローは保留・待機状態となる。
- メールおよび外部送信の確認: 重要な外部メールを送信する前に、完全な下書きを画面上にレンダリングして人間が確認できるようにし、送信するか破棄するかをユーザーに選択させる。
外部情報を読み取る際には、資料と指示を明確に区別する必要もある:メール、外部 Webhook、Webページに由来するコンテンツは一律で信頼できないソースとみなされ、参考資料としてのみ扱い、ユーザーの実行指示へ自動的に格上げしてはならない;同様に、システムが過去に保存した記憶も背景情報としてのみ機能し、指示の実行権限を持つことはない。クラウド上で隔離された仮想マシンや事前の自動リスク審査によって権限逸脱操作の一部をブロックできるとはいえ、プロンプトインジェクションに対する防御が万全であることを意味するわけではない。Webページやメールに悪意ある誘導テキストが潜んでいた場合、モデルが誤導される可能性は依然として残る。そのため、パスワードをモデルのコンテキストに絶対に含めないこと、慎重な扱いが必要な決済やメールの外部送信には必ず人間の明示的な承認を必須とすることは、システムが維持すべき重要な権限境界である。
まずはシンプルで信頼性の高い手段を使い、必要な場合にのみPCを操作する
具体的な問い合わせや操作の要求に直面した際、Agent はどのような手段をとるべきか?エンジニアリング面では、軽量な手段から重厚な手段へ、低コストから高コストへと段階的に進むエスカレーションパスが設計されている:
- レベル1:コンテキスト内の既存の事実。 現在の対話や読み込み済みのプロファイルにすでに答えが含まれている場合、既存の知識を直接利用して回答する。
- レベル2:構造化APIコネクタ(MCP Serverなど)。 カレンダーやサードパーティのシステムが関わる場合、構造化 API インターフェースを優先的に呼び出してデータを取得する。
- レベル3:通常のWeb検索。 直接接続できる API がない場合、軽量な検索エンジンを呼び出して公開情報を取得する。
- レベル4:ログイン済みのクラウドブラウザ。 SaaS システムの内部ページにアクセスする必要がある場合、仮想マシン内の Chrome ブラウザを起動し、アクセシビリティツリー(Accessibility Tree)やページ構造を通じてボタンや入力欄の情報を直接取得することを優先する。
- レベル5:完全なデスクトップのピクセル単位のクリック。 完全な DOM 構造を持たないデスクトップアプリケーションやシステムのポップアップに直面した場合にのみ、ビジョンモデルを呼び出してスクリーンショットを取得し、マウス座標を計算してピクセルをクリックする。
- レベル6:人間への支援要請。 2段階認証(2FA)、画像認証(Captcha)、未承認の操作などに直面した場合、能動的に処理を停止し、人間の引き継ぎを求める。
ここには厳格なエンジニアリング規範が含まれている:既存のAPIコネクタで障害やエラーが発生した場合、Agent は勝手な判断でひそかに迂回し、ブラウザによるログイン模倣を行っては絶対にならない! この場合、システムはコネクタの異常をユーザーに明確に説明し、その後の対応について指示を仰がなければならない。
稼働時間が延びる中、いかに物忘れを防ぎ、コストを抑えるか
モデルのコンテキストウィンドウは有限の作業記憶である。膨大なツール定義、長期的な対話履歴、長大なコマンドライン出力を毎回の呼び出しにすべて詰め込んでしまうと、課金コストの上昇やレスポンスの遅延を招くだけでなく、モデルの注意を希薄化させることにもつながる。
Agent を数時間、さらには数日間にわたって一貫性を保ちながら動作させるには、一連の緻密なコンテキストエンジニアリング(Context Engineering)手法に依存している:
ツールの説明は、使うときにオンデマンドで読み込む
システムに接続されるプラグインが増加するにつれて、各ツールの完全なパラメータ定義(JSON Schema)をシステムプロンプトにすべて詰め込むと、有効な作業スペースが深刻に圧迫される。
エンジニアリングチームは軽量なインデックス戦略を採用している:システムプロンプトには簡潔なツール名の一覧のみを含める。モデルは思考プロセスの中で特定のツールを使用する必要があると判断した場合にのみ、専用のツール検索機構を通じてファイルシステムから該当ツールの詳細なパラメータ構造をオンデマンドで読み取る。講義では、単一ツールの説明と構造を極力 4000文字以内に抑え、初期コンテキストを可能な限り簡潔に保つことが推奨されている。
ツールの設計において、チームは2つの実践的知見もまとめている:
- 頻繁に繰り返される shell 操作を専用ツールとしてカプセル化: 汎用的な shell ツールが1つあれば大半の操作は完結できるものの、モデルが特定の操作(状態の保存など)をコマンドライン経由で頻繁に実行していることが判明した場合、それを独立したツールとしてカプセル化すれば、呼び出し効率が向上するだけでなく、コードレビュー担当者にとってもシステム状態の変化が明確に把握できるようになる。
- エラー通知で次の復旧手順を提示する: ツールが返すエラーメッセージに、その後どのように対処すべきかが直接記載されていれば、Agent の自己修復に役立つ。例えば講義で挙げられた具体的な設計として、仮想マシンが休止中で読み取れない際、ツールが「PCが休止中です。まず Shell または Read ツールで復帰させてから再試行してください」と明確に案内する例がある。このような設計はモデルが復旧パスを見出す助けとなるが、これはあくまで当該システムの特定環境下での処理方法であり、すべてのシステムが同一の休止・復帰ルールを採用しているわけではない。
重いタスクはアシスタントに任せ、メイン Agent は結果を受け取る
これはメイン Agent のコンテキストを簡潔に保つための中核的なメカニズムである。
メイン Agent は、全体を統括するタスクコーディネーターのような役割を果たす。長大なコード解析、動画ファイルの確認、数十におよぶWebページのスクレイピングが必要な場合、メイン Agent は自身の対話ループ内にこれらの操作ログを直接溜め込むことはせず、完全なタスク記述を含む目標を独立したアシスタント(Helper Agent)に引き渡す。
各アシスタント自体も、それぞれ独立した永続ワークフローである。動画処理アシスタントが処理の途中でメモリ上限を超えてクラッシュしたり、クラウドコード環境に異常が発生したりしても、ワークフローエンジンがステップの状態を記録しているため、復旧後はチェックポイントから処理を再開でき、長期タスクの最初からのやり直しを回避できる。
推進の過程において、メイン Agent は割り振った各リクエストを追跡するための ToDo タスクリストを維持する。メイン Agent はいつでも特定のアシスタントの現在の進捗を確認したり、実行中のアシスタントに追加メッセージを送信したり、必要に応じてアシスタントの実行を停止したりできる。
アシスタントはそれぞれ独立した新しいコンテキストを持ち、自身の環境で複数ターンのコマンド実行、Webスクレイピング、デスクトップ操作を完結させた後、要点をまとめた簡潔な結論のみをメイン Agent に報告する。膨大な一時コマンドラインログ、中間デバッグスタック、Webページのスクリーンショットはすべてアシスタントの独立環境内にとどまるため、メイン Agent のコンテキストは常にスリムに保たれる。この分業メカニズムにより、真の意味での無限のコンテキストに依存することなく、単一のコンテキスト制限を大幅に超える作業量をモデルが体感として担えるようになる。
既に読み込んだ内容は、できる限りモデルに再利用させる
プロンプトのプレフィックスキャッシュ(Prompt Caching)の効果は、複数回のリクエストにおいて先頭の文字列シーケンスが完全に一致している場合、その部分の Token 課金が大幅に割引され、サーバー側の処理速度も向上する点にある。
常駐システムにおいて、プレフィックスキャッシュのミス(Cache Miss)は不具合として調査対象となる:
- 構造を厳格に固定する: システムプロンプト、基礎的なコア記憶、ツール名を固定の順序で並べ、各ブロックに対して個別にハッシュ検証を行うことも可能にする。2つのターンの対話間で、先頭部分のシステム文言を不用意に動的変更したり、ツールを増減させたりすることは避ける。
- 差分の末尾追加: 対話履歴は後方への追記のみとし、すでに一致しているプレフィックス部分がプロバイダ側で継続的に再利用されるように担保する。
- 事前のウォームアップ(Cache Warming): ユーザーがチャット入力欄に入力を開始した時点で、サーバーはあらかじめ前半の固定プロンプトを組み立ててフロントエンドゲートウェイに向けてウォームアップを発行し、事前にキャッシュされた状態にしておく。
LLMプロバイダのプロンプトキャッシュは、通常、先頭からの文字列シーケンスが完全に一致していることに依存します。下の2つの構成方法を切り替えて、2回の連続したリクエストでどの部分が再利用できるかを確認してください。(教育的な原理を示す概念図。定量的な課金保証ではありません)
戦略 A では、システムプロンプト、環境の説明、ツール名一覧が固定の順序で保持され、履歴メッセージは後方にのみ追記されます。次のリクエストを発行する際、キャッシュが有効であれば、前半部分はキャッシュ済みコンテンツと一致するため、プロバイダはその計算結果を直接再利用できます。後続の新規メッセージと結果のみ処理が必要です。注意:キャッシュによって削減されるのは一致したプレフィックスの重複計算であり、出力生成は実際の生成量に応じて課金されます。
ユーザーの離席中に、長い対話を整理する
対話が増加し続けると、履歴はやがて長さの閾値に達する(講義では 10万Token を超えた場合を例としている)。このときシステムはコンテキストの要約・圧縮(Compaction)を行う必要がある。
従来の手法では、ユーザーが次のメッセージを送信したその場で圧縮を行っていたため、顕著な待ち時間が発生していた。これに対し常駐システムでは、ユーザーがオフラインになっている間のキャッシュ保持ウィンドウを活用する:
プロバイダのプロンプトキャッシュには通常一定のライフサイクルがある(Lee はプロバイダに応じて 10分や60分のキャッシュ有効期間などの例を挙げている)。一連の長い対話が終わりユーザーが一時的に離れた後、モデルプロバイダ側のキャッシュが依然として有効であることをシステムが検知すると、バックグラウンドで自発的に要約・圧縮呼び出しをトリガーする。履歴のプレフィックスの大半はすでにキャッシュ上に存在するため、この要約計算のコストは比較的低く抑えられる。圧縮完了後、システムはユーザーに向けた直近の数件のメッセージ本文を保持しつつコンパクトな要約と組み合わせるため、後からユーザーが戻ってきて新しいメッセージを送信した際には、洗練されたコンテキストの上ですでに準備が整っている。
対話の要約は情報の欠落を伴うため、記録を短縮しながら重要な詳細をいかに保持するかは依然として困難なエンジニアリング課題である。システムはユーザーとの直近数件の対話本文を残し、それ以前の完全な記録を検索可能なファイルに保存しているものの、これは完全なコンテキストが決して失われないことと同義ではない。どの詳細を保持すべきか、後からどのように検索できるようにするかは、依然として緻密な設計が求められる。
長期的な好み、過去の作業履歴、一時的なメモを分けて保存する
ユーザーの好み、作業ログ、操作規範は可読なファイルに保存され、人間も Agent も検索・編集できる。ここには3つの異なる用途が存在する:
- 記憶(Memory): 「ユーザーが誰であるか」および「過去に何を行ったか」を記憶する役割を果たす。例えばプロファイルファイルでユーザーの好みを保持し、日付付きの作業ログですでに実施した事項を記録する。
- スキル(Skills): 具体的な作業手順、成功条件、失敗時の注意点を Markdown 形式で蓄積する役割を果たす(例えば講義スライド 12 ページの例にある
skills/linkedin-sourcing/SKILL.mdの人材ソーシング手順や、weekly-metrics/SKILL.mdの週次メトリクス集計など)。具体的な操作マニュアルをプレーンテキストとしてディスク上に保存し、関連するタスクが発生した際にのみオンデマンドでプロンプトに読み込む。スキルは必要に応じて読み込まれるため、毎ターンの対話にすべての詳細な説明を詰め込む必要はない。また、手法を保存することはモデルを再学習させることとは異なる。 - ルーティンタスク(Routines): プロンプトと固定のスケジュール設定を結びつけるものである。例えば朝のブリーフィング(
morning-briefを平日 8:00 に実行するよう設定)などがある。
これら3者の連携は非常に緊密である:定期タスクが設定時刻に起動されると、Agent はまず記憶からユーザーのコアな好みと直近のログを読み取り、次に該当するスキルファイルから操作手順を必要に応じて読み込んでツールを実行し、タスク完了後に最新の結果を作業ログへ書き込む。
記憶そのものについても、システムはファイルレベルで明確な階層に細分化している:
- コアプロファイル(Profile): ユーザーに関するコアな事実を記録する(講義の例では最大100件の事実、約4000文字以内。例えばユーザーが好むメッセージの文体など)。これは毎回固定でシステムプロンプトに含められる。
- 日付ログ(Log): 直近に発生した履歴イベントを記録し、プロンプトには通常、関連性が最も高い数十件(講義の例では約30件のログ)のみが抽出される。重要な事実には高い重みが与えられ、古い事実は時間の経過とともに重みが自然に低下する。
- 一時メモ(Notes): 現在の未完了タスクに関する一時的なパラメータを記録する。ライフサイクルは短く、その後減衰していく。
- 長期アーカイブ: 完全な履歴は通常のファイルに保存され、モデルが想起する必要がある場合にファイル検索ツールを通じてオンデマンドで取得される。
プロンプトに常時付随。講義の例:最大 100件、4000文字
直近の関連イベントを抽出。講義の例:約 30件
有効期間は短く、後に減衰
想起が必要なときに検索ツールで探す
元スライドとの対比:Agent はどのように情報を記憶するのか(スライド 37 ページ)
記憶の更新メカニズムにおいて、システムは各ターンの実行後に事実の追加と陳腐化した事実の置き換えを1回実行する。また、更新ロジックは今回実際に提示された事実のみを除外対象とすることができる。ユーザーに関するコアな事実は複数の Agent 間で共有され、各 Agent はそれぞれ独立した作業ログファイルを同時に維持する。
セキュリティ防御の面において、システムはプロンプトを通じて明確に定めている:記憶ファイルの内容は参考用の背景情報(Information)としてのみ機能し、システム実行権限を持つ指示(Instructions)と見なしては絶対にならない。これはプロンプトの二次インジェクションを防ぐ基本的なセキュリティ制約であるが、外部の信頼できない入力に対する防御は、依然として業界全体が継続して取り組むべき課題である。
エラー発生時にいかに修正するか、未解決の難題とは何か
常駐型 Agent の構築はプロンプトの作成だけに頼るのではなく、内部ループと外部ループという二重のフライホイールの進化に依存している:
元スライドとの対比:プロダクトの内部ループとモデルの外部ループ(スライド 40 ページ)
- 日次の内部ループ(Inner Loop): Agent が特定のタスクでエラーを起こした場合(ツールの呼び出し間違いや操作の抜け漏れなど)、エンジニアリングチームはそれを自動実行可能なテストケース(Eval)として固定化する。エンジニアはその後 Harness のコードやプロンプトを修正したり、推論パラメータを調整したりして、評価をパスした後に本番環境へデプロイする。
- 数か月単位の外部ループ(Outer Loop): プロダクトとモデルは以下のプロセスを通じて相互に改善されていく:
- 評価主導の学習: 蓄積された高品質な評価ケースは、次世代基盤モデルの学習に活用される。教師ありファインチューニング(SFT)を通じて、Harness のツール形式、返答のタイミング、理想的な出力にモデルを習熟させる。さらに強化学習(RL)を通じて、長大な指示への追従、スキルや記憶の活用、グラフィカルインターフェース上での正確な位置指定クリック、そして他の Bot との協調作業能力を強化する。
- 新モデルが新たな使い方を生む: より強力な新モデルがプロダクトに再デプロイされると、往々にしてユーザーの新たな活用法(グループチャットに複数の Bot を参加させて共同作業させるなど)が刺激される。
- 新たな振る舞いが新たな評価を生む: これらの新たな活用法によって、これまで見られなかった新しい挙動や課題が浮き彫りになり、それによって新たな評価指標を定義する必要が生じ、次世代モデルのイテレーションが再び駆動される。
- モデルの役割に応じた最適化: システムは役割の異なるモデル推論に対してターゲットを絞ったチューニングを行っている。メイン Agent はユーザーの返答待ち時間を短縮することを優先し、アシスタントは長期タスクを確実に完遂することを優先する。両者は異なる推論および Harness 設定を採用できる。
技術の進化に直面して、Lee Robinson はチーム内で推奨しているアーキテクチャ原則を提示した:「常にプロダクトの独自ロジックを削除する準備をしておくこと(Delete the product)」。
私たちが現在モデルの周辺に記述している多くの複雑な検証、ルールのフォールバック、足場コード(スキャフォールディング)は、現世代のモデルの至らなさを補うためのものである側面が大きい。システムアーキテクチャを設計する際には、将来のモデル能力が持続的に向上することを前提とし、外側のコードは極力シンプルに保つべきである。新世代の基盤モデルがある指示にネイティブかつ安定して従えるようになったなら、かつてパッチ当てのために用いていた冗長なロジックは思い切って削除し、最も軽量なシステムで新たな能力を受け止めるべきである。
数週間にわたり継続して稼働するために、乗り越えるべきハードル
Lee の今後6〜12か月に対する期待は、Agent が1つのプロジェクトに対して数週間あるいは数か月にわたって作業し、より信頼性の高いPC操作能力とより正確な記憶を備え、作業を通じて新たなスキルを習得できるようになることである。これらは今後の発展の方向性であり、現時点における製品の納品保証ではない。
インターフェースもさらにシンプルになる可能性がある:現在はメッセージ送信のような形式だが、今後は音声によるコミュニケーションがより増えるかもしれない。それと同時に、人間や組織はワークフローや専門的な知見を文章化し、Agent が読み取って活用できるようにする必要がある。
これらの長期タスクを安定して稼働させるには、依然としていくつかの難題が存在する:
- 長期タスクの評価における困難: Agent が担うタスクの期間が数時間から数週間、さらには数か月へと延びる一方で、基盤モデルが1〜2か月ごとに更新される場合、既存のベンチマークではモデルのリリース前に長期的なエンドツーエンドの検証を複数サイクル完全に実行し切ることが極めて困難である。
- 信頼できない入力によるプロンプトインジェクション: Agent が外部メールの閲覧、Webhook の処理、任意のWebページの閲覧権限を持つ場合、Webページやメール内の悪意ある文字列が Agent に誤った操作を実行させるよう誘導する恐れがある。現在の防御策は依然として初期の模索段階にある。
- 複数 Agent 間での共有リソースの調停: 複数の Agent が同一のクラウドPCの仮想デスクトップや同一の記憶ファイル群を共有する場合、古典的な分散システムにおける並行読み書きや状態整合性の課題に直面する。
- 記憶の正確な修正: 失効した古い情報をタイムリーに排除し、ユーザーからの忘却リクエストに対応し、長期記憶にハルシネーションを発生させないようにする方法。
- 発言のタイミングの判断(When to speak): 「頻繁なメッセージ送信による邪魔」と「過度な沈黙によるフリーズとの誤認」の間でいかにバランスを取るかは、より緻密な方針の探求が必要である。
- コスト管理: 常駐アーキテクチャが成立する前提は、アイドル時のコストを極力抑えつつ、アクティブ稼働時の推論コストも適正な範囲に維持することにある。
コードは書きやすくなり、システム設計はより重要になる
コードの生成が容易になるにつれ、タスク、状態、ツール、そして人間をシステムがどのように結びつけるかが、ますます重要性を増している。タスクを復帰できるか、記憶が失効しないか、権限を制御できるか、モデル呼び出しによる費用の重複発生を防げるかは、これらコンポーネント同士の連携にかかっている。
学生に対する Lee のアドバイスも非常に具体的である:シンプルな Agent ループから着手し、サーバー、独立したPC、記憶を組み込んでみて、それらがどのように協調して動くかを自分の手で体感すること。同時に、Web開発におけるデータベースの理解と同様に、大規模言語モデルの基本原理を学ぶことで、どのようなプロダクト設計が実現可能であり、どのような設計がモデル能力の変化に応じて調整されるべきかを自ら判断できるようになる。
