AgentChat
← すべての記事
アーキテクチャ·10分で読めます

既存のAPIを使ってSaaSにAIエージェントを追加する方法

既存のプロダクトAPIを、アクションごとにカスタムツールを構築することなく、安全なエージェント機能へ変えるための実践的アーキテクチャ。

このガイドでは、SupportFlowという架空のSaaS向けに、AgentChatとの完全な統合を実装します。SupportFlowには、期限超過した請求書の検索、リマインダーの送信、アカウントメモの追加を行うAPIがすでに用意されています。これらのAPIをAgentChatにプロビジョニングし、ユーザー単位のチャットを作成し、非同期のエージェント実行を開始して、永続化されたメッセージとSupportFlow独自のデータベースから結果を表示します。

重要なアーキテクチャ上の境界は明確です。AgentChatは、モデルによる推論、ツールの選択、チャット履歴、実行制御を担当します。SupportFlowは引き続き、顧客、請求書、認可、検証、最終的な業務記録を管理します。APIドキュメントが両システムをつなぎます。

すべてのSaaS機能をエージェントランタイムに追加する必要はありません。中核となる業務操作を少数のHTTP APIとして公開し、そのコントラクトを各チャットにプロビジョニングします。

完了したリクエストフロー

  1. SupportFlowはダッシュボードからAgentChat APIキーを1つ作成し、それをバックエンドにのみ保存します。
  2. そのバックエンドは、POST /api/api-documents を使用してSupportFlowの操作を登録します。
  3. ユーザーがアシスタントを開くと、SupportFlowはドキュメントUUID、LLM設定UUID、およびAPIホスト用の書き込み専用ユーザー認証情報を使ってセッションを作成します。
  4. SupportFlowはユーザーメッセージを POST /api/agent/sessions/{id}/chat に送信します。
  5. AgentChatは添付された契約書を読み込み、組み込みのhttp_requestツールを使用してSupportFlowを呼び出します。
  6. SupportFlowはAgentChatのメッセージをポーリングする一方、通常のUIはSupportFlowのデータベースから請求書とメモを読み取ります。

ステップ1:限定された業務操作を公開する

エージェントにデータベースへのアクセスや、巨大な単一の内部APIは必要ありません。このワークフローでは、SupportFlowはテナント対応のエンドポイントを正確に3つ公開します:

GET /v1/invoices?status=overdue&limit=3
→ { "items": [{ "invoice_id": "inv_72", "account_id": "acct_9", "amount": 480, "currency": "USD", "due_at": "2026-08-01" }] }

POST /v1/reminders
{ "invoice_id": "inv_72", "tone": "friendly" }
→ { "reminder_id": "rem_31", "status": "queued" }

POST /v1/accounts/acct_9/notes
{ "body": "Friendly reminder queued for overdue invoice inv_72." }
→ { "note_id": "note_55", "created_at": "2026-08-23T09:30:00Z" }

各エンドポイントは呼び出し元を認証し、認証情報からテナントを導出して、すべてのデータベース操作にフィルターを適用します。ある呼び出しで返されたIDは、次の呼び出しへの安全な入力になります。モデルがデータベースのパスワードや、制限のないクエリインターフェースを受け取ることはありません。

ステップ2:モデル設定を一度作成する

AgentChatのすべてのセッションには、ユーザーが所有するLLM設定が必要です。SupportFlowでは、ダッシュボードまたはAPIを通じて設定を作成し、返されたUUIDを保持できます。

POST $AGENTCHAT_SITE_URL/api/llm-config
Authorization: Bearer ac_live_AGENTCHAT_KEY
Content-Type: application/json

{
  "name": "Support production model",
  "api_url": "https://llm-provider.example.com/v1/chat/completions",
  "api_key": "provider_secret",
  "model": "provider-model-name",
  "max_context_length": 128000,
  "max_output_tokens": 8192,
  "temperature": 0.2,
  "disable_reasoning": false
}

レスポンスは success と data にラップされます。チャット作成時に使用する llm_config_id として、data.id を保存してください。AgentChatでは、設定を読み込む際にプロバイダーキーがマスクされます。

