@openreachtech/mentsu-agent-loop-graphql
v1.0.2
Published
Mentsu agent loop graphql (by [email protected])
Keywords
Readme
@openreachtech/mentsu-agent-loop-graphql
@openreachtech/mentsu-agent-loop-coreのエージェントを GraphQL から呼び出し・進捗購読するためのリゾルバ基底 を提供するパッケージです。 リクエスト受付(Mutation)と、ループ進捗のリアルタイム配信(Subscription)の 2 系統を薄い基底クラスで橋渡しします。
⚠️ ステータス: 設計確定 / 実装保留。 継承元となる renchan 系 GraphQL リゾルバ基底パッケージが未確定のため、実装を保留しています。 本 README は確定済みの 設計仕様(API 契約とサンプル) を記載します。フレームワーク確定後、本仕様に沿って実装・公開します。 (GraphQL を採用しない構成 — REST / tRPC など — では本パッケージは不要です。進捗配信はアプリ側で
AgentTopicチャンネルを購読してください。)
目次
概要
エージェントを Web から使うときの典型形は 「Mutation で投入 → 即 accepted を返す → Subscription で進捗を流す」 です。
本パッケージはこの 2 つのリゾルバを基底化し、アプリは数メンバーの宣言だけで GraphQL 連携を完成させられます。
BaseRequestAgentMutationResolver— GraphQL 変数をジョブ body に変換し、Dispatcher に enqueue。長時間処理を待たず{ accepted, jobId }を即返す。BaseAgentProgressSubscriptionResolver— Worker が publish した進捗を購読する。publish 側(Worker のchannel)と同じ コアのAgentTopicを使うため、チャンネル名が構造的に一致する。
buildTopic() がコアの AgentTopic.create(...).value を呼ぶことで、publish と subscribe の チャンネル不一致による「進捗が届かない」事故を設計で防ぎます。
依存方向は一方向(graphql → コア)。コアは GraphQL を知りません。
技術仕様
ランタイム / 配布(予定)
| 項目 | 値 |
| :-- | :-- |
| モジュール形式 | ESM ("type": "module") |
| Node | ≥ 18 |
| エントリ | lib/index.js(barrel) |
peerDependencies(予定)
| パッケージ | 役割 |
| :-- | :-- |
| @openreachtech/mentsu-agent-loop-core | コア(AgentTopic を参照) |
| renchan 系 GraphQL フレームワーク | 継承元のリゾルバ基底(確定待ち) |
実 enqueue は
@openreachtech/mentsu-agent-loop-renchan-jobの Dispatcher を使うのが標準構成です(直接の peer ではなく、アプリが配線する Dispatcher 経由)。
公開クラス一覧(設計仕様)
BaseRequestAgentMutationResolver(抽象)
リクエスト受付 Mutation。enqueue して即応答する。
| メンバー | 区分 | 説明 |
| :-- | :-- | :-- |
| async enqueue({ body, context }) | 推奨シーム | ジョブ body を enqueue し、dispatch 応答(hasResponse() / idKey)を返す。context.share からディスパッチ元を取得できる。デフォルトは後方互換のため get dispatcher に委譲する |
| get dispatcher() | 後方互換 | enqueue 先 Dispatcher。context に到達できないため非推奨。デフォルト enqueue からのみ参照される(実装済みの旧コードはそのまま動作) |
| buildJobBody({ variables }) | 抽象 | GraphQL 変数 → ジョブ body(=ループ入力) |
| async resolve({ variables, context }) | 最終 | enqueue({ body, context }) → { accepted: true, jobId } を即返す |
BaseAgentProgressSubscriptionResolver(抽象)
進捗購読 Subscription。
| メンバー | 区分 | 説明 |
| :-- | :-- | :-- |
| get channel() | 抽象 | Subscription チャンネル名(Worker の channel と共有) |
| generateChannelQuery({ variables }) | 抽象 | スコープ抽出(GraphQL 固有。例: { userId }) |
| buildTopic({ variables }) | 最終 | 内部で コアの AgentTopic.create(...).value を呼び、publish と構造一致 |
進捗の一気通貫(コア → フロント)
[コア] loop.run({ input, onProgress })
└ iterate が毎反復 emitProgress → onProgress(event)
[renchan-job] BaseAgentJobWorker が onProgress → job.updateProgress → onJobProgress
→ AgentTopic.create({ channel, scope }).value のチャンネルへ publish
[graphql] BaseAgentProgressSubscriptionResolver(同じ channel を購読)
[フロント] GraphQL Subscription でリアルタイム受信・表示publish(Worker)と subscribe(resolver)が同じ AgentTopic を使うため、チャンネル名は構造的に一致します。
利用方法
本パッケージは実装保留中です。以下は確定済みの設計に基づく 想定の利用フロー です。
インストール(予定)
npm install @openreachtech/mentsu-agent-loop-graphql
# peer
npm install @openreachtech/mentsu-agent-loop-core
# enqueue 用に renchan-job アダプタも併用するのが標準
npm install @openreachtech/mentsu-agent-loop-renchan-job @openreachtech/renchan-job-bullmq構成
- Mutation resolver —
BaseRequestAgentMutationResolverを継承し、enqueue(推奨。旧形式のget dispatcherも後方互換で可)とbuildJobBodyを実装。 - Subscription resolver —
BaseAgentProgressSubscriptionResolverを継承し、channel(Worker と同一)とgenerateChannelQueryを実装。 - アプリの GraphQL スキーマに Mutation / Subscription を登録する。
ユースケース
- 非同期エージェントの Web API 化 — 長時間ループをジョブ化し、Mutation は即
acceptedを返す(HTTP タイムアウト回避)。 - 進捗のリアルタイム表示 — エージェントの反復・途中経過を Subscription でフロントに逐次配信。
- ユーザー単位のスコープ配信 —
generateChannelQueryでuserId等を scope にし、購読を分離する。 - publish / subscribe のチャンネル一致保証 — Worker と resolver が同じ
AgentTopicを共有し、命名規則を一括管理する。
サンプルコード
題材は「動画 AI 検索エージェント」。Worker の channel('videoSearchProgress')と一致させます。
1. リクエスト受付 Mutation
// app/graphql/mutations/RequestVideoSearchMutationResolver.js
import { BaseRequestAgentMutationResolver } from '@openreachtech/mentsu-agent-loop-graphql'
import VideoSearchJobDispatcher from '../../jobs/videoSearch/VideoSearchJobDispatcher.js'
/**
* @extends {BaseRequestAgentMutationResolver}
*/
export default class RequestVideoSearchMutationResolver extends BaseRequestAgentMutationResolver {
/**
* 推奨シーム。context からディスパッチ元を取得して enqueue する。
*
* @override
*/
async enqueue ({
body,
context,
}) {
return context.share.jobDispatcherProvider.dispatchJob({
DispatcherCtor: VideoSearchJobDispatcher,
body,
})
}
/** @override */
buildJobBody ({
variables,
}) {
return {
keyword: variables.keyword,
userId: variables.userId,
}
}
}呼び出し側(GraphQL)には { accepted, jobId } が即返ります。
後方互換: 旧形式の
get dispatcher ()を実装した既存 resolver もそのまま動作します(resolveはデフォルトでdispatcher.dispatchJob({ body })に委譲)。新規実装ではcontext.shareに到達できるenqueueを推奨します。// 旧形式(引き続きサポート) export default class RequestVideoSearchMutationResolver extends BaseRequestAgentMutationResolver { /** @override */ get dispatcher () { return VideoSearchJobDispatcher } /** @override */ buildJobBody ({ variables }) { return { keyword: variables.keyword, userId: variables.userId } } }
2. 進捗購読 Subscription
// app/graphql/subscriptions/VideoSearchProgressSubscriptionResolver.js
import { BaseAgentProgressSubscriptionResolver } from '@openreachtech/mentsu-agent-loop-graphql'
/**
* @extends {BaseAgentProgressSubscriptionResolver}
*/
export default class VideoSearchProgressSubscriptionResolver extends BaseAgentProgressSubscriptionResolver {
/** @override */
get channel () {
return 'videoSearchProgress' // ← Worker の channel と同じ
}
/** @override */
generateChannelQuery ({
variables,
}) {
return {
userId: variables.userId,
}
}
}3. Redis 経路の全体フロー(再掲)
Mutation(RequestVideoSearchMutationResolver.resolve)
→ buildJobBody → enqueue({ body, context }) → dispatchJob({ body }) → 即 { accepted, jobId } 返却
→ Worker pickup → executeJob 内で loop.run({ input: body, onProgress })
→ onProgress → job.updateProgress(event) → onJobProgress
→ AgentTopic.create({ channel: 'videoSearchProgress', scope: { userId } }).value のチャンネルへ publish
→ VideoSearchProgressSubscriptionResolver が購読 → フロントへ配信4. GraphQL を使わず進捗を流す場合(参考)
GraphQL を採用しない、あるいは非Redis(in-process)構成では、本パッケージは不要です。
アプリ側で onProgress をそのまま broker に publish し、コアの AgentTopic チャンネルを購読してください。
import { AgentTopic } from '@openreachtech/mentsu-agent-loop-core'
const result = await videoSearchRunner.request({
input: { keyword, userId },
onProgress: event =>
subscriptionBroker.publish(
AgentTopic.create({ channel: 'videoSearchProgress', scope: { userId } }).value,
event
),
})関連パッケージ
| パッケージ | 役割 |
| :-- | :-- |
| @openreachtech/mentsu-agent-loop-core | コア(AgentTopic を参照)。本パッケージの peer |
| @openreachtech/mentsu-agent-loop-renchan-job | Redis 実行アダプタ。Mutation が enqueue する Dispatcher / 進捗を publish する Worker を提供 |
| @openreachtech/mentsu-agent-loop-graphql | 本パッケージ(GraphQL リゾルバ基底)※実装保留 |
ライセンス
本プロジェクトは Apache License 2.0 で公開されています。
詳細は LICENSE ファイル を参照してください。
開発者
著作権
© 2026 Open Reach Tech Inc.
