GraphAI(グラフエーアイ)は、AIエージェントの処理手順をYAMLやJSONのデータフローグラフとして書き、依存関係の解決と並行実行をエンジンに任せるTypeScript製のOSSです。開発元はGitHubのreceptron組織で、npmパッケージ graphai の作者欄には Satoshi Nakajima(中島聡)と Isamu Arimoto の名前があります。receptronのREADMEは、中島氏をMicrosoftでWindows 95・Windows 98・Internet Explorerのソフトウェアアーキテクトを務めた人物と紹介しています。ライセンスはMITで、2026年10月23日時点の最新版は2.0.18(npm公開は2026年6月8日)です。
この記事では、データフローグラフの書き方、CLIとNode.jsでの動かし方、並行実行と再試行の挙動、AgentFilterとRAG部品の使い方を、graphai 2.0.18をNode.js v26.5.0で実際に動かした結果とあわせて説明します。名前が同じPython製の別ライブラリや、技術分野としての「Graph AI」との違いも整理します。なお「グラフ AI」で検索して、売上表から棒グラフを作るようなグラフ作成AIツールを探している場合、GraphAIはそれとは別物です。
まとめ:GraphAIの機能と採用条件
- GraphAIは非同期データフロー実行エンジンです。ノードが他ノードの出力を
:ノード名.プロパティで参照すると、それが依存関係になり、依存の無いノードは自動で同時に走ります。 - 最新版は
graphai2.0.18。グラフ定義の形式バージョンはversion: 0.5で、同時実行数の既定値は8です。 - CLI(
@receptron/graphai_cli2.0.12)はクリーン環境だと@graphai/namedinput_validator_agent_filterが見つからず起動に失敗します。同パッケージを追加で入れれば動きます。 - 擬似的な1秒待ちのLLM呼び出し3件は、既定の並行数で1,007ms、
concurrency: 1で3,019msでした。0.5秒の処理3件はmapAgentで510ms、loopで1,512msです。 - エージェント呼び出しの前後に割り込む AgentFilter で、ログ・キャッシュ・ストリーミング・HTTP経由の実行を後から足せます。分割・類似度・並べ替えのエージェントを並べれば、RAGの前処理もグラフで書けます。
- PyPIの
graphai-libはAurelio AIが作った同名の別ライブラリ(Python製)で、互換性はありません。GNNやGraphRAGを指す技術分野の「Graph AI」とも別物です。 - グラフは非巡回(DAG)が前提です。会話の状態を持ち回して分岐と巡回を細かく制御したいPythonチームなら、LangGraphの方が合います。
GraphAIの開発元・版・パッケージ構成
GraphAIのリポジトリは receptron/graphai で、2024年4月5日に作られました。npmの公開履歴では0.1.0が2024年4月18日、1.0.0が2025年3月1日、2.0.0が2025年5月21日です。2026年10月23日にGitHub APIで取得したスター数は373、npmのダウンロード統計APIによる2026年9月19日〜10月18日の30日間のダウンロード数は17,464件でした。LangChainのような大規模エコシステムではなく、日本の開発者コミュニティが中心のプロジェクトです。
本体は小さく、実用的なエージェントは別パッケージに分かれています。必要なものだけを入れる構成です。
| パッケージ | 最新版 | 公開日 | 中身 |
|---|---|---|---|
| graphai | 2.0.18 | 2026-06-08 | 実行エンジン本体 |
| @graphai/vanilla | 2.0.12 | 2025-08-18 | 文字列・配列処理、mapAgent等の34種 |
| @graphai/llm_agents | 2.1.0 | 2026-09-21 | OpenAI・Anthropic・Gemini・Groq・Replicate |
| @graphai/agents | 2.1.0 | 2026-09-21 | 上記を含む一括パッケージ |
| @graphai/mcp_agent | 0.0.6 | 2026-09-22 | MCPサーバーのツール呼び出し |
| @receptron/graphai_cli | 2.0.12 | 2026-02-04 | YAMLを実行する graphai コマンド |
公開日はnpmレジストリのUTC日時に基づきます。GitHub Releasesでの2.0.18の公開日は2026年6月18日(UTC)で、npm公開日の6月8日(UTC)とは10日異なります。版の確認はnpm側を見る方が確実です。
ライセンスは当初からpackage.jsonでMITと宣言されていましたが、リポジトリ直下にLICENSEファイルが無く、GitHubの画面では「ライセンス無し」と表示されていました。2026年10月16日(UTC。日本時間では17日)のコミットでLICENSEファイルが追加され、現在はGitHub上でもMITと表示されます。社内の利用審査で「GitHubにライセンス表示が無い」と止められた記録が残っている場合は、この点を添えて再確認してください。
YAMLを手で書かずにノードと入力をつないで組みたい場合は、公式のGUIツール Grapys(receptron/grapys)があります。Vue版とReact版があり、どちらも同じ機能を持つとREADMEに書かれています。
実運用の例として、READMEはreceptronの動画・ポッドキャスト生成CLIである MulmoCast(マルモキャスト)とは?使い方と料金、CLI・アプリ・MCPの選び方【v2.12対応】 を挙げています。音声・画像・字幕・翻訳の各工程がGraphAIのグラフとして書かれています。
同じ名前の「GraphAI」「Graph AI」との違い
「GraphAI」「Graph AI」で検索すると、この記事で扱うreceptronのGraphAIのほかに、別の開発元の同名ライブラリと、技術分野としてのGraph AIが並びます。中身はそれぞれ別物です。
| 名前 | 中身 | 言語・配布 | 見分け方 |
|---|---|---|---|
| GraphAI(receptron) | YAML・JSONで書くデータフロー実行エンジン | TypeScript、npm graphai |
本記事の対象。receptron/graphai |
| GraphAI(Aurelio AI) | ノードとルーターを関数で書くグラフ実行ライブラリ | Python、PyPI graphai-lib |
aurelio-labs/graphai |
| Graph AI(技術分野) | グラフ構造のデータにAIを適用する手法の総称 | 製品ではない | GNN・グラフ埋め込み・GraphRAG |
| グラフ作成AI | 表やデータから棒グラフ・円グラフを描く機能 | 表計算ソフト・BIツールの機能 | 「AI グラフ作成」などで探す |
Aurelio AI版GraphAI(Python)の書き方と実測
Aurelio AIのGraphAIは、PyPIでは graphai-lib という名前で配布されています。リポジトリ aurelio-labs/graphai は2024年7月22日に作られ、PyPIの初版0.0.1は2024年12月18日、2026年10月23日時点の最新版は0.0.12(2026年9月8日公開)です。対応するPythonは3.10以上3.14未満で、pyproject.tomlの説明文には「Not an AI framework」と書かれています。2026年10月23日時点では、リポジトリにもPyPIのメタデータにもライセンスの記載が見当たりません。業務で使う前に開発元へ確認が必要です。
書き方はreceptron版と大きく違い、YAMLは使いません。ノードを @node、分岐を @router のデコレーターで定義し、add_edge でエッジを明示します。ルーターは次に進むノードの名前を choice として返します。以下は経路選択をLLMの代わりに文字列判定で行う例で、APIキー無しで動きます(Python 3.12・graphai-lib 0.0.12で確認)。
import asyncio
from graphai import Graph, node, router # pip install graphai-lib
@node(start=True)
async def start(input: dict):
return {"input": input}
@router
async def route(input: dict):
# LLMの代わりに文字列で経路を選ぶ
return {"choice": "search" if "最新" in input["query"] else "memory", "input": input}
@node
async def search(input: dict):
return {"input": {**input, "text": "検索結果"}}
@node
async def memory(input: dict):
return {"input": {**input, "text": "記憶"}}
@node(end=True)
async def end(input: dict):
return {"output": input["text"]}
g = Graph()
for n in (start, route, search, memory, end):
g.add_node(n)
g.add_edge(start, route)
g.add_edge(search, end)
g.add_edge(memory, end)
async def main():
r1 = await g.execute(input={"input": {"query": "最新のニュース"}})
r2 = await g.execute(input={"input": {"query": "私の名前は"}})
print(r1["output"], r2["output"], g.max_steps) # => 検索結果 記憶 10
asyncio.run(main())
実行すると、docstringの無い関数ごとに Function start has no docstring という警告がログに出ました。実行ステップ数には上限 max_steps(既定10)があり、超えると MaxStepsError で止まります。receptron版のYAMLを読み込む機能は無く、2つのGraphAIの間に互換性はありません。
技術分野の「Graph AI」と処理フローのGraphAIの違い
英語の解説記事やグラフデータベース各社の用語集で「Graph AI」と言うと、グラフ構造のデータにAIを適用する技術の総称を指します。人や商品を頂点、関係を辺として表し、グラフニューラルネットワーク(GNN)やグラフ埋め込みで学習したり、ナレッジグラフをLLMの検索に使うGraphRAGで回答の根拠を集めたりする分野です。
receptronのGraphAIがグラフにするのは処理の手順で、技術分野のGraph AIがグラフにするのはデータです。データ側の手法は グラフ埋め込み(Graph Embedding)とは?手法比較・GNNとの関係・Python実装まで、GraphRAGの構築は GraphRAGをAzureで動かす方法|graphrag 3.3の設定とAccelerator終了後の選択肢【2026年10月】、グラフを保存するデータベースは Neo4jとは?グラフデータベースの構造とCypher・エディション選定を実装視点で解説【2026年版】 で扱っています。
データフローグラフの構造:ノード・エージェント・データソース
GraphAIのグラフは version と nodes を必須とするオブジェクトで、YAMLかJSONで書きます。任意で concurrency(同時実行数)と loop(グラフ全体の反復)を指定できます。
静的ノードと計算ノードの違い
ノードは2種類です。静的ノードは value で値を持つ変数の役割で、ループのたびに update で値を差し替えられます。計算ノードは agent で指定したエージェント関数を呼び、その戻り値を他ノードへ渡します。計算ノードの主なプロパティは次のとおりです。
| プロパティ | 役割 | 既定値 |
|---|---|---|
| agent | 呼び出すエージェント(必須) | なし |
| inputs | 入力元のデータソース | 空なら即実行 |
| params | エージェント固有の設定 | なし |
| if / unless | 値の真偽で実行可否を決める | なし |
| anyInput | 入力が1つ揃えば実行 | false |
| retry | 失敗時の最大再試行回数 | なし |
| timeout | 待ち時間の上限(ミリ秒) | なし |
| priority | 実行順の優先度 | 0 |
| isResult | run()の戻り値に含める | false |
エッジを書かずに依存関係を決める参照記法
GraphAIには「AからBへ線を引く」記述がありません。inputs の値に :summary.text のように別ノードを書くと、それがそのまま依存関係になります。参照は :ノード名、:ノード名.プロパティ、配列の要素なら :ノード名.$0 や :ノード名.$last の形です。
この仕組みのため、依存の無いノードは書いた順序に関係なく同時に走ります。逆に言えば、実行順を手で並べたいときは参照で依存を作る必要があります。ノードを記述する順序と、依存関係によって決まる実行順序は区別してください。
GraphAIのインストールと最初のグラフの実行手順
使い方は、YAMLをCLIで実行する方法と、Node.jsのコードからエンジンを呼ぶ方法の2つです。試すだけならCLI、アプリへ組み込むならコードを選びます。
CLIで動かす手順と依存不足エラーの回避策
公式チュートリアルの手順は、CLIをグローバルに入れ、カレントディレクトリの .env に OPENAI_API_KEY を書き、graphai hello.yaml を実行する流れです。ただし最新の @receptron/graphai_cli 2.0.12 をクリーンな環境へ入れると、起動時に次のエラーで止まります(2026年10月1日、Node.js v26.5.0で確認)。
Error: Cannot find module '@graphai/namedinput_validator_agent_filter'
原因は、CLIが依存する @receptron/test_utils 2.0.3 がこのモジュールを読み込むのに、package.jsonの依存に載せていないことです。同じパッケージを一緒に入れると動きます。
npm i -g @receptron/[email protected] @graphai/[email protected]
cat > hello.yaml <<'EOF'
version: 0.5
nodes:
prompt:
value: Explain GraphAI in 30 words.
echo:
agent: copyAgent
inputs:
text: :prompt
isResult: true
EOF
graphai hello.yaml # => { "echo": { "text": "Explain GraphAI in 30 words." } }
graphai -l # 使えるエージェントの一覧(2.0.12では51種)
graphai -m hello.yaml # グラフをMermaid記法で出力
この例はAPIキー無しで動く copyAgent を使っています。agent: openAIAgent に変更し、入力を inputs: { prompt: :prompt } に変更します。さらに params.model と OPENAI_API_KEY を設定すると、指定したプロンプトでOpenAIのAPIを呼び出せます。-m で出るMermaid図は、グラフの依存関係をレビューするときに役立ちます。
Node.jsのコードから実行する手順と独自エージェントの登録
アプリに組み込むときは npm i [email protected] @graphai/[email protected] を入れ、GraphAI クラスにグラフとエージェントの辞書を渡して run() を呼びます。独自の関数は agentInfoWrapper で包めばエージェントとして登録できます。以下を example.mjs として保存し、node example.mjs で実行してください。
import { GraphAI, agentInfoWrapper } from "graphai";
import { stringTemplateAgent } from "@graphai/vanilla";
const upperAgent = async ({ namedInputs }) => ({ text: namedInputs.text.toUpperCase() });
const graphData = {
version: 0.5,
nodes: {
name: { value: "graphai" },
upper: { agent: "upperAgent", inputs: { text: ":name" } },
greeting: {
agent: "stringTemplateAgent",
inputs: { who: ":upper.text" },
params: { template: "Hello, ${who}" },
isResult: true,
},
},
};
const graph = new GraphAI(graphData, { stringTemplateAgent, upperAgent: agentInfoWrapper(upperAgent) });
console.log(await graph.run()); // => { greeting: 'Hello, GRAPHAI' }
ESモジュールで import * as vanilla from "@graphai/vanilla" とした名前空間を展開して渡すと、No Agent: __esModule is not in AgentFunctionInfoDictionary. という検証エラーで止まります。使うエージェントを名前付きで取り込むのが確実です。また、関数をグラフの中に直接書くインラインエージェントはTypeScriptやJavaScriptで書いたグラフでしか使えず、YAMLやJSONには書けません。
並行実行の実測:concurrency・mapAgent・loopの所要時間
GraphAIの価値は、依存の無い呼び出しを自動で同時に走らせる点にあります。並行実行の挙動を、一定時間待機する擬似LLMエージェントで測りました(graphai 2.0.18、@graphai/vanilla 2.0.12、Node.js v26.5.0、APIキー不要)。実際のLLMの応答速度を測る試験ではなく、エンジンがどの呼び出しを同時に走らせるかを見るための計測です。各4回実行し、最小〜最大を載せています。
| グラフ | 処理 | 所要時間 |
|---|---|---|
| 独立ノード3つ(既定 concurrency 8) | 1秒×3件 | 1,005〜1,022ms |
| 同じグラフで concurrency: 1 | 1秒×3件 | 3,004〜3,024ms |
| mapAgent で3件を処理 | 0.5秒×3件 | 510〜529ms |
| loop(while)で3件を処理 | 0.5秒×3件 | 1,508〜1,525ms |
計測に使ったスクリプトです。concurrency.mjs として保存し、node concurrency.mjs で実行できます。summary・keywords・title の3ノードはどれも :topic しか参照していないため、同時に走ります。article は3つ全部を参照しているので、最後にまとめて実行されます。mapAgent と loop の比較には、公式READMEの人物リストの例と同じ形のグラフを使い、openAIAgent を同じ擬似エージェント(0.5秒待機)に置き換えました。
import { GraphAI, agentInfoWrapper } from "graphai";
import { stringTemplateAgent } from "@graphai/vanilla";
import YAML from "yaml"; // npm i graphai @graphai/vanilla yaml
// 指定ミリ秒だけ待って返す擬似LLM(APIキー不要)
const fakeLLM = async ({ params, namedInputs }) => {
await new Promise((r) => setTimeout(r, params.ms));
return { text: `${params.label}(${namedInputs.prompt})` };
};
const agents = { stringTemplateAgent, fakeLLM: agentInfoWrapper(fakeLLM) };
const yaml = `
version: 0.5
concurrency: CONC
nodes:
topic:
value: GraphAI
summary:
agent: fakeLLM
params: { label: summary, ms: 1000 }
inputs: { prompt: :topic }
keywords:
agent: fakeLLM
params: { label: keywords, ms: 1000 }
inputs: { prompt: :topic }
title:
agent: fakeLLM
params: { label: title, ms: 1000 }
inputs: { prompt: :topic }
article:
agent: stringTemplateAgent
inputs: { a: :summary.text, b: :keywords.text, c: :title.text }
params: { template: "\${c} / \${a} / \${b}" }
isResult: true
`;
for (const conc of [8, 1]) {
const graph = new GraphAI(YAML.parse(yaml.replace("CONC", conc)), agents);
const t0 = Date.now();
const result = await graph.run();
console.log(`concurrency=${conc}: ${Date.now() - t0}ms`, result);
}
// => concurrency=8: 1005ms { article: 'title(GraphAI) / summary(GraphAI) / keywords(GraphAI)' }
// => concurrency=1: 3004ms { article: 'title(GraphAI) / summary(GraphAI) / keywords(GraphAI)' }
この結果から言える判断は2つです。1つ目は、concurrency を絞れば直列になるので、APIのレート制限が厳しい場合はここで同時呼び出し数を抑えることです。並行数の枠は子グラフとも共有され(リモート実行を除く)、子グラフのノードも親の上限の中で動きます。2つ目は、リストの各要素に同じ処理をかけるなら mapAgent を使うことです。loop は反復を1回ずつ順に回すので、要素数に比例して遅くなります。loop を使うのは、前回の結果を次の反復で使う処理(会話の継続など)に限るのが妥当です。
制御フローの書き方:入れ子・条件分岐・合流
グラフは非巡回が前提なので、繰り返しや分岐は専用の仕組みで書きます。それぞれの用途は次のとおりです。
- 入れ子グラフ(nestedAgent):ノードの
graphに子グラフを書き、部品として再利用します。親の入力は子グラフから:questionのような名前で参照できます。 - if / unless:ifは参照先が真なら実行し、unlessは偽なら実行します。false・0・空文字・null・undefinedなどに加え、GraphAIでは空配列も偽として扱います。LLMがツール呼び出しを返したときだけ処理を走らせる、といった分岐に使います。
- anyInput:
trueにすると、複数の入力のどれか1つが届いた時点で実行します。ifで分かれた2経路を1つのノードに合流させるときの定番です。 - priority:既定は先入れ先出し(優先度0)で、数値が大きいノードから先に実行されます。負の値も使えます。
LLMを何度も呼び出して段階的に出力を磨く設計は、プロンプトを段に分ける考え方と相性が良い一方、分岐を増やすほどグラフが読みにくくなります。Mermaid図で分岐先を追いにくくなったら、独立した入出力を持つ処理を入れ子グラフへ切り出します。
RAG前処理のグラフ構成:分割・類似度・並べ替え
公式チュートリアルには、Wikipediaの記事を分割して埋め込みベクトルを取り、問いとの類似度が高い順に並べてプロンプトに入れる「In-memory RAG」のグラフがあります。使うのは stringSplitterAgent(分割)、stringEmbeddingsAgent(埋め込み)、dotProductAgent(内積)、sortByValuesAgent(並べ替え)で、どれも @graphai/vanilla に入っています。stringEmbeddingsAgent は既定でOpenAIの埋め込みAPI(text-embedding-3-small)を呼ぶため、ここでは語の出現有無を並べた擬似ベクトルに置き換えて、部品の動きだけを確かめました。rag.mjs として保存し、node rag.mjs で実行できます。
import { GraphAI, agentInfoWrapper } from "graphai";
import { stringSplitterAgent, dotProductAgent, sortByValuesAgent, stringTemplateAgent } from "@graphai/vanilla";
// 埋め込みAPIの代わりに、語ごとの出現有無を並べた擬似ベクトルを返す
const VOCAB = ["retry", "timeout", "concurrency", "loop", "mapAgent", "yaml"];
const embed = (s) => {
const v = VOCAB.map((w) => (s.includes(w) ? 1 : 0));
const n = Math.hypot(...v) || 1;
return v.map((x) => x / n);
};
const fakeEmbeddingsAgent = async ({ namedInputs }) =>
(namedInputs.array ?? [namedInputs.item]).map(embed);
const doc = [
"GraphAI reads a yaml graph.",
"retry and timeout control failures.",
"concurrency limits parallel calls.",
"mapAgent runs items in parallel; loop runs them one by one.",
].join(" ");
const graphData = {
version: 0.5,
nodes: {
source: { value: { text: doc, topic: "concurrency mapAgent" } },
chunks: { agent: "stringSplitterAgent", inputs: { text: ":source.text" }, params: { chunkSize: 40, overlap: 0 } },
chunkEmbeddings: { agent: "fakeEmbeddingsAgent", inputs: { array: ":chunks.contents" } },
topicEmbedding: { agent: "fakeEmbeddingsAgent", inputs: { item: ":source.topic" } },
similarities: { agent: "dotProductAgent", inputs: { matrix: ":chunkEmbeddings", vector: ":topicEmbedding.$0" } },
sorted: { agent: "sortByValuesAgent", inputs: { array: ":chunks.contents", values: ":similarities" } },
prompt: {
agent: "stringTemplateAgent",
inputs: { best: ":sorted.$0" },
params: { template: "Context: ${best}" },
isResult: true,
},
},
};
const graph = new GraphAI(graphData, {
stringSplitterAgent, dotProductAgent, sortByValuesAgent, stringTemplateAgent,
fakeEmbeddingsAgent: agentInfoWrapper(fakeEmbeddingsAgent),
});
const result = await graph.run();
console.log(graph.nodes.chunks.result.contents, graph.nodes.similarities.result);
console.log(result);
実行結果は次のとおりです(graphai 2.0.18・@graphai/vanilla 2.0.12)。
[
'GraphAI reads a yaml graph. retry and ti',
'meout control failures. concurrency limi',
'ts parallel calls. mapAgent runs items i',
'n parallel; loop runs them one by one.'
] [ 0, 0.7071067811865475, 0.7071067811865475, 0 ]
{ prompt: 'Context: meout control failures. concurrency limi' }
ここから分かる注意点は3つです。
stringSplitterAgentは文字数で機械的に切ります。上の例ではtimeoutが「ti」と「meout」に割れました。既定値はソースコード上chunkSize2048文字、overlapはその8分の1(256文字)です。重なりを0にすると、境界の語が両方のチャンクで欠けます。dotProductAgentの戻り値は類似度の配列そのもので、:similaritiesとそのまま参照できます。ベクトルを正規化してから渡せば、内積がコサイン類似度になります。sortByValuesAgentは値の大きい順に並べ替えました。類似度が同じチャンク同士は元の順を保ったので、先頭だけを使うと同点の2番目が落ちます。
公式の例では、この後に tokenBoundStringsAgent でトークン数の上限(例では5000)まで上位のチャンクを詰めてからLLMに渡します。また公式チュートリアルには、LLMにGraphAIのYAMLを生成させてその場で実行する「Dynamic Graph Generation」の例(receptron/graphai_samples の metachat.yaml)もあります。グラフがデータなので、LLMが処理手順そのものを書き換えられるのがGraphAIらしい使い方です。
エラー処理の挙動:retryとtimeoutの実測
LLMのAPIは一時的な失敗やタイムアウトが避けられません。retry と timeout の動作を、失敗する関数と遅い関数で確かめました。
import { GraphAI, agentInfoWrapper } from "graphai";
let calls = 0;
const flaky = async () => { calls++; if (calls < 3) throw new Error(`fail #${calls}`); return { text: "ok" }; };
const slow = async () => { await new Promise((r) => setTimeout(r, 2000)); return { text: "late" }; };
const graph = new GraphAI({
version: 0.5,
nodes: {
a: { agent: "flaky", retry: 2, isResult: true }, // 2回失敗して3回目で成功
b: { agent: "slow", timeout: 500, isResult: true }, // 500msで結果待ちを打ち切る。slow自体は継続する
},
}, { flaky: agentInfoWrapper(flaky), slow: agentInfoWrapper(slow) });
try {
await graph.run();
} catch (e) {
console.log(e.message); // => Timeout
}
console.log(calls, graph.nodes.a.state); // => 3 completed
console.log(graph.nodes.b.state); // => timed-out
結果をまとめると次の3点です。
retry: 2は「初回+再試行2回」で、関数は最大3回呼ばれます。timeoutを超えたノードの状態はtimed-outになり、遅れて返った値は捨てられます。- どこか1つのノードが失敗またはタイムアウトすると、
run()はそのエラーでrejectします。掲載例でrejectの原因になるのはslowのTimeoutです。別に、毎回失敗する関数へretry: 2を付けて試すと、3回目の呼び出しのエラー(fail #3)でrejectしました。
つまり、一部のノードが失敗しても残りの結果を返す、という動きは既定ではしません。補助的な処理(関連リンクの取得など)が失敗しても本処理の結果は返したいなら、その処理をエージェント関数の中で例外を握りつぶして既定値を返す形にしておく必要があります。
AgentFilterによる呼び出し前後の処理と実行時間の計測
AgentFilterは、すべてのエージェント呼び出しの前後に割り込む関数です。Expressのミドルウェアのように、受け取った agent を自分で呼び、その前後にログ・計測・キャッシュなどの処理を挟みます。グラフ定義を変えずに横断的な処理を足せるので、本番のログ取りやデバッグはここで行います。次の例は、ノード名と所要時間を記録するフィルタです(filter.mjs として保存し node filter.mjs で実行)。
import { GraphAI, agentInfoWrapper } from "graphai";
import { copyAgent } from "@graphai/vanilla";
const sleepy = async ({ params }) => { await new Promise((r) => setTimeout(r, params.ms)); return { ms: params.ms }; };
// エージェント呼び出しの前後に割り込み、ノード名と所要時間を記録する
const timingFilter = async (context, agent) => {
const t0 = Date.now();
const result = await agent(context);
console.log(`[${context.debugInfo.nodeId}] ${context.debugInfo.agentId} ${Date.now() - t0}ms`);
return result;
};
const graphData = {
version: 0.5,
nodes: {
a: { agent: "sleepy", params: { ms: 300 } },
b: { agent: "sleepy", params: { ms: 100 } },
c: { agent: "copyAgent", inputs: { a: ":a.ms", b: ":b.ms" }, isResult: true },
},
};
const agents = { copyAgent, sleepy: agentInfoWrapper(sleepy) };
console.log("-- 全ノード");
await new GraphAI(graphData, agents, { agentFilters: [{ name: "timingFilter", agent: timingFilter }] }).run();
console.log("-- agentIds: [sleepy] に限定");
await new GraphAI(graphData, agents, { agentFilters: [{ name: "timingFilter", agent: timingFilter, agentIds: ["sleepy"] }] }).run();
実行結果です。
-- 全ノード
[b] sleepy 100ms
[a] sleepy 300ms
[c] copyAgent 0ms
-- agentIds: [sleepy] に限定
[b] sleepy 102ms
[a] sleepy 302ms
フィルタは GraphAI の第3引数 agentFilters に配列で渡し、agentIds を付けると特定のエージェントだけに効きます(型定義にはノード名で絞る nodeIds もあります)。ログは終わった順に出るので、a と b が同時に走り、短い b が先に終わったことも読み取れます。よく使う処理は公式のフィルタとして配布されています(版はnpmの2026年10月23日時点)。
| パッケージ | 最新版 | 用途 |
|---|---|---|
| @graphai/cache_agent_filter | 2.0.2 | getCache・setCacheを渡して結果をキャッシュ |
| @graphai/stream_agent_filter | 2.0.3 | LLMのトークンを逐次受け取る(サーバー・クライアント両方) |
| @graphai/http_client_agent_filter | 2.0.1 | エージェントの実行をHTTPでサーバーへ委ねる |
| @graphai/step_runner_agent_filter | 2.0.3 | コンソールで1ステップずつ実行してデバッグ |
| @graphai/namedinput_validator_agent_filter | 2.0.1 | エージェントの入力スキーマで入力値を検証 |
前述のCLIで依存不足になっていたのは、表の最後の入力検証フィルタです。@graphai/agent_filters を入れると、5つをまとめて導入できます。
LangGraphとの違いとGraphAIを選ぶ条件
名前が似ているため、LangChain社の LangGraphでAIエージェントを実装する手順:状態管理から承認フローまで と比べられることがよくあります。設計思想は大きく違います。
| 観点 | GraphAI | LangGraph |
|---|---|---|
| 言語 | TypeScript / JavaScript | Python / JavaScript |
| グラフの書き方 | YAML・JSONで宣言 | コードでノードとエッジを追加 |
| 依存の決まり方 | 入力の参照から自動 | エッジを明示 |
| 巡回 | 不可(loopで全体を反復) | エッジで巡回可 |
| 並行実行 | 依存の無いノードを自動並行 | 同じステップのノードを並行 |
| ライセンス | MIT | MIT |
GraphAIが向いているのは、処理の流れが「入力を集めて、並べて、まとめる」パイプライン型の場合です。RAGの前処理(検索・分割・埋め込み・並べ替え)や、複数のLLMに同じ問いを投げて比較する処理は、依存を書くだけで並行化されます。グラフがYAMLなので、コードを書かない担当者が手順を読んで修正できる点も利点です。
反対に、採用を見送るべき場面もはっきりしています。チームの主言語がPythonで、会話の状態を保存して途中から再開したり、人の承認を挟んで分岐を戻したりする必要があるなら、LangGraphを選ぶべきです。GraphAIの巡回は「グラフ全体の反復」でしか表現できず、状態機械のように任意のノードへ戻る設計は書きにくくなります。採用前には、自分たちが使うエージェントの公式サンプルとIssueを確認し、問題が起きたときにソースコードを調査できる体制を用意してください。前述のCLIの依存不足のような不具合を自分で調べて回避できるチーム向けです。AIエージェントの業務組み込みを設計から相談したい場合は、AIエージェント開発の支援もご覧ください。
TypeScriptでエージェントを組む選択肢としてはMastraやLangChain.jsもあります。各フレームワークの比較は AIエージェントフレームワークとは?主要8種の比較・動作コード・選定基準【2026年9月版】 にまとめています。
よくある質問
GraphAIのGitHubリポジトリと公式ドキュメントはどこですか?
リポジトリは GitHubのreceptron/graphai、公式サイトは graphai.info です。公式サイトには日本語版もあり、チュートリアルを日本語で読めます。ノードのプロパティなどの仕様はリポジトリ内の packages/graphai/README.md、エンドユーザー向けのサンプルは receptron/graphai_samples にあります。
「グラフ AI」で探しているのがグラフ作成ツールの場合は?
GraphAIは表やデータから棒グラフ・円グラフを描くツールではなく、AIの処理手順をグラフ構造で組むための開発用ライブラリです。グラフ作成が目的なら、表計算ソフトやBIツールに付いているAI機能を探す方が近道です。
GraphAIはPythonから使えますか?
receptronのGraphAIはnpmで配布されるTypeScript / JavaScript実装で、Pythonのパッケージはありません(本体はNode.jsのほかブラウザでも動作します)。Pythonで書いた処理を組み込むなら、@graphai/http_client_agent_filter でエージェントの実行をHTTPサーバーへ委ねる方法があり、FastAPIで書いたサンプル receptron/graphai-python-server があります(最終更新は2024年6月30日)。PyPIの graphai-lib はAurelio AIの別ライブラリで、receptron版のYAMLは動きません。Pythonだけでグラフ構造のエージェントを組むなら、graphai-lib かLangGraphが候補です。
GraphAIは無料で使えますか?
GraphAI本体と公式エージェントはMITライセンスで、商用でも無料です。ただし openAIAgent などが呼び出すLLMのAPI料金は、各サービスの料金体系で別にかかります。
GraphAIとグラフ理論はどう関係しますか?
GraphAIのグラフは、グラフ理論でいう有向非巡回グラフ(DAG)です。ノードが頂点、入力の参照が有向辺にあたります。巡回がなければ依存関係に沿った実行順を作れますが、その順序は一意とは限らず、独立したノードは並行実行できます。頂点・辺・DAGの基礎は グラフ理論とは?頂点と辺の基礎から最短経路・グラフDB・GNNの実装応用まで で説明しています。