ステップ3:SupportFlow APIドキュメントを用意する

これがプラグインの仕組みです。このドキュメントには、運用上の指示、正確な入力、正確な出力、処理順序のルールが記載されています。マーケティング文句でも、エージェントに推測を強いるリンクでもありません。

POST $AGENTCHAT_SITE_URL/api/api-documents
Authorization: Bearer ac_live_AGENTCHAT_KEY
Content-Type: application/json

{
  "title": "SupportFlow Invoice Actions",
  "description": "Find overdue invoices, queue reminders, and record account notes.",
  "content": "# SupportFlow Invoice Actions\nBase URL: https://support.example.com/v1\n\nGET /invoices?status=overdue&limit=3 returns items with invoice_id, account_id, amount, currency, and due_at. Use only when the user requests invoice lookup.\n\nPOST /reminders body: invoice_id required; tone is friendly or firm. Response: reminder_id and status. Never send more reminders than the user requested.\n\nPOST /accounts/{account_id}/notes body: body required. Call only after the reminder request succeeds. Include the invoice ID and reminder status in the note.\n\nIf any write returns 401 or 403, stop writing and explain that the session credential needs access. Do not retry a permission denial."
}

AgentChatはUUIDを含む新しいドキュメントをdataに返します。そのUUIDをSupportFlowのインテグレーション設定に保存してください。後でこのドキュメントを更新すると、セッションはドキュメントをコピーするのではなく添付するため、以降のチャットターンで使用される指示が変更されます。

ステップ4:現在のSupportFlowユーザー用のチャットを作成する

POST $AGENTCHAT_SITE_URL/api/agent/sessions
Authorization: Bearer ac_live_AGENTCHAT_KEY
Content-Type: application/json

{
  "title": "Invoice assistant for user_42",
  "llm_config_id": "llm_config_uuid",
  "api_document_ids": ["supportflow_document_uuid"],
  "system_prompt": "Act only on the user’s explicit request. Summarize every write with the affected invoice and account IDs.",
  "compact_threshold_percent": 80,
  "max_turns": 12,
  "tool_timeout_seconds": 120,
  "tool_result_max_chars": 10000,
  "host_headers": [
    { "host": "support.example.com", "header_key": "Authorization", "header_value": "Bearer short_lived_user_42_token" },
    { "host": "support.example.com", "header_key": "X-Workspace-ID", "header_value": "workspace_7" }
  ]
}

ヘッダー値は書き込み専用です。AgentChatはこのセッション用にヘッダー値を保存し、http_requestが一致するホストを対象とする場合にのみ注入します。また、その値をモデルやAPIレスポンスに公開することはありません。別のSupportFlowユーザーには、同じドキュメントUUIDを持ちながら異なるヘッダーを持つ別のセッションが割り当てられます。

ステップ5:非同期実行を開始する

POST $AGENTCHAT_SITE_URL/api/agent/sessions/session_uuid/chat
Authorization: Bearer ac_live_AGENTCHAT_KEY
Content-Type: application/json

{ "message": "Find my three most overdue invoices, send each a friendly reminder, and add a note to each account." }

→ { "success": true, "data": { "session_id": "session_uuid", "state": "processing" } }

AgentChat は直ちに応答を返し、バックグラウンドで実行を継続します。エージェントは、添付された SupportFlow ドキュメントに加えて、組み込みツールをちょうど4つ(get_api_document、http_request、sleep、view_image)受け取ります。SupportFlow の機能がこれらのツールに組み込まれているわけではありません。提供された API コントラクトから学習し、http_request を通じて実行します。

このリクエスト中にエージェントが行うこと

  1. 文書化された延滞請求書エンドポイントを http_request を通じて呼び出します。
  2. 構造化された項目を読み取り、ユーザーが要求した請求書のうち最大3件を選択します。
  3. リマインダーをキューに追加します。1つのモデル応答によって生成された独立した呼び出しは、同時に実行できます。
  4. リマインダーの成功結果が利用可能になった後、返された各請求書とアカウントIDを使用してアカウントノートエンドポイントを呼び出します。
  5. 完了した操作と、請求書ごとの失敗があればそれを一覧にした最終アシスタントメッセージを作成します。

