
Project89で次世代Agentフレームワークを見た
TechFlow厳選深潮セレクト

Project89で次世代Agentフレームワークを見た
Project89は、ゲーム開発向けの高性能エージェントフレームワークの設計において、全く新しいアプローチを採用している。
著者:0xhhh
結論から述べると、@project_89はゲーム開発向けの高性能エージェントフレームワークを、全く新しいアプローチで設計しています。これは現在一般的に使われているエージェントフレームワークと比べて、よりモジュール化が進んでおり、パフォーマンスも優れています。
この記事の執筆には非常に長い時間をかけました。誰でも理解できるように、このフレームワークが従来のエージェントフレームワークと比較してどのようなアーキテクチャ上の進化を遂げたのかを説明しようと試み、何度も書き直した末にこの形になりました。ただし、一部の技術的な内容については依然としてわかりやすく言い換えることに成功できていません。記事の改善に関するご意見があれば、ぜひコメントをお寄せください。
開発者背景
本稿は技術ブログであるため、まず創設者の技術力について見てみましょう。
Founderはproject89を始める前に、以下のプロジェクトに取り組んでいました。https://github.com/Oneirocom/Magick。これはAIを使ったプログラミング支援ソフトウェアであり、shaw氏はそのプロジェクトにおいて4番目に貢献度の高い開発者です。彼の経歴にもこのプロジェクトは記載されています。



左上:project89の創設者、右下:ai16zのshaw
ここからは、project89が提供する高性能エージェントフレームワークについて紹介します。
https://github.com/project-89/argOS
一、なぜECSでエージェントフレームワークを設計するのか
ゲーム分野における応用例を見ると、現在ECSアーキテクチャを採用しているゲームには以下のようなものがあります。ブロックチェーングーム:Mud、Dojo。伝統的ゲーム:オーバーウォッチ、スターシティズンなど。また、主流のゲームエンジンもUnityのようにECS方向へ進化しています。
ECSとは何か?
ECS(Entity-Component-System)は、ゲーム開発およびシミュレーションシステムで広く使われるアーキテクチャパターンです。データとロジックを完全に分離することで、大規模かつ拡張性のある環境下でも効率的に多数のエンティティとその振る舞いを管理できます。
-
Entity(エンティティ) • ID(数値または文字列)にすぎず、データやロジックを含まない。 • 必要に応じてさまざまなコンポーネントを追加することで、属性や能力を与えることができる。
-
Component(コンポーネント) • エンティティの具体的なデータや状態を保持する。
-
System(システム) • 特定のコンポーネントに関連するロジックを実行する責任を持つ。
エージェントの行動を具体例に挙げてこの仕組みを理解しましょう。ArgOSでは、各エージェントを一つのエンティティとして扱います。このエンティティは複数のコンポーネントを登録でき、たとえば下図では、このエージェントは以下の4つのコンポーネントを持っています:
- Agent Component:エージェント名、モデル名などの基本情報を格納
- Perception Component:外部からの知覚データを格納
- Memory Component:エージェントの記憶データ(過去の行動など)を格納
- Action Component:実行すべきアクションのデータを格納
Systemの処理フロー:
- 例えばゲーム内で、目の前に武器があることを知覚した場合、Perception Systemが実行され、該当エージェントエンティティのPerception Component内のデータが更新される。
- 次にMemory Systemが起動し、Perception ComponentとMemory Componentを呼び出し、知覚データを永続化されたデータベースに保存する。
- Action SystemがMemory ComponentとAction Componentを呼び出し、記憶から周囲の環境情報を取得し、適切な行動を最終的に実行する。
- こうして各コンポーネントのデータが更新されたエージェントエンティティが得られる。つまり、Systemは特定のコンポーネントに対してどのような処理ロジックを適用するかを定義する役割を担っている。

project89の世界には多種多様なタイプのエージェントが存在します。中には前述の基本機能に加えて「計画立案」能力を持つエージェントもいます。そのような場合は、以下の図のようになります。

