Qwenの計画とJevの行動選択が安全ゲートを通ってファンタジーゲームへ届く、二つの速度のAIエージェントを表したイメージ

Article

Qwen3.8-Flash-NextとJevで、Ultima Onlineの自律エージェントを作ってみた

2026年9月20日
9 min read
AIエージェント
#Qwen3.8-Flash-Next#Jev#Ultima Online#TazUO#MCP#AIエージェント#GX10

Ultima Onlineのキャラクターに、**「忍術を60まで上げて」**と自然言語で目標を渡す。あとは現在地やマナ、技能値を読みながら、自分で移動し、練習し、必要なら方針を考え直してもらう。

そんなエージェントを、Qwen3.8-Flash-NextとJev、そしてTazUOへ独自実装したMCPを使って作っている。

今回いちばん大事にしたのは、すべてを一つのAIへ任せないことだ。

Qwenが方針と行動候補を作り、Jevが現在の状況から次の一手を選び、Pythonが条件を再確認して実行する。

実ゲームでは、同じ方針のまま5区間を移動してDojoの掲載位置付近へ到着し、Mirror Imageの詠唱を3回送信した。Journalで詠唱開始を読み取り、忍術スキルが52.7から52.9へ上がったところまで確認できた。後続の保存記録には53.2も残っている。

ただし、目標の60へ到達したわけではない。補給・購入・蘇生まで含めた長時間の完全自律運用も、まだ確認できていない。

この記事では「どこまで動いたか」と「まだ動いていない部分」を分けながら、二つの速度を持つエージェントの構成を紹介する。

この記事は2026年9月19日時点の実装と保存済み検証記録をもとにした。執筆時にゲーム操作、モデル推論、テストを再実行した結果ではない。

一手ごとにQwenを待たない構成

全体像はこうなっている。

ユーザーの目標をQwenの戦略、Jevの行動選択、Pythonの安全確認、TazUOへ独自実装したMCPへつなぐ構成図

担当 役割
Qwen3.8-Flash-Next 目標を段階へ分け、行動候補・完了条件・期限を含む方針を作る
Jev 最新の観測と方針を見て、候補、待機、再検討から次の一手を選ぶ
Python Runtime 状態、時間、前提条件、停止、重複送信を確認し、単一のExecutorから操作する
独自実装のTazUO MCP Ultima Onlineの状態を読み、移動や詠唱などの操作をゲームへ届ける
SQLite 会話、受理した目標、計画、進捗イベントを保存する

補足: ここでいう「TazUO MCP」は、公開されているTazUO本体の標準機能ではない。私が手元のTazUOへ独自実装したMCP拡張を指している。

MacではTazUOをベースにしたクライアント、そのクライアントへ追加したMCP、Python Agent、Web UI、SQLiteが動く。QwenはGX10からOpenAI互換APIで提供し、JevはCloudflare経由で利用している。

Qwen側は、以前紹介したGX10 1台のQwen3.8-Flash-Next環境だ。記事ではモデル名までを扱い、内部IPや認証情報は載せない。

Qwenは「何をするか」をまとめて考える

Qwenへ渡すのは、ユーザーの目標、現在の観測、地点やゲームの参照資料、直近の結果だけではない。

接続中のMCPからtools/listで取得したツール一覧とJSON Schemaも見せる。利用できる操作と実際の引数を確認したうえで、次のような方針を作らせる。

  • 移動、育成、補給、帰還などの段階
  • 各段階の完了条件
  • MCPのツール名と引数を持つ行動候補
  • 実行前提、反復できるか、実行間隔、実行後の確認方法
  • 方針そのものの有効期限

「Dojoで忍術を60まで」という目標なら、まず目的地へ移動し、その後に練習へ進む。目的地へ着く前から詠唱を始めないよう、位置とfacetも完了条件に含める。

現在の設定では、計画の有効期限は既定300秒、最大600秒。定期レビューは180秒ごとだ。初回の戦略生成には74.4秒かかった例もあるので、これを毎操作の前に待っていてはゲームを継続して動かしにくい。

そこで、Qwenは長めの時間軸を担当する。

Jevは「いま何をするか」を選ぶ

Jevへ渡すのは、最新の観測、現在の段階、実行可能な行動候補だ。

Cloudflareの公式仕様では、Jevは状態に対して型付きのNoul、Choice、Scoreを評価する構造化モデルとして説明されている。今回の主経路ではchoiceを使い、候補ID、waitescalateのどれかを選ばせている。

ここで重要なのは、JevにMCPの任意のツール名や引数を毎回作らせていないことだ。Qwenが作った候補の範囲で、現在のマナ、詠唱中か、フォロワー数に空きがあるかといった状態を見て選ぶ。

方針がまだ有効なら、Qwenの定期レビュー中も行動ループを続けられる。状態と方針が合わなくなったときは、escalateでQwenへ再検討を戻す。

保存された検証では、Jevはおおむね0.5〜1秒で応答していた。フォロワー枠が回復した状態を使った読み取り試験では809.26msで再詠唱候補を選んでいる。ただし、この値は単発の確認であり、p95の性能測定ではない。

Pythonが最後の安全確認をする

QwenもJevも、ゲーム操作を直接送らない。

現在のWorld Modelの中心は、Pydanticで定義したObservationだ。HP、マナ、座標、技能値、周囲のオブジェクト、包帯、詠唱状態などをMCPから組み立てる。取得できなかった値はNoneにし、実際の0と混同しない。

