AceDataCloud AI Chat v2 でエージェント型アプリを構築する

チャットエンドポイントはテキストを返すことができます。エージェントエンドポイントは、ファイルを確認し、ウェブを検索し、認可されたツールを呼び出し、不足している情報を尋ね、そのすべてのステップをインターフェースにストリーミングで返すことができます。

これが、AceDataCloud AI Chat v2 の背後にある実践的な違いです。POST https://api.acedata.cloud/aichat2/conversations のエンドポイントは、元の会話 API のシンプルなリクエストスタイルを維持しながら、マルチモーダルコンテンツブロック、自律的な複数ラウンドのツール利用、MCP 接続、構造化ストリーミングイベント、再開可能な会話、および会話 CRUD アクションを追加します。

AI Chat v2 アーキテクチャ: マルチモーダル入力、エージェントツール、構造化イベント

このガイドでは、基本的なチャットボットから本番環境のエージェント体験へ移行する際に重要となる統合上の判断に焦点を当てます。

AI Chat v2 では何が変わるのか?

AI Chat v2 は、元の /aichat/conversations インターフェースを包括的にアップグレードしたものです。主な機能は次のとおりです。

  • マルチモーダル入力: 1 つの message 配列で、順序付けされた text、image_url、および file_url ブロックを送信します。
  • 自律的なツール利用: モデルは、複数ラウンドにわたって組み込みツールおよびユーザー認可済みの MCP サーバーを呼び出すことができます。
  • 型付きストリーミング: テキスト、ツールアクティビティ、引用、カード、アーティファクト、エラー、および完了データを個別のイベントとしてレンダリングします。
  • 一時停止と再開: ask_user_question イベントを処理し、ツール結果を使用して同じ会話を継続します。
  • 会話管理: 同じエンドポイント上のアクションを通じて、取得、一括取得、更新、および削除を行います。
  • 後方互換性のあるリクエスト: 既存の model + question クライアントは、エンドポイントパスを変更することで移行できます。

重要なアーキテクチャ上の変化は、フロントエンドがレスポンスを単一の不透明な文字列として扱う必要がなくなることです。イベント駆動型のワークスペースにすることができます。

後方互換性のあるパスから始める

最もリスクの低い移行は、意図的に小規模です。既存のリクエストボディを維持し、エンドポイントのみを変更します。

curl -X POST 'https://api.acedata.cloud/aichat2/conversations' \
  -H 'accept: application/json' \
  -H 'authorization: Bearer YOUR_API_TOKEN' \
  -H 'content-type: application/json' \
  -d '{
    "model": "YOUR_SUPPORTED_MODEL",
    "question": "Summarize the three most important points in this request.",
    "stateful": true
  }'

JSON モードでは、レスポンスは使い慣れた形式を維持します。

{
  "answer": "...",
  "id": "conversation-uuid"
}

返された id を保持してください。次のリクエストでこれを送信すると、クライアントが完全なメッセージ履歴を再送信しなくても、管理された会話を継続できます。

stateful のデフォルトは true です。ラウンドを保存しない場合は、明示的に false に設定してください。

この最初の移行ステップにより、ツールや新しいストリーミング UI を導入する前に、認証、モデルの可用性、レイテンシ、およびアプリケーションの動作を検証できます。

順序とモダリティが重要な場合は message を使用する

古い question フィールドは、テキストのみのプロンプトには便利です。画像やファイルを含むテキストには、順序付けされた message 配列を使用してください。

{
  "model": "YOUR_SUPPORTED_MODEL",
  "stateful": true,
  "message": [
    {
      "type": "text",
      "text": "Read the attached report and compare its chart with this screenshot. Return five findings."
    },
    {
      "type": "file_url",
      "file_url": {
        "url": "https://example.com/report.pdf"
      }
    },
    {
      "type": "image_url",
      "image_url": {
        "url": "https://example.com/dashboard.png"
      }
    }
  ]
}

サポートされるコンテンツブロックは次のとおりです。

ブロック 必須値 最適な用途
text text 指示、コンテキスト、および質問
image_url image_url.url スクリーンショット、グラフ、製品画像
file_url file_url.url PDF、CSV、TXT、およびその他のファイル

AI Chat v2 は古い references 配列も引き続き認識します。画像拡張子は画像ブロックに変換され、その他の URL はファイルブロックになります。この互換性は移行中に役立ちますが、コンテンツの順序が重要な場合、message の方が長期的にはより良い契約です。

クライアントをトークンだけでなくイベント中心に設計する

accept ヘッダーでレスポンス形式を選択します。

クライアント ヘッダー 形式
ブラウザ UI text/event-stream Server-Sent Events
Node、Python、CLI、ワーカー application/x-ndjson 1 行につき 1 つの JSON イベント
シンプルなバックエンドリクエスト application/json 最終的な {answer, id} オブジェクト

最小限の Python NDJSON コンシューマーは、他のイベントタイプを保持しながらテキストを組み立てることができます。

import json
import os
import requests

url = "https://api.acedata.cloud/aichat2/conversations"
headers = {
    "accept": "application/x-ndjson",
    "authorization": f"Bearer {os.environ['ACEDATA_API_TOKEN']}",
    "content-type": "application/json",
}
payload = {
    "model": os.environ["ACEDATA_CHAT_MODEL"],
    "question": "Research the topic, cite sources, and return a concise brief.",
    "stateful": True,
}

