次の方法で共有


Microsoft Foundry エージェントで関数呼び出しを使用する

Microsoft Foundry エージェントでは関数呼び出しがサポートされています。これにより、カスタム機能を使用してエージェントを拡張できます。 名前、パラメーター、および説明を使用して関数を定義すると、エージェントはアプリに呼び出しを要求できます。 アプリによって関数が実行され、出力が返されます。 その後、エージェントは結果を使用して、システムからの正確なリアルタイム データを使用して会話を続行します。

Important

実行は、作成後 10 分後に期限切れになります。 有効期限が切れる前にツールの出力を送信します。

Microsoft Foundry ポータルで関数ツールを使用してエージェントを実行できます。 ただし、ポータルでは、エージェントでの関数定義の追加、削除、または更新はサポートされていません。 SDK または REST API を使用して関数ツールを構成します。

利用サポート

✔️ (GA) は一般提供を示し、✔️(プレビュー) はパブリック プレビューを示し、ダッシュ (-) は機能が使用できないことを示します。

Microsoft Foundry のサポート Python SDK C# SDK JavaScript SDK Java SDK REST API 基本エージェントのセットアップ 標準エージェントのセットアップ
✔️ ✔️ (プレビュー) ✔️ (プレビュー) ✔️ (プレビュー) - ✔️ (GA) ✔️ ✔️

現在、Java SDK では、新しいエージェント API (azure-ai-projects パッケージ) での関数呼び出しはサポートされていません。 Java のサポートは、クラシック エージェント API でのみ使用できます。 クラシック エージェントでの Java 関数呼び出しの例については、 クラシック エージェントのドキュメントを参照してください

[前提条件]

開始する前に、次の内容を確認してください。

  • 基本または標準のエージェント環境

  • Foundry プロジェクトとデプロイされたモデル。

  • 言語の最新のプレリリース SDK パッケージ:

    • パイソン: azure-ai-projects>=2.0.0b4
    • .NET: Azure.AI.Projects.OpenAI (プレリリース)
    • TypeScript: @azure/ai-projects (最新ベータ)

    インストールと認証の手順については、 クイック スタートを参照してください。

環境変数

言語ごとに異なる環境変数の名前が使用されます。 1 つのセットを一貫して使用します。

Language プロジェクト エンドポイント モデル展開名
Python FOUNDRY_PROJECT_ENDPOINT FOUNDRY_MODEL_DEPLOYMENT_NAME
C# FOUNDRY_PROJECT_ENDPOINT FOUNDRY_MODEL_DEPLOYMENT_NAME
TypeScript FOUNDRY_PROJECT_ENDPOINT FOUNDRY_MODEL_DEPLOYMENT_NAME
REST API FOUNDRY_PROJECT_ENDPOINT (要求本文フィールドを使用)

ヒント

DefaultAzureCredentialを使用する場合は、サンプルを実行する前にaz loginを使用してサインインします。

クイック検証

認証とエンドポイントが正しく設定されているかどうかがわからない場合は、最初に次のスニペットを実行します。

import os

from azure.ai.projects import AIProjectClient
from azure.identity import DefaultAzureCredential
from dotenv import load_dotenv

load_dotenv()

with (
    DefaultAzureCredential() as credential,
    AIProjectClient(endpoint=os.environ["FOUNDRY_PROJECT_ENDPOINT"], credential=credential) as project_client,
):
    print("Connected to project.")

関数ツールを使用してエージェントを作成する

関数呼び出しは、次のパターンに従います。

  1. 関数ツールの定義 - 各関数の名前、パラメーター、目的について説明します。
  2. エージェントを作成する - エージェントを関数定義に登録します。
  3. プロンプトを送信する — エージェントはプロンプトを分析し、必要に応じて関数呼び出しを要求します。
  4. 実行して返す — アプリが関数を実行し、出力をエージェントに送信します。
  5. 最後の応答を取得 する — エージェントは関数の出力を使用して応答を完了します。

最新のプレリリース パッケージが必要です。 詳細については、クイックスタートをご覧ください。

次のコード サンプルを使用して、エージェントを作成し、関数呼び出しを処理し、ツールの出力をエージェントに返します。