Jevが候補を選んでも、Pythonは送信直前にもう一度確認する。

  • 人間が停止していないか
  • 目標、制御権、接続セッションが変わっていないか
  • 観測、判断、方針が古くなっていないか
  • 前提条件と実行間隔を満たすか
  • ツール名と引数がMCP Schemaに合っているか
  • 一回限りの操作や、結果不明の操作を重ねて送ろうとしていないか

操作経路は単一のExecutorへ集めた。停止や目標変更の後からQwenやJevの遅い回答が届いても、そのまま実行しないためだ。

また、MCPの応答がdispatchedでも、それだけでゲーム内成功とは扱わない。移動後の座標、Journal、技能値などを再び読み、計画の進捗へ反映する。

戦略ループと行動ループを分ける

この構成には二つのループがある。

戦略ループ

初回、新しい目標、例外、停滞、期限切れ、定期レビューでQwenを呼ぶ。Qwenは複数段階の方針と候補をまとめて更新する。

行動ループ

観測 → 候補の絞り込み → Jevの選択 → Pythonの再検証 → MCP操作 → 結果の再観測を繰り返す。

旧方針が有効な範囲なら、定期レビューをQwenが考えている間もこちらを続ける。期限切れや緊急の再検討が必要な状態まで、無条件に古い方針で走り続けるわけではない。

この分離によって、長く考える時間と、ゲーム内でテンポよく動く時間を両立させた。

長距離移動は16タイルずつ作り直す

実ゲームで早めにぶつかったのが経路探索だった。

MCPの移動上限は64タイルだが、長距離を一度に指定するとNo path was generated.になる場所があった。読み取り検証では32タイルと64タイルで経路が出ず、16タイル先なら79ノードの経路が生成された。

そこで、現在地から目的地へ向かう16タイルの区間を毎回作り直すことにした。Jevがその区間の実行を選び、移動後に位置を再観測する。

これにより、保存された実ゲーム検証では、Qwenの再計画を挟まずに5区間を移動し、Dojoの掲載位置付近へ到着できた。

万能なナビゲーションが完成したわけではない。掲載座標から実際に歩けるか、入口を通れるかは別の問題だ。それでも、長い経路を一度に解かせるより、現在地から短く刻む方が継続制御に向いていることは確認できた。

実ゲームで確認できたこと

2026年9月19日の保存済み検証記録をまとめると、次のようになる。

確認項目 保存された結果
Qwenを呼び直さずに移動 5区間
Qwenを呼び直さずに詠唱送信 3回
Journalで確認した詠唱開始 4回
最初の詠唱送信間隔 6.806秒、6.091秒
忍術スキル 52.7 → 52.9
後続の観測 53.2、HP 124/124、停止解除

詠唱送信間隔は、その場での行動間隔だ。Jev単体の推論時間ではない。

また、途中のJournalにはフォロワー数上限による詠唱拒否も残っていた。過去の失敗だけを見て待ち続けないよう、短期判断では現在のフォロワー数を優先するようにした。実MCPの現在値が0/5まで戻った状態では、Jevが再詠唱候補を選べた。

「過去に失敗した」と「いまも実行できない」を分けることは、ゲームに限らず継続型Agentで重要だと思う。

繰り返してよい操作、いけない操作

詠唱、短い区間移動、技能使用、攻撃、自己包帯には反復条件を持たせられる。

一方、購入、物品移動、Gumpへの返信、銀行引き出しを同じように自動反復すると危ない。現在の実装では、一回限りの操作を識別し、送信結果が不明な操作を別IDでやり直さないようにしている。

銀行MCPについては、別クライアントが行った100 Gold引き出しの結果をAgent側から読み戻し、口座と手持ちの差分が一致するところまで確認した。これはAgent自身が新しく引き出して補給を完遂した実績ではない

計画を作れたこと、MCPへ送れたこと、ゲーム内で成功したことは、それぞれ別の証拠として扱う必要がある。

まだ「完全自律」とは言わない

今回確認できたのは、限定した時間の中で、同じ方針を使って移動と忍術練習を継続できたことだ。

まだ確認できていないものも多い。

  • 忍術60までの育成完了
  • 補給、購入、装備をつないだ一連の運用
  • 死亡後の蘇生と復帰
  • 長時間運用での停止・再開・通信障害からの回復
  • 多数試行によるレイテンシや成功率の評価

現在の主な実装はPython、Pydantic、HTTPX、FastAPI、SQLite、ブラウザのHTML/CSS/JavaScriptだ。原案にあったPydanticAIやpydantic-graph、網羅的なMonster DB、戦闘履歴からの危険度学習まで完成したわけではない。

だから今の説明は、「UOを全部任せられるAgentが完成した」ではなく、方針生成と継続判断を分けた構成で、実ゲームの移動と練習が続くところまで動いたになる。

次は補給と復帰をつなぐ

次の課題は、移動と育成だけでなく、消耗品の不足、銀行、購入、装備、死亡後の復帰を一つの流れにすることだ。

ただし、自動化する範囲が広がるほど、AIの自由度を上げるだけでは危なくなる。Qwenには方針を考えてもらい、Jevには候補から選んでもらい、Pythonには止める責任を持たせる。

この役割分担は、Ultima Onlineに限らず、長く考えるAIと素早く反応するAIを組み合わせたいAgentにも使えるはずだ。

今のところ、Qwenは「どこへ向かうか」を考え、Jevは「次の一歩」を選び、Pythonは「本当に踏み出してよいか」を確認する。

その三つを分けたことで、ようやくゲームの時間で動き続けるAgentらしくなってきた。

参照した外部仕様