with requests.post(url, json=payload, headers=headers, stream=True, timeout=120) as response:
    response.raise_for_status()
    answer = []

    for raw_line in response.iter_lines():
        if not raw_line:
            continue

        event = json.loads(raw_line)
        event_type = event.get("type")

        if event_type == "text_delta":
            answer.append(event.get("content", ""))
        elif event_type == "tool_use":
            print("tool started:", event.get("tool_name"))
        elif event_type == "tool_result":
            print("tool finished; error =", event.get("is_error"))
        elif event_type == "citation":
            print("source:", event)
        elif event_type == "artifact":
            print("artifact:", event)
        elif event_type == "error":
            raise RuntimeError(event.get("message", "unknown agent error"))
        elif event_type == "done":
            print("usage:", event.get("usage"))
            print("terminal reason:", event.get("terminal_reason"))

print("".join(answer))

本番環境のインターフェースでは、各イベントファミリーに対してレンダラーまたはハンドラーを定義する必要があります。

  • text_delta は回答領域を更新します。
  • tool_use および tool_result は、アクティビティ状態と監査ビューを駆動します。
  • citation は関連する出力にソースを添付します。
  • card は構造化されたプレビューをレンダリングします。
  • artifact は個別に生成された成果物を公開します。
  • thinking は、選択したモデルがそれを公開する場合にのみ処理する必要があります。
  • error は現在のラウンドを終了または回復します。
  • done はストリームを閉じ、トークン使用量と終了理由を記録します。

インターフェースが最終回答のみを必要とする場合は、すべての text_delta から content を連結してください。これは JSON モードで返される answer と同等です。

エージェントにツールを使わせる—ただしアクティビティを可視化する

ツール呼び出しはデフォルトで有効です。AI Chat v2 は、ウェブ検索、ページ抽出、ファイル読み取りなどの組み込み機能を使用できます。また、Google Drive、Notion、Slack、GitHub など、ユーザー認可済みの MCP 接続をマウントすることもできます。

ストリームはその境界を明確に公開します。

{"type":"tool_use","tool_id":"toolu_01","tool_name":"web_search","input":{"query":"topic"}}
{"type":"tool_result","tool_id":"toolu_01","output":"...","is_error":false}

tool_id によって tool_use と tool_result を対応付けます。これにより、進行状況インジケーター、レイテンシ測定、エラー処理、およびオペレーターが読める監査証跡をサポートできます。

1 つのリクエストで発生できる自律的なツールラウンド数を制限するには、max_turns を使用します。許容範囲は 1~500 であり、ドキュメント化されたデフォルト値は 500 です。より低い値は、制限のない実行を減らします。max_turns: 1 を設定すると、単一のレスポンスが強制され、ツール呼び出しが防止されます。

実用的なロールアウトパターンは次のとおりです。

  1. プロダクト UI では、ツールなしの JSON モードから開始します。
  2. NDJSON または SSE を追加し、text_delta と done をレンダリングします。
  3. ツールアクティビティを折りたたまれたタイムラインとして表示します。
  4. 引用とアーティファクトのレンダリングを追加します。
  5. タスクの複雑さとコスト許容度に基づいて、意図的に max_turns を設定します。
  6. 書き込み可能な接続は、その確認モデルを確認した後にのみ有効にします。

質問を再開可能な状態機械として処理する

エージェントが明確化を必要とする場合があります。その場合、ストリームは ask_user_question を送出でき、会話は awaiting_user_input 状態に入ります。

クライアントは次のことを行う必要があります。

  1. 会話の id と tool_id を保存します。
  2. 質問とその選択肢をレンダリングします。
  3. ユーザーの回答を収集します。
  4. 同じ会話 id を使用して別のリクエストを送信します。
  5. 保留中のツール呼び出しのために、tool_results を通じて回答を返します。 これは、エージェントが不足している情報で完了できるふりをするよりも堅牢です。また、機密性の高いアクションに対する承認ゲートも可能にします。

対話型実行と無人実行を分離する

Webhook、CI/CD ジョブ、監視システムの場合、async: true は作業の継続中にタスク識別子を返します。結果は後で取得するか、HTTP(S) コールバック URL に配信できます。

無人の書き込みアクセスは明示的であるべきです。AI Chat v2 は allowed_skills、allowed_mcp_servers、または同等の unattended_policy オブジェクトをサポートしています。空のリストは、いかなる機能も許可しません。事前承認はコネクタ独自のセキュリティメカニズムをバイパスしません。無人確認をサポートしないスキルは、引き続きドライランするか、書き込みを拒否するべきです。

この区別は重要です: 接続の可用性は、人が不在の状態で行動する許可と同じではありません。

本番環境チェックリスト

エージェント型インターフェースを開始する前に、以下を確認してください:

  • API 認証情報はサーバー側に保存され、ブラウザーコードには決して保存されない。
  • モデル名はハードコードされた想定ではなく、現在サポートされているモデル一覧から取得される。
  • ストリームパーサーは、部分的なネットワークチャンクと未知のイベントタイプを許容する。
  • ツールイベントは tool_id によって対応付けられ、エラーが記録される。
  • max_turns は意図的に設定されている。
  • 引用およびアーティファクト URL は安全にレンダリングされる。
  • ask_user_question は後で再開するために十分な状態を永続化する。
  • 書き込み可能な接続は、確認または限定的な無人認可を保持する。
  • done.usage と terminal_reason はオブザーバビリティに反映される。
  • 会話の削除および保持ポリシーは、製品要件に一致している。

チャットボットからエージェントへの最短経路

AI Chat v2 は全面的な書き換えを強制しません。エンドポイントを変更し、現在のリクエストボディを維持することから始めてください。次に、マルチモーダルな message ブロックへ移行し、構造化ストリーミングを採用し、ツールの進行状況を公開し、一時停止と再開の処理を追加します。

その結果、ファイル、ツール、引用、アーティファクト、またはユーザーへの確認のために別個のプロトコルを考案することなく、単純な回答から監査可能なエージェントワークフローへと成長できるクライアントが得られます。

公式リソース