関数呼び出し
リクエストで関数を記述すると、モデルは実行してほしい呼び出しを返します。お使いのコードがそれを実行して結果を送り返します。API はツール呼び出しを返すだけで、ツール自体は実行しません。
POST https://api.shannon-ai.com/v1/chat/completions
このページのサンプルは /v1/chat/completions を使っています。同じループが /v1/responses と /v1/messages でも動作します。形式によって書き方が異なる箇所は、以下のセクションで三つすべてを示します。
import json
from openai import OpenAI
client = OpenAI(api_key="YOUR_API_KEY", base_url="https://api.shannon-ai.com/v1")
tools = [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the current weather for a city.",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "City name, for example Paris"},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
},
"required": ["city"],
},
},
}]
def get_weather(city, unit="celsius"):
# Your code: ask a weather service here.
return {"city": city, "temperature": 18, "unit": unit, "conditions": "cloudy"}
messages = [{"role": "user", "content": "What is the weather in Paris right now?"}]
answer = None
for _ in range(5): # the API sets no limit on rounds: set your own
response = client.chat.completions.create(
model="Kimi-K3-3BIT-REAP",
messages=messages,
tools=tools,
)
choice = response.choices[0]
if choice.finish_reason != "tool_calls":
answer = choice.message.content
break
messages.append(choice.message) # the assistant turn with its tool_calls
for call in choice.message.tool_calls:
args = json.loads(call.function.arguments) # arguments is a JSON string
result = get_weather(**args)
messages.append({
"role": "tool",
"tool_call_id": call.id,
"content": json.dumps(result),
})
print(answer) import OpenAI from "openai";
const client = new OpenAI({ apiKey: "YOUR_API_KEY", baseURL: "https://api.shannon-ai.com/v1" });
const tools = [{
type: "function",
function: {
name: "get_weather",
description: "Get the current weather for a city.",
parameters: {
type: "object",
properties: {
city: { type: "string", description: "City name, for example Paris" },
unit: { type: "string", enum: ["celsius", "fahrenheit"] },
},
required: ["city"],
},
},
}];
// Your code: ask a weather service here.
function getWeather({ city, unit = "celsius" }) {
return { city, temperature: 18, unit, conditions: "cloudy" };
}
const messages = [{ role: "user", content: "What is the weather in Paris right now?" }];
let answer = null;
// The API sets no limit on rounds: set your own.
for (let round = 0; round < 5; round++) {
const response = await client.chat.completions.create({
model: "Kimi-K3-3BIT-REAP",
messages,
tools,
});
const choice = response.choices[0];
if (choice.finish_reason !== "tool_calls") {
answer = choice.message.content;
break;
}
messages.push(choice.message); // the assistant turn with its tool_calls
for (const call of choice.message.tool_calls) {
const args = JSON.parse(call.function.arguments); // arguments is a JSON string
messages.push({
role: "tool",
tool_call_id: call.id,
content: JSON.stringify(getWeather(args)),
});
}
}
console.log(answer); # 1. Send the conversation with the tools.
curl https://api.shannon-ai.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "Kimi-K3-3BIT-REAP",
"messages": [
{"role": "user", "content": "What is the weather in Paris right now?"}
],
"tools": [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the current weather for a city.",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "City name, for example Paris"},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
},
"required": ["city"]
}
}
}]
}'
# 2. Run the function yourself, then send the assistant turn and the result.
# Use the id of the call you received.
curl https://api.shannon-ai.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "Kimi-K3-3BIT-REAP",
"messages": [
{"role": "user", "content": "What is the weather in Paris right now?"},
{"role": "assistant", "content": null, "tool_calls": [{
"id": "call_9f1c2ab34d5e4f60a7b8c9d0e1f2a3b4",
"type": "function",
"function": {"name": "get_weather", "arguments": "{\"city\":\"Paris\"}"}
}]},
{"role": "tool", "tool_call_id": "call_9f1c2ab34d5e4f60a7b8c9d0e1f2a3b4",
"content": "{\"city\":\"Paris\",\"temperature\":18,\"unit\":\"celsius\",\"conditions\":\"cloudy\"}"}
],
"tools": [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the current weather for a city.",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "City name, for example Paris"},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
},
"required": ["city"]
}
}
}]
}' 最初の応答は質問に答えません。呼び出しを求めます。
{
"id": "chatcmpl-5b0c1d8e7f6a4b3c9d2e1f0a8b7c6d5e",
"object": "chat.completion",
"created": 1791590400,
"model": "Kimi-K3-3BIT-REAP",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": null,
"reasoning_content": "The user asks for the current weather in Paris. I should call get_weather.",
"tool_calls": [
{
"id": "call_9f1c2ab34d5e4f60a7b8c9d0e1f2a3b4",
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"city\":\"Paris\"}"
}
}
]
},
"finish_reason": "tool_calls"
}
],
"usage": {
"prompt_tokens": 312,
"completion_tokens": 58,
"total_tokens": 370,
"prompt_tokens_details": {"cached_tokens": 0},
"completion_tokens_details": {"reasoning_tokens": 31}
}
} 結果を送信すると、次の応答は通常の回答になります。message.content にテキストが入り、finish_reason は stop です。
ループの手順
| ステップ | 担当 | 動作 |
|---|---|---|
| 1 | あなた | messages を、モデルが要求してよい関数の一覧である tools と一緒に送信します。 |
| 2 | モデル | 応答に tool_calls と finish_reason: "tool_calls" が含まれます。各呼び出しには、関数名と引数が示されます。 |
| 3 | あなた | 各呼び出しの arguments をパースし、関数を実行します。 |
| 4 | あなた | アシスタントのメッセージと、呼び出しごとにひとつの tool メッセージを messages に追加し、同じ tools でリクエストをもう一度送信します。 |
| 5 | モデル | モデルは finish_reason: "stop" のテキストで答えるか、さらに呼び出しを求めます。後者の場合は、ステップ 3 に戻ります。 |
ひとつのリクエストは、モデルの一ターンです。API はリクエスト間で会話を保持せず、ラウンド数も定めません。messages を保持し、いつ止めるかを決めるのはお使いのコードです。
ツールの定義
tools は、関数ごとにひとつのエントリを持つ配列です。カタログのすべてのモデルが受け付けます。GET /v1/models は、すべての ID について capabilities.tools: true を報告します。
| フィールド | 型 | 説明 |
|---|---|---|
type | string | 常に function。 |
function.name | string | モデルがこの関数を要求するときに使う名前。必須です。 |
function.description | string | 関数の内容を、わかりやすい言葉で記述します。 |
function.parameters | object | 引数を、最上位に type: "object" を持つ JSON Schema で記述します。下記の スキーマのキーワード を参照してください。 |
エンドポイントごとに、ツールの書き方が異なります。呼び出すエンドポイントに合ったものを送信してください。
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the current weather for a city.",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "City name, for example Paris"
},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
},
"required": ["city"]
}
}
} {
"type": "function",
"name": "get_weather",
"description": "Get the current weather for a city.",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "City name, for example Paris"
},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
},
"required": ["city"]
}
} {
"name": "get_weather",
"description": "Get the current weather for a city.",
"input_schema": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "City name, for example Paris"
},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
},
"required": ["city"]
}
} tool_choice
tool_choice は、モデルがツールを呼び出してもよいか、呼び出さなければならないかを指定します。tools と一緒にのみ読み取られます。
| 値 | 説明 | 適用モデル |
|---|---|---|
"auto" | テキストで答えるかツールを呼び出すかは、モデルが判断します。これがデフォルトです。 | すべてのモデル |
"required" | 応答は少なくともひとつのツールを呼び出します。 | ホスト型オープンウェイトモデル |
{"type": "function", "function": {"name": "get_weather"}} | 応答はこの関数を呼び出します。名前は tools にある関数のいずれかでなければなりません。他の関数への呼び出しは、応答から除かれます。 | ホスト型オープンウェイトモデル |
Shannon モデル(shannon-*)は、auto の場合と同様に、リクエストごとに判断します。
required や名前付き関数を指定した場合は、tool_calls を読む前に finish_reason を確認してください。モデルが呼び出しを生成しなかった場合、応答は finish_reason: "stop" のテキスト回答になります。
| 意味 | /v1/chat/completions | /v1/responses | /v1/messages |
|---|---|---|---|
| モデルが判断する | "auto" | "auto" | {"type": "auto"} |
| 少なくともひとつのツールを呼び出す | "required" | "required" | {"type": "any"} |
| 名前を指定した関数を呼び出す | {"type": "function", "function": {"name": "get_weather"}} | {"type": "function", "name": "get_weather"} | {"type": "tool", "name": "get_weather"} |
互換性のために受け付けられるもの:tool_choice: "none" と parallel_tool_calls。ツール呼び出しのないターンにするには、tools なしでリクエストを送信してください。
応答内のツール呼び出し
| フィールド | 型 | 説明 |
|---|---|---|
finish_reason | string | 応答に少なくともひとつの呼び出しが含まれる場合は tool_calls。 |
message.tool_calls | array | 呼び出しごとに一件のエントリ。このフィールドは、モデルが呼び出しを求めた場合にのみ含まれます。 |
tool_calls[].id | string | call_ の後ろに 32 桁の十六進数が続きます。結果とともに tool_call_id として送り返してください。 |
tool_calls[].type | string | 常に function。 |
tool_calls[].function.name | string | 実行する関数。 |
tool_calls[].function.arguments | string | 引数を JSON 文字列 で表したもの。引数がない場合は "{}" です。使用する前にパースしてください。 |
message.content | string | null | 応答に呼び出しだけが含まれる場合は null。ホスト型オープンウェイトモデルは呼び出しと並べてテキストを返すことがあります。Shannon モデルは null を返します。 |
各形式での同じ呼び出し。/v1/responses では output の function_call アイテムで、arguments は JSON 文字列です。/v1/messages では tool_use コンテンツブロックで、input は JSON オブジェクト、id は toolu_ で始まり、stop_reason は tool_use です。
{
"finish_reason": "tool_calls",
"message": {
"role": "assistant",
"content": null,
"tool_calls": [
{
"id": "call_9f1c2ab34d5e4f60a7b8c9d0e1f2a3b4",
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"city\":\"Paris\"}"
}
}
]
}
} {
"output": [
{
"id": "fc_3d2c1b0a9f8e4d7c6b5a4f3e2d1c0b9a",
"type": "function_call",
"call_id": "call_9f1c2ab34d5e4f60a7b8c9d0e1f2a3b4",
"name": "get_weather",
"arguments": "{\"city\":\"Paris\"}",
"status": "completed"
}
]
} {
"stop_reason": "tool_use",
"content": [
{
"type": "tool_use",
"id": "toolu_9f1c2ab34d5e4f60a7b8c9d0e1f2a3b4",
"name": "get_weather",
"input": {"city": "Paris"}
}
]
} ひとつのターンでの複数の呼び出し
ひとつの応答に複数の呼び出しが含まれることがあります。そのすべてを実行し、次のリクエストで、呼び出しごとに、それぞれの tool_call_id を付けて結果をひとつずつ送信してください。
ホスト型オープンウェイトモデルは、重複しない呼び出しをそれぞれ一度だけ返します。名前も引数も同じ二つの呼び出しは、ひとつにまとめて届きます。
ストリームされるツール呼び出し
stream: true の場合、呼び出しはひとまとまりで届きます。チャンクに完全な arguments 文字列が入っているため、つなぎ合わせる断片はありません。index は、そのターンの呼び出しを 0 から数えます。
{
"id": "chatcmpl-5b0c1d8e7f6a4b3c9d2e1f0a8b7c6d5e",
"object": "chat.completion.chunk",
"created": 1791590400,
"model": "Kimi-K3-3BIT-REAP",
"choices": [
{
"index": 0,
"delta": {
"tool_calls": [
{
"index": 0,
"id": "call_9f1c2ab34d5e4f60a7b8c9d0e1f2a3b4",
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"city\":\"Paris\"}"
}
}
]
},
"finish_reason": null
}
]
} | エンドポイント | 届くもの |
|---|---|
/v1/chat/completions | 呼び出しごとにひとつの chat.completion.chunk が届き、呼び出しは delta.tool_calls[0] に入ります。最後のチャンクには finish_reason: "tool_calls" と usage があります。 |
/v1/responses | 呼び出しごとに:response.output_item.added(空の arguments を持つ function_call アイテム)、response.function_call_arguments.delta(文字列全体)、response.function_call_arguments.done、response.output_item.done。 |
/v1/messages | 呼び出しごとに:content_block_start(空の input を持つ tool_use ブロック)、引数テキスト全体が input_json_delta.partial_json に入った content_block_delta がひとつ、content_block_stop。その後 message_delta に stop_reason: "tool_use" が含まれます。 |
shannon-1.6-lite、shannon-1.6-pro、shannon-2-lite、shannon-2-pro、shannon-coder-1 では、tools を含むストリームリクエストは、ターンの最後にひとつの content デルタで回答テキストを届けます。 ストリーミング
結果を送り返す
二回目のリクエストは会話を繰り返し、ふたつを追加します。呼び出しを求めたアシスタントのターンと、呼び出しごとの結果です。
{
"messages": [
{"role": "user", "content": "What is the weather in Paris right now?"},
{
"role": "assistant",
"content": null,
"tool_calls": [
{
"id": "call_9f1c2ab34d5e4f60a7b8c9d0e1f2a3b4",
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"city\":\"Paris\"}"
}
}
]
},
{
"role": "tool",
"tool_call_id": "call_9f1c2ab34d5e4f60a7b8c9d0e1f2a3b4",
"content": "{\"city\":\"Paris\",\"temperature\":18,\"unit\":\"celsius\",\"conditions\":\"cloudy\"}"
}
]
} {
"input": [
{"role": "user", "content": "What is the weather in Paris right now?"},
{
"type": "function_call",
"call_id": "call_9f1c2ab34d5e4f60a7b8c9d0e1f2a3b4",
"name": "get_weather",
"arguments": "{\"city\":\"Paris\"}"
},
{
"type": "function_call_output",
"call_id": "call_9f1c2ab34d5e4f60a7b8c9d0e1f2a3b4",
"output": "{\"city\":\"Paris\",\"temperature\":18,\"unit\":\"celsius\",\"conditions\":\"cloudy\"}"
}
]
} {
"messages": [
{"role": "user", "content": "What is the weather in Paris right now?"},
{
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_9f1c2ab34d5e4f60a7b8c9d0e1f2a3b4",
"name": "get_weather",
"input": {"city": "Paris"}
}
]
},
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_9f1c2ab34d5e4f60a7b8c9d0e1f2a3b4",
"content": "{\"city\":\"Paris\",\"temperature\":18,\"unit\":\"celsius\",\"conditions\":\"cloudy\"}"
}
]
}
]
} - アシスタントのターンは、受け取ったとおりに、結果の前に送り返してください。各結果は ID で呼び出しと対応付けられます:
/v1/chat/completionsではtool_call_id、/v1/responsesではcall_id、/v1/messagesではtool_use_idです。 - 結果はテキストです。オブジェクトは JSON 文字列にシリアライズして
content(/v1/responsesではoutput)に入れます。/v1/messagesでは、tool_resultブロックのcontentは文字列、またはテキストブロックのリストです。 - アシスタントのターンでは、
function.argumentsは届いたとおり、JSON 文字列のままにします。 - 会話はツールの結果で終わっていてもかまいません。新しいユーザーメッセージは不要です。モデルは結果から続けます。
- 関数が失敗した場合は、失敗の内容を結果のテキストとして送信してください。モデルはそれを報告するか、別の呼び出しを求めることができます。
スキーマのキーワード
parameters(/v1/messages では input_schema)は JSON Schema です。Shannon 3 ファミリー(shannon-3、shannon-3-pro、shannon-3.1、shannon-3.1-pro)とホスト型オープンウェイトモデルは、送信したとおりに受け取ります。
shannon-1.6-lite、shannon-1.6-pro、shannon-2-lite、shannon-2-pro、shannon-coder-1 は、三つのエンドポイントすべてで、次のサブセットを受け取ります。
| 扱い | キーワード |
|---|---|
| 送信したとおりに読み取られる | 以下の行で名前が挙がっていないすべてのキーワード(たとえば type、properties、required、items、enum、description、minimum、maximum、anyOf、allOf)が、スキーマのあらゆる階層で対象です。 |
format | 値 int32、int64、float、double、byte、date、date-time、enum が読み取られます。 |
oneOf | anyOf として読み取られます。 |
| これらのモデルが受け取るスキーマに含まれないもの | $schema, $id, $ref, $defs, $comment, definitions, additionalProperties, unevaluatedProperties, patternProperties, propertyNames, examples, default, title, const, not, if, then, else, contains, minContains, maxContains, dependentRequired, dependentSchemas, dependencies, readOnly, writeOnly, deprecated, contentEncoding, contentMediaType, contentSchema, multipleOf, uniqueItems。数値の場合の exclusiveMinimum と exclusiveMaximum。format のその他の値。 |
動作と上限
- API は、ツール数にも、ラウンド数にも上限を設けていません。
- リクエストボディは最大 32 MiB までで、結果を含む会話はモデルのコンテキストウィンドウに収まる必要があります。
- リクエストに
toolsが含まれる場合、shannon-1.6-lite、shannon-1.6-pro、shannon-2-lite、shannon-2-proはデフォルトのtemperatureとして 0.2 を使います。別の値にするにはtemperatureを送信してください。 - 各ラウンドは独立したリクエストです。他のリクエストと同様に、残高から消費され、フラッド保護の対象としてカウントされます。 上限と残高
エラー
ツール呼び出しはステータス 200 の通常の応答です。次のエラーは、リクエスト自体に関するものです。
| ステータス | タイプ | メッセージ | 発生条件 |
|---|---|---|---|
400 | invalid_request_error | unknown model: <id> | model が、公開されている一覧にある ID ではありません。 |
422 | invalid_request_error | Failed to deserialize the JSON body into the target type: … | tools が配列ではないか、他のフィールドの JSON 型が正しくありません。 |
413 | invalid_request_error | Failed to buffer the request body: … | リクエストボディが 32 MiB を超えています。エラーには code: "request_too_large" が含まれます。 |
引数を書くのはモデルです。外部からの入力と同じように、関数を実行する前にスキーマと照合して確認してください。
認証、残高、サーバーのエラーは、すべてのリクエストと同じです。 エラー処理