mcpField
A
ai-agent

ai-agent

github.com/rivet-devエージェントワークフロー441.2k 回インストール1 日前に更新
リポジトリ

ai-agent について

対話ごとに永続メモリーを持つ AI エージェントバックエンドを構築するための RivetKit スキルです。キュー処理やストリーミング応答、サンドボックス型コーディングエージェントの例を含みます。

主な機能

  1. 01対話ごとに1つの Rivet Actor
  2. 02永続化される対話状態
  3. 03メッセージキューの逐次処理
  4. 04ストリーミング応答の配信
  5. 05サンドボックス型コーディングエージェント

活用シーン

  1. 01対話ごとのメモリーを持つチャットエージェントの構築
  2. 02対話内のメッセージを順番に処理
  3. 03隔離サンドボックスでのコーディングエージェント作成

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/rivet-dev/skills --skill ai-agent

インストール後、Claude Code で/ai-agentを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

BASE_SKILL.md
index.json
openapi.json
reference/actors/
access-control.md
actions.md
actor-runtime-socket.md
appearance.md
authentication.md
communicating-between-actors.md
connections.md
debugging.md
design-patterns.md
destroy.md
errors.md
events.md
fetch-and-websocket-handler.md
helper-types.md
http-api.md
input.md
inspector-tabs.md
keys.md
kv.md
lifecycle.md
limits.md
metadata.md
queues.md
reference/actors/quickstart/
backend.md
cloudflare.md
effect.md
next-js.md

詳細

AI エージェント

重要:作業を始める前に、このスキルのディレクトリにある BASE_SKILL.md を必ず読んでください。デバッグ、エラー処理、状態管理、デプロイ、プロジェクトのセットアップに関する重要なガイダンスが記載されています。これらのルールとパターンは、すべての RivetKit の作業に適用されます。以下は、すでに読んで内容を理解していることを前提としています。

実装例

参考となる実装が必要な場合は、以下のテンプレートにある動作する実装例のコードを直接読んでください。

RivetKit で AI エージェントのバックエンドを構築するためのパターンです。各会話は、メモリ、メッセージキュー、ストリーミング出力を管理する 1 つの Rivet Actor になります。

スターターコード

GitHub にある動作する実装例のいずれかを使い、必要に応じて変更してください。以下のセクションでは、特に別のバリエーションが指定されていない限り、主要な ai-agent の実装例について説明します。

バリエーションスターターコード使用する場面
キュー駆動の AI SDK エージェントGitHub各会話が独自の永続メモリを保持し、メッセージを一度に 1 つずつ処理する、ストリーミング対応のチャットエージェントが必要な場合。
サンドボックス型コーディングエージェントGitHubDocker、Daytona、または E2B を使い、隔離されたサンドボックス内でコーディングエージェント(デフォルトでは Codex)を実行する場合。
耐久性のあるストリームを使うエージェント(実験的)GitHubアクターの状態やイベントではなく、耐久性のあるストリームを使って、プロンプトと応答を再生可能かつ再起動に耐える形で配信したい場合。

会話メモリ

会話またはエージェントの ID をキーとして、会話ごとに 1 つのアクターを使います(アクターキーを参照)。エージェントアクターの永続的な状態が会話メモリになります。ai-agent の実装例では、messages と status は JSON アクター状態に保存され、外部データベースなしでスリープや再起動後も保持されます。モデルを呼び出すたびに、c.state.messages とシステムプロンプトからプロンプトが再構築されるため、メモリと推論への入力は同じデータになります。

バリエーションメモリの保存場所永続化される状態フィールド
ai-agentJSON アクター状態messages、status
sandbox-coding-agentJSON アクター状態とサンドボックスの ACP セッションmessages、status、sessionId
experimental-durable-streams-ai-agent耐久性のあるストリーム。アクターには会話 ID と読み取りカーソルのみを保存conversationId、promptStreamOffset

メッセージ処理

ai-agent の実装例では、クライアントは agent.connection.send("message", { text, sender }) を使って、ユーザー入力をエージェントの message キューに追加します。これはキューへの追加であり、アクションの呼び出しではありません。エージェントの run フック(ライフサイクルを参照)は、for await (const queued of c.queue.iter()) を使ってキューを順番に消費します。

キューを順番に消費することで、会話ごとの並行処理が保証されます。アクターごとにモデル呼び出しが実行中になるのは最大 1 つであり、追加のロックは必要ありません。status フィールド(モデル呼び出し中の thinking)は UI 向けのシグナルにすぎず、実際のロックは実行ループが担います。また、トークンストリーム内で c.aborted も確認するため、シャットダウン時には正常に終了します。

バリエーションメッセージの入力方法直列化の保証
ai-agentconnection.send 経由で message キューに追加run フックが c.queue.iter() を使い、キューからメッセージを一度に 1 つずつ取り出します。
sandbox-coding-agentキューを使わず、sendMessage アクションを呼び出す各呼び出しは、結果をブロードキャストする前にサンドボックスとの往復処理を待ちます。
experimental-durable-streams-ai-agentonWake から耐久性のあるプロンプトストリームをロングポーリングpromptStreamOffset はチャンクごとに永続化されるため、再起動後もプロンプトを再処理せずに再開できます。

ストリーミング応答

ai-agent アクターは、モデルのテキスト差分ごとに response イベントをブロードキャストします。ペイロードには messageId、トークンごとの delta、累積された content、done フラグ(失敗時には error も)が含まれるため、クライアントは差分を追加することも、content を使って messageId ごとにメッセージを冪等に置き換えることもできます。サンプルのフロントエンドでは messageId ごとに置き換えるため、イベントが失われても問題ありません。最後のブロードキャストでは、空の delta、完全な content、done: true が含まれます。