Systemの実行フロー
しかし実際のSystem実行フローは、「Perception Systemが終了したらMemory Systemを呼び出す」といった従来型の直接的な呼び出し関係ではありません。異なるSystem同士には呼び出し関係が存在せず、それぞれが決まった周期ごとに独立して実行されます。たとえば:
- Perception Systemは2秒ごとに実行され、外界からの知覚情報を更新し、Perception Componentに反映
- Memory Systemは1秒ごとに実行され、Perception Componentからデータを抽出してMemory Componentに読み込む
- Plan Systemは1000秒ごとに実行され、受け取った情報に基づいて目標達成のために最適な計画が必要かどうかを判断し、結果をPlan Componentに記録
- Action Systemも2秒ごとに実行され、外界の情報に即座に対応できるようにする。また、Plan Componentに更新があれば、それに基づいてAction Componentを更新し、最初のアクションを調整
ここまで述べてきた内容は、私の理解に基づきArgOSのアーキテクチャを大幅に簡略化して説明したものです。これにより皆さんの理解を助けられればと考えました。次に、実際のArgOSについて見ていきましょう。
二、ArgOS System アーキテクチャ
ArgOSでは、エージェントがより深い思考を行い、複雑なタスクを実行できるようにするために、多くのコンポーネントとシステムが設計されています。
さらに、ArgOSではSystemを「三つの階層」(ConsciousnessLevel)に分類しています。
1)意識的(CONSCIOUS)システム
- RoomSystem、PerceptionSystem、ExperienceSystem、ThinkingSystem、ActionSystem、CleanupSystemを含む
- 更新頻度は高め(例:10秒ごと)
- 環境知覚、即時思考、アクション実行など、「リアルタイム」あるいは「顕在意識」レベルの処理に近い
2)潜在的(SUBCONSCIOUS)システム
- GoalPlanningSystem、PlanningSystem
- 更新頻度は比較的低め(例:25秒ごと)
- 定期的に目標や計画の確認・生成を行う「思考」ロジックを処理
3)無意識(UNCONSCIOUS)システム
- 現時点ではまだ使用されていない
- 更新頻度はさらに遅い(例:50秒以上)
つまり、ArgOSでは各SystemをConsciousnessLevelに応じて分類し、どのタイミングで実行するかを規定しています。
なぜこのような設計なのか? それは、ArgOSにおける各System間の関係が極めて複雑だからです。下図をご覧ください。