import os
import json
from dotenv import load_dotenv
from azure.ai.projects import AIProjectClient
from azure.ai.projects.models import PromptAgentDefinition, Tool, FunctionTool
from azure.identity import DefaultAzureCredential
from openai.types.responses.response_input_param import FunctionCallOutput, ResponseInputParam

load_dotenv()

def get_horoscope(sign: str) -> str:
    """Generate a horoscope for the given astrological sign."""
    return f"{sign}: Next Tuesday you will befriend a baby otter."

endpoint = os.environ["FOUNDRY_PROJECT_ENDPOINT"]

with (
    DefaultAzureCredential() as credential,
    AIProjectClient(endpoint=endpoint, credential=credential) as project_client,
    project_client.get_openai_client() as openai_client,
):

    # Define a function tool for the model to use
    func_tool = FunctionTool(
        name="get_horoscope",
        parameters={
            "type": "object",
            "properties": {
                "sign": {
                    "type": "string",
                    "description": "An astrological sign like Taurus or Aquarius",
                },
            },
            "required": ["sign"],
            "additionalProperties": False,
        },
        description="Get today's horoscope for an astrological sign.",
        strict=True,
    )

    tools: list[Tool] = [func_tool]

    agent = project_client.agents.create_version(
        agent_name="MyAgent",
        definition=PromptAgentDefinition(
            model=os.environ["FOUNDRY_MODEL_DEPLOYMENT_NAME"],
            instructions="You are a helpful assistant that can use function tools.",
            tools=tools,
        ),
    )

    # Prompt the model with tools defined
    response = openai_client.responses.create(
        input="What is my horoscope? I am an Aquarius.",
        extra_body={"agent_reference": {"name": agent.name, "type": "agent_reference"}},
    )
    print(f"Response output: {response.output_text}")

    input_list: ResponseInputParam = []
    # Process function calls
    for item in response.output:
        if item.type == "function_call":
            if item.name == "get_horoscope":
                # Execute the function logic for get_horoscope
                horoscope = get_horoscope(**json.loads(item.arguments))

                # Provide function call results to the model
                input_list.append(
                    FunctionCallOutput(
                        type="function_call_output",
                        call_id=item.call_id,
                        output=json.dumps({"horoscope": horoscope}),
                    )
                )

    print("Final input:")
    print(input_list)

    response = openai_client.responses.create(
        input=input_list,
        previous_response_id=response.id,
        extra_body={"agent_reference": {"name": agent.name, "type": "agent_reference"}},
    )

    print(f"Agent response: {response.output_text}")

    print("\nCleaning up...")
    project_client.agents.delete_version(agent_name=agent.name, agent_version=agent.version)
    print("Agent deleted")

想定される出力

次の例は、予想される出力を示しています:

Response output: 
Final input:
[FunctionCallOutput(type='function_call_output', call_id='call_abc123', output='{"horoscope": "Aquarius: Next Tuesday you will befriend a baby otter."}')]

関数でエージェントを使用する例

この例では、エージェントでローカル関数を使用します。 この関数を使用して、ユーザーの質問に応じてエージェント固有の情報を提供します。 この例のコードは同期です。 非同期の例については、GitHub の Azure SDK for .NET リポジトリの サンプル コード 例を参照してください。

class FunctionCallingDemo
{
    // Define three functions:
    //   1. GetUserFavoriteCity always returns "Seattle, WA".
    //   2. GetCityNickname handles only "Seattle, WA"
    //      and throws an exception for other city names.
    //   3. GetWeatherAtLocation returns the weather in Seattle, WA.

    /// Example of a function that defines no parameters but
    /// returns the user's favorite city.
    private static string GetUserFavoriteCity() => "Seattle, WA";

    /// <summary>
    /// Example of a function with a single required parameter
    /// </summary>
    /// <param name="location">The location to get nickname for.</param>
    /// <returns>The city nickname.</returns>
    /// <exception cref="NotImplementedException"></exception>
    private static string GetCityNickname(string location) => location switch
    {
        "Seattle, WA" => "The Emerald City",
        _ => throw new NotImplementedException(),
    };

