> ## Documentation Index
> Fetch the complete documentation index at: https://docs.arouter.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# 도구 호출

> AI가 함수를 호출하고 실제 세계에서 작업을 수행할 수 있게 합니다. 도구 호출을 통해 모델이 외부 API, 데이터베이스 및 서비스와 상호작용할 수 있습니다.

도구 호출（함수 호출이라고도 함）을 통해 모델은 사용자가 정의한 특정 함수의 실행을 요청할 수 있습니다. 모델은 언제, 어떤 인수로 도구를 호출할지 결정하고, 애플리케이션이 도구를 실행하고 결과를 반환합니다.

ARouter는 모든 주요 제공업체의 도구 호출을 지원합니다. 인터페이스는 OpenAI 도구 호출 표준을 따릅니다.

## 작동 방식

도구 호출은 3단계 사이클을 따릅니다:

1. **도구를 포함한 추론** — 도구 정의가 포함된 요청을 보냅니다. 모델은 도구 호출을 결정하고 `tool_calls` 응답을 반환합니다.
2. **도구 실행（클라이언트 측）** — 애플리케이션이 요청된 함수를 실행하고 결과를 수집합니다.
3. **도구 결과를 포함한 추론** — 도구 결과를 모델에 다시 보내면 모델이 최종 응답을 생성합니다.

### 1단계: 도구를 포함한 추론

```json theme={null}
{
  "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` 배열을 반환합니다:

```json theme={null}
{
  "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단계: 도구 실행（클라이언트 측）

애플리케이션이 모델의 인수로 함수를 실행합니다:

```python theme={null}
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` 역할 메시지로 다시 보냅니다:

```json theme={null}
{
  "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": [...]
}
```

## 전체 예제

<Tabs>
  <Tab title="Python (OpenAI)">
    ```python theme={null}
    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."
    ```
  </Tab>

  <Tab title="Node.js (OpenAI)">
    ```typescript theme={null}
    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);
    ```
  </Tab>

  <Tab title="Go">
    ```go theme={null}
    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)
    }
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={null}
    # 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\"}"
          }
        ]
      }'
    ```
  </Tab>
</Tabs>

## 스트리밍 도구 호출

스트리밍이 활성화되면 도구 호출 인수가 `delta.tool_calls`를 통해 점진적으로 전달됩니다:

```typescript theme={null}
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`가 있는 모델이 이 기능을 지원합니다.

```bash theme={null}
curl https://api.arouter.ai/v1/models \
  -H "Authorization: Bearer lr_live_xxxx"
```

도구 호출은 대부분의 최첨단 모델에서 지원됩니다:

* `openai/gpt-5.4`, `openai/gpt-5.4-pro`
* `anthropic/claude-sonnet-4.6`, `anthropic/claude-opus-4.5`
* `google/gemini-2.5-flash`, `google/gemini-2.5-pro`
* `deepseek/deepseek-v3.2`