- PerceptionSystemは外界や他のエンティティから「刺激」(stimuli)を収集し、エージェントのPerceptionコンポーネントに更新する。刺激の変化が顕著かどうかを判断し、安定性や処理モード(ACTIVE/REFLECTIVE/WAITING)に基づいて適切に更新を行う。その後、ExperienceSystemやThinkingSystemなどの後続処理に「現在の知覚情報」を提供する。
- ExperienceSystemは、PerceptionSystemが収集したStimuliをより抽象的な「体験」(Experience)に変換する。LLMまたはルールロジック(extractExperiences)を呼び出して新しい体験を識別し、Memoryコンポーネントに保存する。重複除去、フィルタリング、検証を行い、eventBusを通じて「experience」イベントを他のシステムや外部リスナーに送信する。
- ThinkingSystemはエージェント自身の「思考」システムである。Memory、Perceptionなどのコンポーネントから現在の状態を取得し、generateThought(...)を介してLLM/ルールロジックを使って「思考結果」(ThoughtResult)を生成する。思考結果に基づき、以下のような処理を行う可能性がある:
- Memory内のthoughts(思考履歴)を更新
- 新しいアクションをトリガー(Action.pendingAction[eid]に設定)
- エージェントの外見(表情、姿勢など)を変更し、関連するStimulusを生成して他のエンティティに「変化」を知らせる
- ActionSystemは、エージェントのAction.pendingActionが空でない場合、runtime.getActionManager().executeAction(...)を介して実際にアクションを実行する。実行後、結果をAction.lastActionResultに書き戻し、部屋や他のエンティティに通知する。また、CognitiveStimulus(認知刺激)を生成することで、後続のシステムが「アクションが完了した」こと、あるいはそれを記憶に取り込めるようにする。
- GoalPlanningSystemは、Goal.current[eid]リスト内の目標の進捗を定期的に評価したり、外部または内部記憶に大きな変化がないか(detectSignificantChanges)をチェックする。新たな目標が必要になったり、目標の調整が必要な場合、generateGoals(...)を介して生成しGoal.current[eid]に書き込む。進行中の目標の進捗も更新し、達成または失敗条件を満たせばステータスを変更し、対応するPlanに達成/失敗信号を送る。
- PlanningSystemは「既存の目標」(Goal.current[eid])に対して実行計画を生成または更新する。ある目標に紐づくアクティブな計画が存在しない場合、generatePlan(...)を介して複数のステップからなる実行ルートマップを生成し、Plan.plans[eid]に書き込む。また、目標が達成または失敗した場合には、関連するPlanのステータスを更新し、対応する認知刺激を生成する。
- RoomSystemは部屋(Room)関連の更新を処理する。
- 部屋内の在室者リスト(occupants)を取得し、各エージェントに対して「外見(appearance)」刺激を生成。他のエンティティがその外見や動作を「見る」ことができるようになる。
- 部屋の環境Stimulus(たとえば「部屋の雰囲気」情報)を作成し関連付ける。エージェントが特定の空間にいる場合、その空間を知覚している他のエンティティがその外見の変化を認識できるようにする。
- CleanupSystemは定期的にCleanupコンポーネントが付与されたエンティティを探し出し、削除する。不要になったStimulusやその他のオブジェクトを回収し、ECS内に大量の無効なエンティティが残らないようにする。
- 例:「物体を見る」→「行動を実行する」までの1サイクル
以下のシナリオ例では、各Systemが1ラウンド(または数フレーム)内でどのように協調して一連の処理を完遂するかを示します。
- 準備:ワールド内にエージェント(EID=1)が存在し、「Active」状態で部屋(EID=100)にいる。この部屋に新たにアイテム「MagicSword」が出現し、対応するStimulusが生成される。
- PerceptionSystemが「MagicSword」の出現を検知し、エージェント(1)に対してStimulus(type="item_appearance")を生成し、Perception.currentStimuli[1]に追加する。前回のStimuliハッシュと比較し、「顕著な変化あり」と判定し、エージェントのProcessingStateを再び「ACTIVE」モードに切り替える。
- ExperienceSystemは、エージェント(1)のPerception.currentStimuliが空でないことを検知し、「Sword appears」などの情報を抽出して1つ以上の新規Experience(type: "observation")を生成する。これをMemory.experiences[1]に保存し、「experience」イベントを発行する。
- ThinkingSystemはMemory、Perceptionなどの状態情報を読み取り、generateThoughtを呼び出す。「私はMagicSwordを見た。拾って、何ができるか試してみよう…」という思考が生まれる。この思考結果には実行予定のアクションが含まれる:{ tool: "pickUpItem", parameters: { itemName: "MagicSword" } }。ThinkingSystemはこのアクションをAction.pendingAction[1]に書き込む。もし外見に変更がある場合(例:「好奇心旺盛な表情」)、Appearanceを更新し、視覚刺激を生成する。
- ActionSystemはAction.pendingAction[1] = { tool: "pickUpItem", parameters: ... } を検知する。runtime.getActionManager().executeAction("pickUpItem", 1, { itemName: "MagicSword" }, runtime)を呼び出して「拾う」アクションのロジックを実行する。結果として{ success: true, message: "あなたは魔法の剣を拾った" }を得て、Action.lastActionResult[1]を更新し、「action」イベントを部屋(100)にブロードキャストする。同時に認知刺激(type="action_result")を生成し、Memoryに書き込むか、次のターンでThinkingSystemが捕捉できるようにする。
- GoalPlanningSystem(エージェントが目標を持っている場合)は定期的に目標の進捗を評価する。もしエージェントの目標が「強力な武器を手に入れる」であり、MagicSwordを入手済みであれば、その目標を「達成」とマークする可能性がある。また、「部屋に新しい物体が出現した」という変化がエージェントの目標に影響を与える場合、detectSignificantChangesに基づき新たな目標を生成したり、古い目標を放棄したりする。
- PlanningSystem(関連する目標がある場合)は、「強力な武器を手に入れる」といった達成済みまたは新しく生成された目標について、新たな計画が必要か、既存の計画を更新する必要があるかをチェックする。達成済みであれば、関連するPlanの[status]を"completed"に設定。あるいは、目標が次の段階(「魔法剣を研究する」)に進む場合、さらに多くのステップを生成する。
- RoomSystem(毎フレームまたは毎ラウンド)は、部屋(100)内のOccupantsリストや可視エンティティを更新する。エージェント(1)の外見が変化した場合(例:Appearance.currentAction = "holding sword")、他の同室のエージェント(Agent2、Agent3)が「agent1が剣を手にした」ことを認識できるよう、「appearance」視覚刺激を新たに作成する。
- CleanupSystemは、マークされた(Cleanup)エンティティや刺激を削除する。拾取後に「MagicSword」のStimulusが不要になった場合、CleanupSystem内で対応するStimulusエンティティを削除できる。
これらのシステムの連携により、AIエージェントは以下の流れを実現します:
• 環境変化の知覚(Perception) → 内部経験への記録または変換(Experience) → 自己思考と意思決定(Thinking) → 行動実行(Action) → 目標と計画の動的調整(GoalPlanning + Planning) → 環境との同期(Room) → 不要エンティティの即時回収(Cleanup)。
三、ArgOS全体アーキテクチャの解析
1. コアアーキテクチャの階層構造