    /// <summary>
    /// Example of a function with one required and one optional, enum parameter
    /// </summary>
    /// <param name="location">Get weather for location.</param>
    /// <param name="temperatureUnit">"c" or "f"</param>
    /// <returns>The weather in selected location.</returns>
    /// <exception cref="NotImplementedException"></exception>
    public static string GetWeatherAtLocation(string location, string temperatureUnit = "f") => location switch
    {
        "Seattle, WA" => temperatureUnit == "f" ? "70f" : "21c",
        _ => throw new NotImplementedException()
    };

    // For each function, create FunctionTool, which defines the function name, description, and parameters.
    public static readonly FunctionTool getUserFavoriteCityTool = ResponseTool.CreateFunctionTool(
        functionName: "getUserFavoriteCity",
        functionDescription: "Gets the user's favorite city.",
        functionParameters: BinaryData.FromString("{}"),
        strictModeEnabled: false
    );

    public static readonly FunctionTool getCityNicknameTool = ResponseTool.CreateFunctionTool(
        functionName: "getCityNickname",
        functionDescription: "Gets the nickname of a city, e.g. 'LA' for 'Los Angeles, CA'.",
        functionParameters: BinaryData.FromObjectAsJson(
            new
            {
                Type = "object",
                Properties = new
                {
                    Location = new
                    {
                        Type = "string",
                        Description = "The city and state, e.g. San Francisco, CA",
                    },
                },
                Required = new[] { "location" },
            },
            new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }
        ),
        strictModeEnabled: false
    );

    private static readonly FunctionTool getCurrentWeatherAtLocationTool = ResponseTool.CreateFunctionTool(
        functionName: "getCurrentWeatherAtLocation",
        functionDescription: "Gets the current weather at a provided location.",
        functionParameters: BinaryData.FromObjectAsJson(
             new
             {
                 Type = "object",
                 Properties = new
                 {
                     Location = new
                     {
                         Type = "string",
                         Description = "The city and state, e.g. San Francisco, CA",
                     },
                     Unit = new
                     {
                         Type = "string",
                         Enum = new[] { "c", "f" },
                     },
                 },
                 Required = new[] { "location" },
             },
            new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }
        ),
        strictModeEnabled: false
    );

    // Create the method GetResolvedToolOutput.
    // It runs the preceding functions and wraps the output in a ResponseItem object.
    private static FunctionCallOutputResponseItem GetResolvedToolOutput(FunctionCallResponseItem item)
    {
        if (item.FunctionName == getUserFavoriteCityTool.FunctionName)
        {
            return ResponseItem.CreateFunctionCallOutputItem(item.CallId, GetUserFavoriteCity());
        }
        using JsonDocument argumentsJson = JsonDocument.Parse(item.FunctionArguments);
        if (item.FunctionName == getCityNicknameTool.FunctionName)
        {
            string locationArgument = argumentsJson.RootElement.GetProperty("location").GetString();
            return ResponseItem.CreateFunctionCallOutputItem(item.CallId, GetCityNickname(locationArgument));
        }
        if (item.FunctionName == getCurrentWeatherAtLocationTool.FunctionName)
        {
            string locationArgument = argumentsJson.RootElement.GetProperty("location").GetString();
            if (argumentsJson.RootElement.TryGetProperty("unit", out JsonElement unitElement))
            {
                string unitArgument = unitElement.GetString();
                return ResponseItem.CreateFunctionCallOutputItem(item.CallId, GetWeatherAtLocation(locationArgument, unitArgument));
            }
            return ResponseItem.CreateFunctionCallOutputItem(item.CallId, GetWeatherAtLocation(locationArgument));
        }
        return null;
    }

    public static void Main() 
    {
        // Create project client and read the environment variables that will be used in the next steps.
        var projectEndpoint = System.Environment.GetEnvironmentVariable("FOUNDRY_PROJECT_ENDPOINT");
        var modelDeploymentName = System.Environment.GetEnvironmentVariable("FOUNDRY_MODEL_DEPLOYMENT_NAME");
        AIProjectClient projectClient = new(endpoint: new Uri(projectEndpoint), tokenProvider: new DefaultAzureCredential());
        // Create an agent version with the defined functions as tools.
        PromptAgentDefinition agentDefinition = new(model: modelDeploymentName)
        {
            Instructions = "You are a weather bot. Use the provided functions to help answer questions. "
                    + "Customize your responses to the user's preferences as much as possible and use friendly "
                    + "nicknames for cities whenever possible.",
            Tools = { getUserFavoriteCityTool, getCityNicknameTool, getCurrentWeatherAtLocationTool }
        };
        AgentVersion agentVersion = projectClient.Agents.CreateAgentVersion(
            agentName: "myAgent",
            options: new(agentDefinition));

        // If the local function call is required, the response item is of type FunctionCallResponseItem.
        // It contains the function name needed by the Agent. In this case, use the helper method
        // GetResolvedToolOutput to get the FunctionCallOutputResponseItem with the function call result.
        // To provide the right answer, supply all the response items to the CreateResponse call.
        // At the end, output the function's response.
        ResponsesClient responseClient = projectClient.OpenAI.GetProjectResponsesClientForAgent(agentVersion.Name);

        ResponseItem request = ResponseItem.CreateUserMessageItem("What's the weather like in my favorite city?");
        var inputItems = new List<ResponseItem> { request };
        string previousResponseId = null;
        bool functionCalled = false;
        ResponseResult response;
        do
        {
            response = responseClient.CreateResponse(
                previousResponseId: previousResponseId,
                inputItems: inputItems);
            previousResponseId = response.Id;
            inputItems.Clear();
            functionCalled = false;
            foreach (ResponseItem responseItem in response.OutputItems)
            {
                inputItems.Add(responseItem);
                if (responseItem is FunctionCallResponseItem functionToolCall)
                {
                    Console.WriteLine($"Calling {functionToolCall.FunctionName}...");
                    inputItems.Add(GetResolvedToolOutput(functionToolCall));
                    functionCalled = true;
                }
            }
        } while (functionCalled);
        Console.WriteLine(response.GetOutputText());

        // Remove all the resources created in this sample.
        projectClient.Agents.DeleteAgentVersion(agentName: agentVersion.Name, agentVersion: agentVersion.Version);
    }
}

