작동 방식
도구 호출은 3단계 사이클을 따릅니다:- 도구를 포함한 추론 — 도구 정의가 포함된 요청을 보냅니다. 모델은 도구 호출을 결정하고
tool_calls응답을 반환합니다. - 도구 실행(클라이언트 측) — 애플리케이션이 요청된 함수를 실행하고 결과를 수집합니다.
- 도구 결과를 포함한 추론 — 도구 결과를 모델에 다시 보내면 모델이 최종 응답을 생성합니다.
1단계: 도구를 포함한 추론
{
"model": "openai/gpt-5.4",
"messages": [
{ "role": "user", "content": "What is the weather in San Francisco?" }
],
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the current weather for a location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City name, e.g. 'San Francisco'"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"]
}
},
"required": ["location"]
}
}
}
],
"tool_choice": "auto"
}
tool_calls 배열을 반환합니다:
{
"id": "chatcmpl-xxx",
"choices": [
{
"message": {
"role": "assistant",
"content": null,
"tool_calls": [
{
"id": "call_abc123",
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"location\": \"San Francisco\", \"unit\": \"fahrenheit\"}"
}
}
]
},
"finish_reason": "tool_calls"
}
]
}
2단계: 도구 실행(클라이언트 측)
애플리케이션이 모델의 인수로 함수를 실행합니다:import json
tool_call = response.choices[0].message.tool_calls[0]
args = json.loads(tool_call.function.arguments)
# 함수 실행
result = get_weather(
location=args["location"],
unit=args.get("unit", "fahrenheit")
)
# result = {"temperature": 72, "condition": "sunny", "unit": "fahrenheit"}
3단계: 도구 결과를 포함한 추론
도구 결과를tool 역할 메시지로 다시 보냅니다:
{
"model": "openai/gpt-5.4",
"messages": [
{ "role": "user", "content": "What is the weather in San Francisco?" },
{
"role": "assistant",
"content": null,
"tool_calls": [
{
"id": "call_abc123",
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"location\": \"San Francisco\", \"unit\": \"fahrenheit\"}"
}
}
]
},
{
"role": "tool",
"tool_call_id": "call_abc123",
"content": "{\"temperature\": 72, \"condition\": \"sunny\", \"unit\": \"fahrenheit\"}"
}
],
"tools": [...]
}
전체 예제
- Python (OpenAI)
- Node.js (OpenAI)
- Go
- cURL
import json
from openai import OpenAI
client = OpenAI(
base_url="https://api.arouter.ai/v1",
api_key="lr_live_xxxx",
)
# 도구 정의
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the current weather for a location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City name, e.g. 'San Francisco'",
},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
},
"required": ["location"],
},
},
}
]
messages = [{"role": "user", "content": "What is the weather in San Francisco?"}]
# 1단계: 첫 번째 추론
response = client.chat.completions.create(
model="openai/gpt-5.4",
messages=messages,
tools=tools,
tool_choice="auto",
)
assistant_message = response.choices[0].message
messages.append(assistant_message)
# 2단계: 도구 실행
if assistant_message.tool_calls:
for tool_call in assistant_message.tool_calls:
if tool_call.function.name == "get_weather":
args = json.loads(tool_call.function.arguments)
# 날씨 API 시뮬레이션
result = {"temperature": 72, "condition": "sunny", "unit": args.get("unit", "fahrenheit")}
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": json.dumps(result),
})
# 3단계: 최종 추론
final_response = client.chat.completions.create(
model="openai/gpt-5.4",
messages=messages,
tools=tools,
)
print(final_response.choices[0].message.content)
# "The current weather in San Francisco is 72°F and sunny."
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.arouter.ai/v1",
apiKey: "lr_live_xxxx",
});
// 도구 정의
const tools: OpenAI.Chat.ChatCompletionTool[] = [
{
type: "function",
function: {
name: "get_weather",
description: "Get the current weather for a location",
parameters: {
type: "object",
properties: {
location: {
type: "string",
description: "City name, e.g. 'San Francisco'",
},
unit: { type: "string", enum: ["celsius", "fahrenheit"] },
},
required: ["location"],
},
},
},
];
const messages: OpenAI.Chat.ChatCompletionMessageParam[] = [
{ role: "user", content: "What is the weather in San Francisco?" },
];
// 1단계: 첫 번째 추론
const response = await client.chat.completions.create({
model: "openai/gpt-5.4",
messages,
tools,
tool_choice: "auto",
});
const assistantMessage = response.choices[0].message;
messages.push(assistantMessage);
// 2단계: 도구 실행
if (assistantMessage.tool_calls) {
for (const toolCall of assistantMessage.tool_calls) {
if (toolCall.function.name === "get_weather") {
const args = JSON.parse(toolCall.function.arguments);
const result = {
temperature: 72,
condition: "sunny",
unit: args.unit ?? "fahrenheit",
};
messages.push({
role: "tool",
tool_call_id: toolCall.id,
content: JSON.stringify(result),
});
}
}
}
// 3단계: 최종 추론
const finalResponse = await client.chat.completions.create({
model: "openai/gpt-5.4",
messages,
tools,
});
console.log(finalResponse.choices[0].message.content);
package main
import (
"context"
"encoding/json"
"fmt"
"log"
"github.com/arouter-ai/arouter-go"
)
func main() {
client := arouter.NewClient("lr_live_xxxx",
arouter.WithBaseURL("https://api.arouter.ai/v1"),
)
tools := []arouter.Tool{
{
Type: "function",
Function: &arouter.FunctionDefinition{
Name: "get_weather",
Description: "Get the current weather for a location",
Parameters: map[string]any{
"type": "object",
"properties": map[string]any{
"location": map[string]any{
"type": "string",
"description": "City name",
},
"unit": map[string]any{
"type": "string",
"enum": []string{"celsius", "fahrenheit"},
},
},
"required": []string{"location"},
},
},
},
}
messages := []arouter.Message{
{Role: "user", Content: "What is the weather in San Francisco?"},
}
// 1단계
resp, err := client.CreateChatCompletion(context.Background(), arouter.ChatCompletionRequest{
Model: "openai/gpt-5.4",
Messages: messages,
Tools: tools,
})
if err != nil {
log.Fatal(err)
}
assistantMsg := resp.Choices[0].Message
messages = append(messages, assistantMsg)
// 2단계 & 3단계
for _, tc := range assistantMsg.ToolCalls {
var args map[string]string
json.Unmarshal([]byte(tc.Function.Arguments), &args)
result := fmt.Sprintf(`{"temperature":72,"condition":"sunny","unit":"%s"}`, args["unit"])
messages = append(messages, arouter.Message{
Role: "tool",
ToolCallID: tc.ID,
Content: result,
})
}
finalResp, err := client.CreateChatCompletion(context.Background(), arouter.ChatCompletionRequest{
Model: "openai/gpt-5.4",
Messages: messages,
Tools: tools,
})
if err != nil {
log.Fatal(err)
}
fmt.Println(finalResp.Choices[0].Message.Content)
}
# 1단계: 도구를 포함한 추론
curl https://api.arouter.ai/v1/chat/completions \
-H "Authorization: Bearer lr_live_xxxx" \
-H "Content-Type: application/json" \
-d '{
"model": "openai/gpt-5.4",
"messages": [
{"role": "user", "content": "What is the weather in San Francisco?"}
],
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the current weather for a location",
"parameters": {
"type": "object",
"properties": {
"location": {"type": "string"},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
},
"required": ["location"]
}
}
}
],
"tool_choice": "auto"
}'
# 3단계: 도구 결과 전송
curl https://api.arouter.ai/v1/chat/completions \
-H "Authorization: Bearer lr_live_xxxx" \
-H "Content-Type: application/json" \
-d '{
"model": "openai/gpt-5.4",
"messages": [
{"role": "user", "content": "What is the weather in San Francisco?"},
{
"role": "assistant",
"content": null,
"tool_calls": [{"id": "call_abc123", "type": "function", "function": {"name": "get_weather", "arguments": "{\"location\": \"San Francisco\"}"}}]
},
{
"role": "tool",
"tool_call_id": "call_abc123",
"content": "{\"temperature\": 72, \"condition\": \"sunny\"}"
}
]
}'
스트리밍 도구 호출
스트리밍이 활성화되면 도구 호출 인수가delta.tool_calls를 통해 점진적으로 전달됩니다:
const stream = await client.chat.completions.create({
model: "openai/gpt-5.4",
messages: [{ role: "user", content: "What's the weather in NYC?" }],
tools,
stream: true,
});
let toolCallArgs = "";
let toolCallId = "";
let toolCallName = "";
for await (const chunk of stream) {
const delta = chunk.choices[0]?.delta;
if (delta?.tool_calls) {
const tc = delta.tool_calls[0];
if (tc.id) toolCallId = tc.id;
if (tc.function?.name) toolCallName = tc.function.name;
if (tc.function?.arguments) toolCallArgs += tc.function.arguments;
}
if (chunk.choices[0]?.finish_reason === "tool_calls") {
// 모든 인수 수신 완료
const args = JSON.parse(toolCallArgs);
console.log(`Calling ${toolCallName} with:`, args);
}
}
지원되는 모델
GET /v1/models를 사용하여 도구 호출을 지원하는 모델을 찾으세요. 기능 목록에 tools가 있는 모델이 이 기능을 지원합니다.
curl https://api.arouter.ai/v1/models \
-H "Authorization: Bearer lr_live_xxxx"
openai/gpt-5.4,openai/gpt-5.4-proanthropic/claude-sonnet-4.6,anthropic/claude-opus-4.5google/gemini-2.5-flash,google/gemini-2.5-prodeepseek/deepseek-v3.2