2. コンポーネント(Component)の分類
ECSにおいて、各エンティティ(Entity)は複数のコンポーネント(Component)を持つことができます。システム内での性質やライフサイクルに基づき、コンポーネントはおおむね以下のように分類できます。
- コアアイデンティティ系 (Identity-Level Components)
- Agent / PlayerProfile / NPCProfile など
- エンティティを一意に識別し、主要なキャラクター情報やユニット情報を格納。通常はデータベースに永続化される。
- 行動・状態系 (Behavior & State Components)
- Action, Goal, Plan, ProcessingState など
- エンティティが現在行っていることや目標、外部コマンドや内部思考に対する反応状態を表す。
- pendingAction, goalsInProgress, plans, 思考やタスクのキューなどが含まれる。
- 中短期的な状態が多く、ゲームラウンドやビジネスサイクルに応じて動的に変化する。
- データベースへの永続化の有無はケースによる。中断後の再開を希望する場合は、定期的にDBに書き込まれる。
- 知覚・記憶系 (Perception & Memory Components)
- Perception, Memory, Stimulus, Experience など
- エンティティが外部から知覚した情報(Stimuli)、およびそれらから抽出された体験(Experiences)を記録。
- Memoryには会話履歴、出来事の記録など大量のデータが蓄積されることが多く、永続化が必要。
- Perceptionはリアルタイムまたは一時的な情報が多く、短期間のみ有効。必要に応じて重要な知覚イベントのみDBに保存。
- 環境・空間系 (Room, OccupiesRoom, Spatial, Environment, Inventory など)
- 部屋、環境、位置、アイテムコンテナなどの情報を表す。
- Room.id、OccupiesRoom、Environment などのフィールドはしばしば永続化される(例:部屋の説明文、マップ構造など)。
- 頻繁に変化するコンポーネント(例:エンティティが部屋間を移動)は、イベント駆動または定期的に書き込まれる。
- 外見・インタラクション系 (Appearance, UIState, Relationship など)
- エンティティの「可視部分」や「インタラクション」情報を記録。Avatar、pose、facialExpression、他エンティティとのソーシャル関係などを含む。
- 一部はメモリ内で処理(リアルタイム表示用)。一方、重要なソーシャル関係などは永続化される場合もある。
- 補助・運用系 (Cleanup, DebugInfo, ProfilingData など)
- 回収対象のエンティティをマーク(Cleanup)、デバッグ情報(DebugInfo)を記録して監視・分析時に使用。
- 基本的にメモリ内のみに存在。ログや監査が必要な場合を除き、DBに同期されることはない。
3. Systemアーキテクチャ
上記にて説明済み
4. Managerアーキテクチャ
コンポーネントとシステムに加え、データベースへのアクセス方法や状態更新時の競合処理など、リソースを管理する存在が必要です。