これが、レスポンス設計が重要な理由です。曖昧な「成功」結果では、エージェントが次のアクションに確実に結び付けられるものが何も残りません。構造化されたIDとステータスにより、推論ループは複数の一般的なAPIを組み合わせて、1つのユーザー向けの結果を実現できます。

ステップ6:LLMストリームではなく、永続メッセージをポーリングする

GET $AGENTCHAT_SITE_URL/api/agent/sessions/session_uuid/messages?after_id=&after_revision=0
Authorization: Bearer ac_live_AGENTCHAT_KEY

→ {
  "success": true,
  "data": {
    "messages": [{ "id": "message_uuid", "role": "assistant", "content": "...", "stream_status": "streaming", "revision": 4 }],
    "last_id": "message_uuid",
    "last_revision": 4,
    "is_processing": true,
    "total_tokens": 2840
  }
}

SupportFlowはバックエンドまたはプロキシ経由のクライアントから1秒に1回ポーリングし、メッセージIDごとに行をマージして、リビジョンが増加した場合にのみ内容を置き換えます。会話の出力については、AgentChatのデータベースが信頼できる唯一の情報源です。請求書、リマインダー、メモについては、SupportFlowのデータベースが引き続き信頼できる唯一の情報源となります。

is_processingがfalseになると、SupportFlowは請求書とアカウントのクエリを更新できます。その後、通常の製品UIには、自身のAPIを通じて作成されたリマインダーとメモが表示されます。ビジネス状態を再構築するために、アシスタントの文章を解析する必要はありません。

実行制御と障害復旧

GET  /api/agent/sessions/session_uuid/state
POST /api/agent/sessions/session_uuid/stop
POST /api/agent/sessions/session_uuid/continue

stateエンドポイントは、処理がアクティブかどうか、および次のアクションがcontinueかどうかを報告します。Stopリクエストはアクティブな実行をキャンセルします。回復可能な失敗または最大ターン数の制限によって処理が一時停止した場合、continueは、新しいターン予算と同じ永続的な会話コンテキストを使用して別の実行を開始します。

プロビジョニングするもの、そしてプロビジョニングしないもの

  • 安定したビジネス機能を表すAPI(検索、作成、更新、検証、公開、ジョブのステータス確認など)をプロビジョニングします。
  • 必須フィールド、制約、レスポンスオブジェクト、エラーの意味、副作用、順序要件を文書化します。
  • すべての内部エンドポイントではなく、チャット体験に必要なドキュメントだけを添付します。
  • 認証情報はホスト固有のセッションヘッダーに保持し、プロンプトやAPIドキュメントの内容には決して含めません。
  • エージェントの柔軟性を高めるためだけに、生のSQL、無制限のファイルアクセス、または汎用的な内部プロキシを公開しないでください。
  • 他のクライアントに対して行っているのとまったく同じように、すべてのツールリクエストで独自の認可と検証を実行します。

コアツール群を増やさずに機能の対応範囲を広げられる理由

RAG製品では検索および引用エンドポイントをプロビジョニングできます。ストーリー製品では章、画像生成、公開用のエンドポイントをプロビジョニングできます。コーディング製品ではワークスペースファイル、チェック、デプロイ用のエンドポイントをプロビジョニングできます。AgentChatは引き続き同じ4つのコアツールを使用します。アプリケーション固有の操作はAPIドキュメントとして提供されるため、機能の追加は新しいエージェントランタイムのリリースではなく、プロビジョニングの変更で実現できます。

これがAgentChatの中核となるパターンです。APIドキュメントを作成し、スコープを限定したチャットセッションを作成し、エージェントにHTTP操作を組み立てさせ、永続メッセージを消費し、結果として得られるレコードを独自のアプリケーションデータベースからレンダリングします。