inngest-agents について
inngest-agentsは、Inngest AgentKitを使ったAIエージェントや複数ステップのワークフローの構築、移行、デバッグを支援するスキルです。永続実行、ツールの副作用、人による承認、リアルタイム進捗を扱います。
主な機能
- 01Inngest関数によるAgentKitの永続実行
- 02step.aiによるモデル呼び出しの再試行とキャッシュ
- 03ツールの副作用の永続的な処理
- 04人の承認や外部コールバックの待機
- 05ワークフロー進捗のリアルタイム配信
- 06エージェント評価のガイダンス
活用シーン
- 01サポートやリサーチ用エージェントの構築
- 02既存エージェントの永続ワークフローへの移行
- 03エージェント操作への人の承認追加
- 04再試行や副作用の重複のデバッグ
MCP 対応
MCP サーバーを呼び出すエージェントを扱い、副作用のあるツールをInngestの永続ステップで実行する方法を案内します。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ inngest/ inngest-skills --skill inngest-agentsインストール後、Claude Code で/inngest-agentsを入力して読み込まれたか確認します。
詳細
Inngest エージェント
ユーザーが AI エージェント、複数ステップの AI ワークフロー、ツール呼び出しループ、サポートエージェント、リサーチエージェント、Human-in-the-loop のレビューフロー、またはリアルタイムのエージェント UI を構築、移行、デバッグしたい場合にこのスキルを使用します。
Inngest の AgentKit では createAgent を使ってエージェントを定義します。AgentKit の実行が Inngest 関数によって所有されている場合、モデル呼び出しには Inngest の step.ai が使われるため、モデル結果が耐久性をもってリトライ・キャッシュされます。データベースの読み書き、ツールの副作用、待機、承認、リアルタイムの進捗、フロー制御には、エージェントの周囲でより低レベルの Inngest ステッププリミティブを使用してください。
公式リファレンス:
- AgentKit エージェント: https://agentkit.inngest.com/concepts/agents
createAgent: https://agentkit.inngest.com/reference/create-agent- AI 推論と
step.ai: https://www.inngest.com/docs/features/inngest-functions/steps-workflows/step-ai-orchestration - Agent Evals: https://www.inngest.com/docs/learn/agent-evals
- AgentKit リアルタイムフック: https://www.inngest.com/changelog/2025-09-24-agentkit-use-agent
コピー可能な例
耐久性のあるサポートエージェントまたはツール呼び出しエージェントをゼロから始める場合は、../../examples/durable-agent にある付属の例を確認してください。ここには期待されるエージェントファーストの形が示されています。すばやい HTTP トリガー、型付きイベント、Inngest 関数内の AgentKit、ステップスコープのコンテキスト読み込み、step.waitForEvent による人手承認、承認後の耐久性のある副作用です。
エージェントに Inngest を使うべき場合
適しているケース:
- エージェントが単一の HTTP リクエストより長くかかる可能性がある。
- エージェントがツール、API、データベース、ブラウザ、サンドボックス、または MCP サーバーを呼び出す。
- エージェントがデプロイ、クラッシュ、サーバーレスのタイムアウト、またはモデル/API の障害を乗り越える必要がある。
- エージェントが人手による承認、外部コールバック、スケジュールされたフォローアップ、またはユーザー入力を待つ可能性がある。
- エージェントの進捗を耐久性のあるワークフローから UI にストリーミングする必要がある。
- モデル/プロバイダーの呼び出しに並行性またはスロットルの制限が必要である。
- 重複した送信、課金、書き込み、またはモデル呼び出しが高コストになる。
通常は価値がないケース:
- 短時間で読み取り専用のモデル呼び出しが 1 回だけで、副作用がなく、耐久性のある進捗も不要である。
- リクエストを失っても許容できる UI 専用のオートコンプリート。
アーキテクチャ
リポジトリにすでにより強力な確立されたパターンがない限り、この形を使用してください:
- HTTP/サーバーアクション層が認証を検証し、必要に応じてユーザーの意図を保存し、安定した
idを持つイベントを送出し、すばやく応答を返します。 - Inngest 関数がエージェントの実行を所有します。
step.runの中で状態と外部コンテキストを読み込みます。- 関数内で AgentKit エージェントを作成するか、エージェント/ネットワークのファクトリをインポートします。
- モデル推論は AgentKit /
step.aiを通じて実行し、モデル以外のツールの副作用はstep.runでラップします。 - 人手による承認と外部コールバックには
step.waitForEventまたはstep.waitForSignalを使用します。 - ネイティブのリアルタイム機能で耐久性のある進捗を発行します。
- エージェントの成果を後で評価する必要がある場合は、セッションとスコアを追加します。
- プロバイダーとテナントの制限のために、関数レベルでフロー制御を適用します。
基本的な AgentKit 関数
まずは小さく型付きの関数を優先してください。単一エージェントのパスが証明された後に、ネットワークや追加のツールを加えます。
import { createAgent, openai } from "@inngest/agent-kit";
import { inngest } from "@/inngest/client";
export const summarizeTicket = inngest.createFunction(
{
id: "summarize-ticket",
triggers: [{ event: "support/ticket.created" }],
concurrency: [{ key: "event.data.accountId", limit: 2 }]
},
async ({ event, step }) => {
const ticket = await step.run("load-ticket", () => {
return getTicket(event.data.ticketId);
});
const writer = createAgent({
name: "support-summary-writer",
system: "Write a concise support-ticket summary with next actions.",
model: openai({ model: "gpt-4o" })
});
const { output } = await writer.run(JSON.stringify(ticket));
await step.run("save-summary", () => {
return saveTicketSummary(event.data.ticketId, output);
});
return { ticketId: event.data.ticketId };
}
);
ツール呼び出し
ツールは AgentKit で定義できますが、エージェントにとって安全なツールは依然として耐久性のルールに従う必要があります:
- 読み取り専用のツール呼び出しは、リプレイしても害がない場合にはエージェントの一部として実行できます。
- 外部の副作用は、安定した ID と
step.runの境界で分離するか、提供されたstepを使用するツールハンドラーとして実装する必要があります。 - ツールの出力は、ステップ状態の制限に収まる程度に小さくする必要があります。
- ツールのパラメーターはスキーマで検証してください。モデルが提供した引数を決して信用しないでください。
- 認証されたイベントデータからテナント/ユーザー ID を使用し、モデルのテキストだけに依存しないでください。
ツールの副作用チェックリスト:
- What external state can this tool change?
- What idempotency key prevents duplicate writes?
- What should happen if the model calls the same tool twice?
- Is the output safe to store in function run state?
- Does the tool need provider-specific concurrency or throttle limits?
Human in the Loop
データベースをポーリングしたり、状態をメモリに保持したりする代わりに、耐久性のある待機を使用してください。
const approval = await step.waitForEvent("wait-for-approval", {
event: "support/reply.approved",
timeout: "3d",
match: "data.ticketId"
});
if (!approval) {
await step.run("mark-review-timeout", () => {
return markTicketNeedsManualReview(event.data.ticketId);
});
return { status: "timed_out" };
}
await step.run("send-reply", () => {
return sendSupportReply({
ticketId: event.data.ticketId,
approvalId: approval.data.approvalId
});
});
リアルタイムの進捗
v4 ネイティブのリアルタイムでは:
- ステップ間で
step.realtime.publishを使用します。 - 既存の
step.run内ではinngest.realtime.publishを使用します。 - v4 プロジェクトでは v3 の
@inngest/realtimeパッケージをインストールしないでください。 - プロセスローカルの WebSocket を、永続関数の進捗の唯一のソースとして構築しないでください。
AgentKit 固有の UI フックについては、useAgent や useChat を組み込む前に、インストールされている @inngest/agent-kit のバージョンと最新のドキュメントを確認してください。
エージェントの評価
ユーザーがエージェントのスコアリング、プロンプトやモデルの比較、ユーザーフィードバックの追跡、会話/チケットごとの実行のグループ化、または時間経過に伴うエージェント品質のデバッグを求めた場合は、inngest-agent-evals を使用します。永続的なエージェントワークフローでは、ユーザーフローを開始または接続するイベントで meta.sessions を追加し、実行中に判明するシグナルには直接スコアリングを使用し、後から到着するプロダクト成果には遅延スコアラーを使用します。
フロー制御とコスト
エージェントのワークロードでは、多くの場合、プロバイダーとテナントの制限が必要です:
- モデルプロバイダーには、アカウントスコープの並行性またはスロットルキーを使用します。
- 公平性が重要な場合は、テナントまたはアカウントごとにキーを設定します。
- 決定的なイベント ID を使用して、重複したユーザー操作が重複した高コストの実行を生み出さないようにします。
- 成功したモデル/ツールの結果をステップに保持し、後続の失敗を再試行しても以前のモデル呼び出しに再度課金されないようにします。
例:
{
id: "support-agent-run",
triggers: [{ event: "support/agent.requested" }],
throttle: {
limit: 120,
period: "1m",
key: `"openai"`
},
concurrency: [
{ key: "event.data.accountId", limit: 3 }
]
}
ブラウンフィールド移行
既存のエージェントを移行する場合:
- モデル呼び出し、ツールループ、インメモリ状態、ストリーミングハンドラー、承認ポーリング、および外部の副作用を検索します。
- まずはプロンプト/ツールの動作を安定させたままにします。
- トリガーをイベントと Inngest 関数に移動します。
- モデル呼び出しを AgentKit /
step.aiに移動します。 - 副作用のあるツールを
step.runまたは永続的なツールハンドラーに移動します。 - プロセスローカルの待機を
step.waitForEventまたはstep.waitForSignalに置き換えます。 - 永続的な実行が機能した後にリアルタイムを追加します。
リポジトリに複数の可能なワークフローがあり、ユーザーがどれを選んでいない場合は、まず inngest-brownfield-audit を使用してください。
アンチパターン
- エージェントのループ状態をメモリ内にのみ保持する。
- すべてのモデル呼び出しとツール呼び出しを囲む 1 つの巨大な
try/catch。 - 1 つのツールの失敗後にエージェント全体を再試行する。
- 後続のステップが失敗した後に、成功したモデル呼び出しに対して繰り返し課金する。
- 人によるレビューの仕組みとして
setTimeout、cron ポーリング、または Redis TTL を使用する。 - 冪等性キーのない副作用のあるツール。
- 永続的な処理が別の場所で継続している間に停止する可能性のあるサーバープロセスから進捗をストリーミングする。
- 周囲の Inngest 関数を登録せずに AgentKit を追加する。
検証
- エージェント、ツールスキーマ、およびイベントペイロードを型チェックします。
- ツールハンドラーをモデルの動作とは別に単体テストします。
- HTTP エントリポイントが 1 つの決定的なイベントを発行し、迅速に返すことをテストします。
- 重複したイベント ID が最終的な副作用を重複させないことをテストします。
- 可能であれば、Inngest 開発サーバーを実行し、エージェントのステップ/トレースを検査します。