Agentive
AIエージェント活用

AIエージェントの状態管理 — runtime_status.jsonからLangGraphまで

約6分で読めます

AIエージェントが複雑なタスクを遂行するには「今どの段階にいるか」を正確に把握する状態管理が不可欠になる。JSON単一ファイルからグラフベースの状態管理まで、規模に応じた選択肢を解説する。

状態管理の3段階

段階方法適用規模複雑度
レベル1JSONファイル単一エージェント
レベル2SQLite + JSON複数タスク並行
レベル3LangGraphマルチエージェント

レベル1: runtime_status.json

最もシンプルな方法。1つのJSONファイルでエージェントの状態を管理する。

{
  "agent_id": "cloudworks-bot",
  "status": "running",
  "current_task": {
    "id": "task-001",
    "type": "scrape_and_apply",
    "phase": "applying",
    "target": "cloudworks",
    "started_at": "2026-04-09T10:00:00Z"
  },
  "last_completed": {
    "id": "task-000",
    "completed_at": "2026-04-09T09:45:00Z",
    "result": "applied_3_jobs"
  },
  "error_count": 0,
  "last_heartbeat": "2026-04-09T10:05:00Z"
}

状態遷移の定義

idle -> running -> completing -> idle
             \-> error -> recovering -> idle
                                    \-> halted(手動復旧必要)

状態遷移は必ず一方向に定義する。error -> runningのような逆戻りはrecoveringを経由させる。

読み書きのコード例

import json
from pathlib import Path
from datetime import datetime

STATUS_FILE = Path("runtime_status.json")

def update_status(phase, **kwargs):
    status = json.loads(STATUS_FILE.read_text())
    status["current_task"]["phase"] = phase
    status["last_heartbeat"] = datetime.now().isoformat()
    status.update(kwargs)
    STATUS_FILE.write_text(json.dumps(status, indent=2, ensure_ascii=False))

def get_status():
    return json.loads(STATUS_FILE.read_text())

レベル2: SQLite + JSONの併用

タスクが複数並行する場合、JSONファイルでは競合が起きる。SQLiteでタスク一覧を管理し、各タスクの詳細はJSON列に格納する。

import sqlite3, json

db = sqlite3.connect("agent_state.db")
db.execute(
    "CREATE TABLE IF NOT EXISTS tasks ("
    "id TEXT PRIMARY KEY, "
    "status TEXT DEFAULT 'pending', "
    "payload JSON, "
    "created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, "
    "updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP)"
)

def add_task(task_id, payload):
    db.execute("INSERT INTO tasks (id, payload) VALUES (?, ?)",
               (task_id, json.dumps(payload)))
    db.commit()

def update_task_status(task_id, status):
    db.execute("UPDATE tasks SET status=?, updated_at=CURRENT_TIMESTAMP WHERE id=?",
               (status, task_id))
    db.commit()

レベル3: LangGraphとの比較

LangGraphはグラフベースの状態管理フレームワークで、条件分岐・並行実行・人間承認を宣言的に定義できる。

比較項目runtime_status.jsonLangGraph
セットアップゼロ(ファイル1つ)pip install + グラフ定義
状態遷移コード内にif文グラフのエッジで宣言的定義
並行処理ファイルロック必要ビルトインサポート
人間承認(HITL)自前実装interrupt()で標準サポート
可視化なしグラフの可視化ツールあり
依存関係なしlanggraph, langchain_core

選択基準

  • タスクが1種類で直線的 -> レベル1のJSONで十分
  • 複数タスクが並行し、状態を永続化したい -> レベル2のSQLite
  • 条件分岐・承認フロー・マルチエージェント連携が必要 -> レベル3のLangGraph

heartbeatパターン

エージェントが生存しているかを確認する仕組み。last_heartbeatを定期更新し、一定時間更新がなければ異常とみなす。

from datetime import datetime, timedelta

def is_agent_alive(status, threshold_minutes=10):
    last = datetime.fromisoformat(status["last_heartbeat"])
    return datetime.now() - last < timedelta(minutes=threshold_minutes)

watchdogプロセスがheartbeatを監視し、停止を検知したら再起動またはアラートを発行する。

設計のベストプラクティス

  1. 最小限の状態から始める: 最初からLangGraphを入れない。JSONで足りなくなってから移行する
  2. 状態遷移図を先に描く: コードより先に状態と遷移を定義する
  3. heartbeatは必須: 自律エージェントは「黙って死ぬ」ことがある
  4. エラー状態を明示的に定義する: 「不明な状態」を許容しない

関連記事

A

Agentive 編集部

AIエージェントを実際に使い倒す個人開発者。サイト制作の自動化を実践しながら、その知見を発信しています。