想定される出力

次の例は、予想される出力を示しています:

Calling getUserFavoriteCity...
Calling getCityNickname...
Calling getCurrentWeatherAtLocation...
Your favorite city, Seattle, WA, is also known as The Emerald City. The current weather there is 70f.

Foundry Agent Service で関数呼び出しを使用するには、2 つの方法があります。

  1. responseを作成します。 エージェントが関数を再度呼び出す必要がある場合は、別の responseを作成します。
  2. conversationを作成し、複数の会話アイテムを作成します。 各会話項目は、1 つの responseに対応します。

例を実行する前に、次の環境変数を設定します。

export AGENT_TOKEN=$(az account get-access-token --scope "https://ai.azure.com/.default" --query accessToken -o tsv)

エージェントが呼び出す関数を定義する

まず、エージェントが呼び出す関数を定義します。 エージェントが呼び出す関数を作成するときは、その構造と必要なパラメーターを docstring に記述します。 関数の例については、他の SDK 言語を参照してください。

エージェントを作成する

curl -X POST "$FOUNDRY_PROJECT_ENDPOINT/agents?api-version=v1" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $AGENT_TOKEN" \
  -d '{
    "name": "<AGENT_NAME>-function-calling",
    "description": "Agent with function calling",
    "definition": {
      "kind": "prompt",
      "model": "<MODEL_DEPLOYMENT>",
      "instructions": "You are a helpful agent.",
      "tools": [
        {
          "type": "function",
          "name": "getCurrentWeather",
          "description": "Get the current weather in a location",
          "parameters": {
            "type": "object",
            "properties": {
              "location": {"type": "string", "description": "The city and state e.g. San Francisco, CA"},
              "unit": {"type": "string", "enum": ["c", "f"]}
            },
            "required": ["location"]
          }
        }
      ]
    }
  }'

会話を作成する

curl -X POST "$FOUNDRY_PROJECT_ENDPOINT/openai/v1/conversations" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $AGENT_TOKEN" \
  -d '{
    "items": [
      {
        "type": "message",
        "role": "user",
        "content": [
          {
            "type": "input_text",
            "text": "What'\''s the weather in Dar es Salaam, Tanzania?"
          }
        ]
      }
    ]
  }'

次の手順で返された会話 ID (conv_xyz...) を保存します。

応答を作成する

<CONVERSATION_ID>を前の手順の ID に置き換えます。