アシスタントのメッセージオブジェクトは c.state.messages にあり、ストリーミング中にその場で変更されるため、ストリームの途中でアクターが再起動しても部分的なコンテンツは保持されます。サンプルではスロットリングなしで AI SDK の差分ごとにブロードキャストします。高トラフィックのデプロイで推奨される拡張機能は差分のバッチ処理またはスロットリングであり、サンプルでは実装されていません。

バリアントによる違い:sandbox-coding-agent は、サンドボックスの処理完了後に done: true の response ブロードキャストを 1 回送信します(段階的なストリーミングはありません)。experimental-durable-streams-ai-agent は、トークンごとのチャンクを永続的な応答ストリームに追加してから、responseComplete または responseError をブロードキャストします。

アーキテクチャ

トピック概要
トポロジーagentManager["primary"] シングルトンディレクトリと、会話ごとに 1 つの agent[agentId] アクター。
入力クライアントは connection.send を使って、AgentQueueMessage ペイロードをエージェントの message キューにプッシュします。
ストリーミングモデルの差分ごとに response を 1 回ブロードキャストし、最後に done: true を含むブロードキャストを送信します。
メモリ会話履歴全体とステータスは JSON アクター状態に保持されます。外部データベースは使用しません。

マネージャーは AgentInfo レコードを作成し、アクター間通信を通じて各エージェントを起動します。具体的には、createAgent が c.client<typeof registry>() を呼び出し、続いて client.agent.getOrCreate([info.id]) を呼び出して getStatus() を待機するため、クライアントの接続前に会話アクターが作成されます。サンドボックスのバリアントでは、エージェントと同じキーを共有する codingSandbox アクター(codingSandbox.getOrCreate([c.key[0]]))を加えてこのトポロジーを拡張するため、エージェントとサンドボックスの対応関係はキー空間に暗黙的に含まれます。

アクター

  • キー:agentManager["primary"]

  • 役割:ディレクトリアクター。AgentInfo レコードを作成し、エージェントを一覧表示し、c.client() を通じて各エージェントアクターを起動します。

  • アクション

    • createAgent
    • listAgents
  • キュー

    • なし
  • 状態

    • JSON
    • agents
  • キー:agent[agentId]

  • 役割:会話ごとに 1 つのアクター。メッセージ履歴全体とステータスを保持し、run ループでキューに入ったユーザーメッセージを処理し、AI SDK を通じてモデルを呼び出し、ストリーミング差分をブロードキャストします。

  • アクション

    • getHistory
    • getStatus
  • キュー

    • message
  • イベント

    • messageAdded
    • status
    • response
  • 状態

    • JSON
    • messages
    • status

ライフサイクル

sequenceDiagram
	participant C as Client
	participant AM as agentManager
	participant A as agent
	participant LLM as Model API

	C->>AM: createAgent(name)
	AM->>A: getOrCreate([info.id]) + getStatus()
	AM-->>C: AgentInfo
	C->>A: connection.send("message", {text, sender})
	Note over A: run loop pops queue via c.queue.iter()
	A-->>C: messageAdded (user message)
	A-->>C: messageAdded (assistant placeholder)
	A-->>C: status (thinking)
	A->>LLM: streamText(system prompt + history)
	loop each text delta
		LLM-->>A: delta
		A-->>C: response {messageId, delta, content, done: false}
	end
	A-->>C: response {delta: "", content, done: true}
	A-->>C: status (idle)

セキュリティチェックリスト

最小限の構成を保つため、サンプルには認証機能が含まれていません。エージェントのバックエンドを公開する前に、以下の基本対策を適用してください。

  • API キーはサーバー側に保持する:OPENAI_API_KEY(または ANTHROPIC_API_KEY)は、アクタープロセス内の AI SDK によって読み込まれます。キーがブラウザーに渡ることはありません。クライアントは RivetKit 経由でのみアクターと通信します。サンドボックス版ではキーをサンドボックスの環境変数に渡し、クライアントには渡しません。
  • 認証を追加する:サンプルには認証機能がないため、サーバーにアクセスできる人なら誰でもエージェントを作成、一覧表示でき、キーを推測できたエージェントにメッセージを送信できます。推奨される拡張として、スコープ付きトークンを使用する onBeforeConnect または createConnState のチェックを追加してください。認証を参照してください。
  • キューペイロードを検証し、レート制限を設定する:サンプルでは、text が文字列ではない本文を除外するだけです。推奨される拡張として、ペイロードサイズの上限、スキーマ検証、接続ごとのレート制限を適用してください。
  • 送信者の ID はサーバー側で決定する:サンプルでは、クライアントから渡された sender フィールドをそのまま信頼します。代わりに、送信者の ID を認証済みの接続に紐付けてください。
  • メッセージ履歴に上限を設けるか、短縮する:サンプルでは上限を設けず、モデル呼び出しのたびに会話履歴全体を送信します。プロンプトと状態が肥大化しないよう、推奨される拡張として古いメッセージを短縮または要約してください。
  • 会話ごとにコストの上限を設定する:推奨される拡張として、エージェントごとのトークン予算とクォータを追加してください。サンドボックス版では実際の計算処理が実行されるため、ユーザーごとのサンドボックスクォータも適用し、サンドボックスからのネットワーク送信を制限してください。

リファレンスマップ

アクター
CLI
クライアント
クックブック
デプロイ
全般
セルフホスティング

コメント