左側のSystems (PerceptionSystem、ExperienceSystem、ThinkingSystem など):
- 各システムはSimulationRuntimeによってECSサイクル内でスケジュールされ、自身が関心を持つエンティティ(コンポーネント条件により)を照会・処理する。
- 処理中にManagersとやり取りを行う。例:
- RoomManager (RM) を呼び出し、部屋情報を照会・更新。
- StateManager (SM) を使用して、ワールド/エージェントの状態(Memory、Goal、Planなど)を取得または保存。
- EventBus (EB) を活用し、外部にイベントをブロードキャストまたはリッスン。
- NLPやプロンプトが必要な場合、PromptManager (PM) を呼び出す。
----------------
右側のManagers (EventBus、RoomManager、StateManager、EventManager、ActionManager、PromptManager など):
- システムレベルの機能を提供。基本的に自らロジックを「駆動」することはなく、SystemsやRuntimeから呼び出される。
- 代表例:
- ActionManager:アクション(Action)の登録と実行を専門に管理。
- EventManager / EventBus:イベントの発行・購読機構を提供。
- RoomManager:rooms、レイアウト、occupantを管理。
- StateManager:ECSとデータベース/ストレージの同期を担当。
- PromptManager:LLMプロンプトテンプレート、コンテキスト管理などの拡張機能を提供。
- 中央のSimulationRuntime (R):
- すべてのSystemsの「スケジューラ」であり、異なる階層(Conscious/Subconsciousなど)のシステムサイクルを開始・停止する。
- 初期化段階でManagersを生成し、各Systemに渡して使用させる。
- CleanupSystem:
- 特に注意すべきは、ComponentSync (CS) とも連携し、エンティティを回収する際にコンポーネントやイベント購読も同期して削除すること。
結論:各Systemは必要に応じて対応するManagerを通じてデータの読み書きやサービス呼び出しを行い、Runtimeはより上位のレイヤーで全SystemとManagerのライフサイクルおよび動作を統一的にスケジュールする。
5. ベクトルおよびデータベースとの連携方法
ECSにおいて、Systemが実際にロジックを実行する場所ですが、データベースの読み書きは「永続化マネージャ(PersistenceManager / DatabaseManager)」または「状態マネージャ(StateManager)」を通じて行われます。おおよそのフローは以下の通りです。
- 起動時または読み込み時 (Initial Load)
- StateManager / PersistenceManagerがデータベースからAgents、Rooms、Goalsなどの主要永続化コンポーネントのデータを読み込み、対応するエンティティ(Entity)を作成し、関連コンポーネントを初期化する。
- 例:複数のエージェントレコードをECSワールドに挿入し、Agent、Memory、Goalなどのコンポーネントを初期化。
- ECS実行時 (Systems Update Loop)
- 各フレーム(またはラウンド)内で以下を実行:
- PerceptionSystemが「知覚」を収集し、Perceptionコンポーネントに書き込む(短期的でDB保存しないことが多い)。
- ExperienceSystemが新しい「認知体験」をMemory.experiencesに書き込む。重要な体験の場合は、即座にStateManagerを呼び出して保存、または「needsPersistence」マークを付けて後で一括書き込み。
- ThinkingSystem / ActionSystem / GoalPlanningSystemなどがコンポーネント内容に基づき意思決定を行い、ECS内のフィールドを更新。
- 特定のコンポーネント(例:Goal.current)に重大な変更があり永続化が必要な場合(例:長期目標の変更)、コンポーネントリスナやシステムイベントを通じ、StateManagerにDB書き込みを通知。
- 各フレーム(またはラウンド)内で以下を実行:
- 定期的またはイベント駆動型の永続化 (Periodic or Event-Driven)
- システム内の重要なポイント(例:計画の更新、エージェントの重大イベント)で、PersistenceManager.storeComponentData(eid, "Goal")などのインターフェースを呼び出してDB保存。
- CleanupSystemまたはタイマー内で、StateManagerが「needsPersistence」マーク付きのコンポーネントやエンティティをスキャンし、一度にまとめてDBに書き戻す。
- また、ログや監査データ(アクション履歴、思考ログなど)もここでアーカイブ保存可能。
- 終了時または中断保存時 (Manual or Shutdown Save)
- サーバーまたはプロセス終了時、StateManager.saveAll()を呼び出して未書き込みデータを一括でDBに保存し、次回起動時にECS状態を復元できるようにする。
- 単体機/オフライン環境では、手動でアーカイブをトリガーすることも可能。
- 完全な例
以下にシンプルなシナリオを示し、コンポーネントとデータベースのやり取りの方法を説明します。
- 起動時:
- StateManager.queryDB("SELECT * FROM agents") → 複数のエージェントレコードを取得し、各レコードに対してエンティティ(EID=x)を作成し、Agent、Memory、Goalなどのコンポーネントを初期化。
- "rooms"テーブルから部屋情報を読み込み、Roomエンティティを作成。
- 実行時:
- PerceptionSystemが特定の部屋で「MagicSword出現」というイベントを検知し、Perception.currentStimuli[eid]に書き込む。
- ExperienceSystemがStimuliをExperienceに変換し、Memory.experiences[eid]に代入。
- ThinkingSystemがMemory、Goalなどの情報から次に取るべき行動を決定し、Action.pendingAction[eid]を生成。
- ActionSystemがそのアクションを実行後、結果をMemoryまたはAction.lastActionResultに書き込む。
- これが重大なストーリーイベントの場合、Memory.experiences[eid]の最新部分にneedsPersistenceマークを付ける。
- 一定時間後、StateManagerがMemory.experiences[eid]に「needsPersistence」があることを検知し、データベースに書き込む(INSERT INTO memory_experiences ...)。
- 停止時または中断時:
- ECSまたはシステムスケジューラに基づき、「サーバー停止」時にStateManager.saveAll()を呼び出し、メモリ内の主要コンポーネント(Agent、Memory、Goalなど)の最新状態をデータベースに保存。
- 次回再起動時、データベースから読み込んでECSワールドの状態を復元可能。
- コンポーネントを分類することで、プロジェクト内でエンティティデータを明確に管理でき、永続化が必要なデータとメモリ内のみで保持するデータの境界を明確にできる。
- データベースとの連携は通常、専用のManager(例:StateManager)が担当。SystemがDBの読み書きを行う際はこれを通して操作し、System内にSQLなどの低レベルコードを直接書かないようにする。
- これにより、ECSが持つロジック面での効率性・柔軟性と、データベースが提供する永続化、中断後の再開、データ分析の利点を両立できる。
五、アーキテクチャの革新点