curl -X POST "$FOUNDRY_PROJECT_ENDPOINT/openai/v1/responses" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $AGENT_TOKEN" \
  -d '{
    "agent": {"type": "agent_reference", "name": "<AGENT_NAME>-function-calling"},
    "conversation": "<CONVERSATION_ID>",
    "input": []
  }'

想定される出力

応答には、処理する必要がある関数呼び出し項目が含まれています。

{
  "output": [
    {
      "type": "function_call",
      "call_id": "call_xyz789",
      "name": "getCurrentWeather",
      "arguments": "{\"location\": \"Dar es Salaam, Tanzania\", \"unit\": \"c\"}"
    }
  ]
}

関数呼び出しを処理し、エージェントに出力を返した後、最終的な応答には自然言語の気象情報が含まれます。

次のコード サンプルを使用して、関数ツールを使用してエージェントを作成し、モデルからの関数呼び出しを処理し、関数の結果を提供して最終的な応答を取得します。

import { DefaultAzureCredential } from "@azure/identity";
import { AIProjectClient } from "@azure/ai-projects";
import "dotenv/config";

const projectEndpoint = process.env["FOUNDRY_PROJECT_ENDPOINT"] || "<project endpoint>";
const deploymentName = process.env["FOUNDRY_MODEL_DEPLOYMENT_NAME"] || "<model deployment name>";

/**
 * Define a function tool for the model to use
 */
const funcTool = {
  type: "function" as const,
  name: "get_horoscope",
  description: "Get today's horoscope for an astrological sign.",
  strict: true,
  parameters: {
    type: "object",
    properties: {
      sign: {
        type: "string",
        description: "An astrological sign like Taurus or Aquarius",
      },
    },
    required: ["sign"],
    additionalProperties: false,
  },
};

/**
 * Generate a horoscope for the given astrological sign.
 */
function getHoroscope(sign: string): string {
  return `${sign}: Next Tuesday you will befriend a baby otter.`;
}

export async function main(): Promise<void> {
  // Create AI Project client
  const project = new AIProjectClient(projectEndpoint, new DefaultAzureCredential());
  const openAIClient = await project.getOpenAIClient();

  // Create agent with function tools
  console.log("Creating agent with function tools...");
  const agent = await project.agents.createVersion("function-tool-agent", {
    kind: "prompt",
    model: deploymentName,
    instructions: "You are a helpful assistant that can use function tools.",
    tools: [funcTool],
  });
  console.log(`Agent created (id: ${agent.id}, name: ${agent.name}, version: ${agent.version})`);

  // Prompt the model with tools defined
  console.log("\nGenerating initial response...");
  const response = await openAIClient.responses.create(
    {
      input: [
        {
          type: "message",
          role: "user",
          content: "What is my horoscope? I am an Aquarius.",
        },
      ],
    },
    {
      body: { agent: { name: agent.name, type: "agent_reference" } },
    },
  );
  console.log(`Response output: ${response.output_text}`);

  // Process function calls
  const inputList: Array<{
    type: "function_call_output";
    call_id: string;
    output: string;
  }> = [];

  for (const item of response.output) {
    if (item.type === "function_call") {
      if (item.name === "get_horoscope") {
        // Parse the function arguments
        const args = JSON.parse(item.arguments);

        // Execute the function logic for get_horoscope
        const horoscope = getHoroscope(args.sign);

        // Provide function call results to the model
        inputList.push({
          type: "function_call_output",
          call_id: item.call_id,
          output: JSON.stringify({ horoscope }),
        });
      }
    }
  }

  console.log("\nFinal input:");
  console.log(JSON.stringify(inputList, null, 2));

  // Submit function results to get final response
  const finalResponse = await openAIClient.responses.create(
    {
      input: inputList,
      previous_response_id: response.id,
    },
    {
      body: { agent: { name: agent.name, type: "agent_reference" } },
    },
  );

  // The model should be able to give a response!
  console.log("\nFinal output:");
  console.log(finalResponse.output_text);

  // Clean up
  console.log("\nCleaning up resources...");
  await project.agents.deleteVersion(agent.name, agent.version);
  console.log("Agent deleted");
}

main().catch((err) => {
  console.error("The sample encountered an error:", err);
});

想定される出力

次の例は、予想される出力を示しています:

Creating agent with function tools...
Agent created (id: <agent-id>, name: function-tool-agent, version: <version>)

Generating initial response...
Response output: 

Final input:
[
  {
    "type": "function_call_output",
    "call_id": "call_abc123",
    "output": "{\"horoscope\":\"Aquarius: Next Tuesday you will befriend a baby otter.\"}"
  }
]

Final output:
Your horoscope for Aquarius: Next Tuesday you will befriend a baby otter.

Cleaning up resources...
Agent deleted

関数呼び出しが機能することを確認する

関数呼び出しが機能していることを確認するには、次のチェックを使用します。

  1. 最初の応答には、 typefunction_call に設定された出力項目が含まれています。
  2. アプリは、返された引数を使用して、要求された関数を実行します。
  3. アプリは、 function_call_output 項目を含むフォローアップ応答を送信し、前の応答を参照し、エージェントは自然言語の回答を返します。

Microsoft Foundry でトレースを使用する場合は、ツールの呼び出しが発生したかどうかを確認します。 ツールの呼び出しの検証とツールの使用状況の制御に関するガイダンスについては、「 Microsoft Foundry Agent Service でツールを使用するためのベスト プラクティス」を参照してください。

セキュリティとデータに関する考慮事項

  • ツールの引数とツール出力を信頼できない入力として扱います。 値を使用する前に、値を検証してサニタイズします。
  • ツール出力でシークレット (API キー、トークン、接続文字列) を渡さないでください。 モデルに必要なデータのみを返します。
  • DefaultAzureCredentialによって使用される ID に最小限の特権を適用します。
  • 明示的に意図しない限り、副作用は避けてください。 たとえば、関数ツールを安全な操作に制限したり、データを変更するアクションに対して明示的なユーザー確認を要求したりします。
  • 実行時間の長い操作の場合は、すぐに状態を返し、ポーリングを実装します。 10 分間の実行の有効期限は、個々の関数の実行ではなく、合計経過時間に適用されます。

トラブルシューティング

問題点 想定される原因 解決策
エージェントは関数呼び出しを返しますが、最終的な回答は返しません。 ツールの出力がモデルに返されません。 関数を実行し、ツールの出力で responses.create を呼び出し、 previous_response_id して続行します。
関数呼び出しは行われません。 エージェント定義または不適切な名前付けに含まれていない関数。 関数ツールがエージェントに追加されていることを確認します。 わかりやすい名前とパラメーターの説明を使用します。
引数が有効な JSON ではありません。 スキーマの不一致またはモデルの幻覚。 JSON スキーマで正しい型と必要なプロパティが使用されていることを確認します。 アプリで解析エラーを適切に処理します。
必須フィールドがありません。 スキーマでは、必要なプロパティは適用されません。 パラメーター スキーマ "required": [...] 配列を追加します。 より厳密な検証のために strict: true を設定します。
有効期限が切れ、ツールの出力が失敗します。 実行の有効期限が切れています (10 分の制限)。 ツールの出力をすぐに返します。 操作が遅い場合は、状態を返し、個別にポーリングします。
間違ったパラメーターで呼び出された関数。 あいまいな関数の説明。 関数の description フィールドを改善します。 例を使用して、パラメーターの詳細な説明を追加します。
1 つの応答で複数の関数呼び出し。 モデルは、必要な複数の関数を決定しました。 出力配列内の各関数呼び出しを処理します。 1 回の responses.create 呼び出しですべての結果を返します。
Foundry ポータルに関数が表示されません。 ポータルでは関数呼び出しは実行されません。 SDK または REST API を使用して関数呼び出しをテストします。 ポータルにはエージェントが表示されますが、関数は呼び出されません。

リソースをクリーンアップする

テストが完了したら、作成したリソースを削除して、継続的なコストを回避します。

エージェントを削除します。

curl -X DELETE "$FOUNDRY_PROJECT_ENDPOINT/agents/<AGENT_NAME>-function-calling?api-version=v1" \
  -H "Authorization: Bearer $AGENT_TOKEN"

会話を削除します。

curl -X DELETE "$FOUNDRY_PROJECT_ENDPOINT/openai/v1/conversations/<CONVERSATION_ID>" \
  -H "Authorization: Bearer $AGENT_TOKEN"