- このアーキテクチャの最大の特徴は、各Systemが独立して動作し、他のSystemと呼び出し関係を持たない点にある。
- たとえば「環境変化の知覚(Perception) → 内部経験への変換(Experience) → 自己思考と意思決定(Thinking) → 行動実行(Action) → 目標と計画の動的調整(GoalPlanning + Planning) → 環境同期(Room) → 不要エンティティの回収(Cleanup)」という一連の能力を実現する場合、各System間には多くの依存関係が生じる。しかしECSアーキテクチャにより、これらを互いに独立したSystemとして構成でき、個々のSystemは独立して動作し、他のSystemと一切の結合を持たない。
- これが近年UnityがECSアーキテクチャへ移行しつつある主な理由だと考えられる。
- また、あるエージェントに基本機能だけを持たせたい場合、Entity定義時に必要なComponentとSystemを減らすだけで簡単に実現でき、コード修正はほとんど不要。
下図参照:

- 開発中に新しい機能を追加したい場合も、他のSystemに影響を与えることなく、容易に追加できる。
- さらに、このアーキテクチャのパフォーマンスは、従来のオブジェクト指向アーキテクチャよりもはるかに優れている。これはゲーム業界で広く認められた事実であり、ECSが並列処理に適しているためである。複雑なDeFiシーンでも、ECSアーキテクチャは優位性を発揮できる。特にエージェントを用いた定量取引の場面では、ECSの活用余地は大きい(エージェントゲーム以外のシーンでも有用)。
- Systemを意識的、潜在的、無意識の3段階に分け、それぞれの実行頻度を制御する設計は極めて洗練されており、人間の認知能力を具体化したと言える。
個人的な見解として、これは極めてモジュール化が進み、パフォーマンスに優れたフレームワークであり、コード品質も高く、優れた設計ドキュメントも備えています。残念ながら、$project89プロジェクトはこのフレームワークの宣伝を十分に行っていませんでした。そのため、私は4日間かけてこの記事を執筆しました。良いものは発見されるべきだと信じています。明日には英語版も公開する予定です。より多くのゲーム開発チームやDeFiチームにこのフレームワークを知ってもらい、新たなアーキテクチャ選択肢として活用していただければと思います!
TechFlow公式コミュニティへようこそ
Telegram購読グループ:https://t.me/TechFlowDaily
Twitter公式アカウント:https://x.com/TechFlowPost
Twitter英語アカウント:https://x.com/BlockFlow_News













