> ## Documentation Index
> Fetch the complete documentation index at: https://nusaai-edit.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Overview

> > Extend Neosantara capabilities by enabling it to interact with external tools and functions.

NeosantaraAI models are capable of interacting with tools (also known as functions), allowing you to extend the AI's capabilities to perform a wider variety of tasks, such as fetching real-time data, performing calculations, or interacting with external systems.

Here's an example of how to provide tools to NeosantaraAI using the chat completions API:

<CodeGroup>
  ```bash Shell theme={null}
  curl https://api.neosantara.xyz/v1/chat/completions \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $NEOSANTARA_API_KEY" \
    -d '{
      "model": "nusantara-base",
      "max_tokens": 1024,
      "tools": [
        {
          "type": "function",
          "function": {
            "name": "get_weather",
            "description": "Get the current weather in a given location",
            "parameters": {
              "type": "object",
              "properties": {
                "location": {
                  "type": "string",
                  "description": "The city and state, e.g. Jakarta, ID"
                }
              },
              "required": ["location"]
            }
          }
        }
      ],
      "messages": [
        {
          "role": "user",
          "content": "What is the weather like in Jakarta?"
        }
      ]
    }'
  ```

  ```python Python theme={null}
  from openai import OpenAI

  client = OpenAI(
      api_key="YOUR_NEOSANTARA_API_KEY",
      base_url="https://api.neosantara.xyz/v1"
  )

  response = client.chat.completions.create(
      model="nusantara-base",
      max_tokens=1024,
      tools=[
          {
              "type": "function",
              "function": {
                  "name": "get_weather",
                  "description": "Get the current weather in a given location",
                  "parameters": {
                      "type": "object",
                      "properties": {
                          "location": {
                              "type": "string",
                              "description": "The city and state, e.g. Jakarta, ID",
                          }
                      },
                      "required": ["location"],
                  },
              }
          }
      ],
      messages=[{"role": "user", "content": "What's the weather like in Jakarta?"}],
  )
  print(response)
  ```
</CodeGroup>

## How Tool Use Works

NeosantaraAI's tool use functionality follows a common pattern, similar to OpenAI's function calling, where you provide the model with descriptions of available tools, and the model decides if and how to use them.

Integrate client-side tools with NeosantaraAI in these steps:

<Steps>
  <Step title="Provide NeosantaraAI with tools and a user prompt">
    * Define tools with names, descriptions, and input schemas (parameters) in your API request within the `tools` parameter.
    * Include a user prompt that might require these tools, e.g., "What's the weather in Jakarta?"
  </Step>

  <Step title="NeosantaraAI decides to use a tool">
    * The model assesses if any tools can help with the user's query.
    * If yes, the model constructs a `tool_calls` object within its response, containing the name of the tool to be called and the arguments (input) for that tool.
    * The API response will have a `finish_reason` of `tool_calls`.
  </Step>

  <Step title="Execute the tool and return results">
    * Your application extracts the tool name and input from NeosantaraAI's `tool_calls` response.
    * Your application then executes the actual tool code on your system.
    * Return the results to the model in a new `user` message with a `tool` role, containing the `tool_call_id` and the `content` of the tool's output.
  </Step>

  <Step title="NeosantaraAI uses tool result to formulate a response">
    * NeosantaraAI analyzes the tool results you provide to craft its final, natural language response to the original user prompt.
  </Step>
</Steps>

Note: Steps 3 and 4 are optional. For some workflows, NeosantaraAI's tool use request (step 2) might be all you need, without sending results back to the model.

***

## Tool Use Examples

Here are a few code examples demonstrating various tool use patterns and techniques. The examples use simple tools for clarity.

<AccordionGroup>
  <Accordion title="Single Tool Example">
    <CodeGroup>
      ```bash Shell theme={null}
      curl https://api.neosantara.xyz/v1/chat/completions \
        --header "Content-Type: application/json" \
        --header "Authorization: Bearer $NEOSANTARA_API_KEY" \
        --data '{
          "model": "nusantara-base",
          "max_tokens": 1024,
          "tools": [{
            "type": "function",
            "function": {
              "name": "get_weather",
              "description": "Get the current weather in a given location",
              "parameters": {
                "type": "object",
                "properties": {
                  "location": {
                    "type": "string",
                    "description": "The city and state, e.g. Jakarta, ID"
                  },
                  "unit": {
                    "type": "string",
                    "enum": ["celsius", "fahrenheit"],
                    "description": "The unit of temperature, either \"celsius\" or \"fahrenheit\""
                  }
                },
                "required": ["location"]
              }
            }
          }],
          "messages": [{"role": "user", "content": "What is the weather like in Jakarta?"}]
        }'
      ```

      ```python Python theme={null}
      from openai import OpenAI

      client = OpenAI(api_key="YOUR_NEOSANTARA_API_KEY", base_url="https://api.neosantara.xyz/v1")

      response = client.chat.completions.create(
          model="nusantara-base",
          max_tokens=1024,
          tools=[
              {
                  "type": "function",
                  "function": {
                      "name": "get_weather",
                      "description": "Get the current weather in a given location",
                      "parameters": {
                          "type": "object",
                          "properties": {
                              "location": {
                                  "type": "string",
                                  "description": "The city and state, e.g. Jakarta, ID"
                              },
                              "unit": {
                                  "type": "string",
                                  "enum": ["celsius", "fahrenheit"],
                                  "description": "The unit of temperature, either 'celsius' or 'fahrenheit'"
                              }
                          },
                          "required": ["location"]
                      }
                  }
              }
          ],
          messages=[{"role": "user", "content": "What is the weather like in Jakarta?"}]
      )

      print(response)
      ```
    </CodeGroup>

    NeosantaraAI will return a response similar to:

    ```json theme={null}
    {
      "id": "chatcmpl-...",
      "object": "chat.completion",
      "created": 1701234567,
      "model": "nusantara-base",
      "choices": [
        {
          "index": 0,
          "message": {
            "role": "assistant",
            "content": null,
            "tool_calls": [
              {
                "id": "call_...",
                "type": "function",
                "function": {
                  "name": "get_weather",
                  "arguments": "{\"location\": \"Jakarta, ID\", \"unit\": \"celsius\"}"
                }
              }
            ]
          },
          "finish_reason": "tool_calls"
        }
      ],
      "usage": {
        "prompt_tokens": 50,
        "completion_tokens": 10,
        "total_tokens": 60
      },
      "_metadata": {
        "creator": "neosantara.xyz",
        "status": true,
        "tier": "Free"
        // ...
      }
    }
    ```

    You would then need to execute the `get_weather` function with the provided input, and return the result in a new `user` message:

    <CodeGroup>
      ```bash Shell theme={null}
      curl https://api.neosantara.xyz/v1/chat/completions \
        --header "Content-Type: application/json" \
        --header "Authorization: Bearer $NEOSANTARA_API_KEY" \
        --data '{
          "model": "nusantara-base",
          "max_tokens": 1024,
          "tools": [
              {
                "type": "function",
                "function": {
                  "name": "get_weather",
                  "description": "Get the current weather in a given location",
                  "parameters": {
                    "type": "object",
                    "properties": {
                      "location": {
                        "type": "string",
                        "description": "The city and state, e.g. Jakarta, ID"
                      },
                      "unit": {
                        "type": "string",
                        "enum": ["celsius", "fahrenheit"],
                        "description": "The unit of temperature, either \"celsius\" or \"fahrenheit\""
                      }
                    },
                    "required": ["location"]
                  }
                }
              }
          ],
          "messages": [
              {
                  "role": "user",
                  "content": "What is the weather like in Jakarta?"
              },
              {
                  "role": "assistant",
                  "content": null,
                  "tool_calls": [
                      {
                          "id": "call_toolu_01A09q90qw90lq917835lq9",
                          "type": "function",
                          "function": {
                              "name": "get_weather",
                              "arguments": "{\"location\": \"Jakarta, ID\", \"unit\": \"celsius\"}"
                          }
                      }
                  ]
              },
              {
                  "role": "tool",
                  "tool_call_id": "call_toolu_01A09q90qw90lq917835lq9",
                  "content": "{\"temperature\": 28, \"unit\": \"celsius\", \"description\": \"Partly cloudy\"}"
              }
          ]
        }'
      ```

      ```python Python theme={null}
      from openai import OpenAI
      import json

      client = OpenAI(api_key="YOUR_NEOSANTARA_API_KEY", base_url="https://api.neosantara.xyz/v1")

      # First call to get tool_calls
      response1 = client.chat.completions.create(
          model="nusantara-base",
          max_tokens=1024,
          tools=[
              {
                  "type": "function",
                  "function": {
                      "name": "get_weather",
                      "description": "Get the current weather in a given location",
                      "parameters": {
                          "type": "object",
                          "properties": {
                              "location": {
                                  "type": "string",
                                  "description": "The city and state, e.g. Jakarta, ID"
                              },
                              "unit": {
                                  "type": "string",
                                  "enum": ["celsius", "fahrenheit"],
                                  "description": "The unit of temperature, either 'celsius' or 'fahrenheit'"
                              }
                          },
                          "required": ["location"]
                      }
                  }
              }
          ],
          messages=[{"role": "user", "content": "What is the weather like in Jakarta?"}]
      )

      # Assuming response1 contains a tool_call
      if response1.choices[0].message.tool_calls:
          tool_call = response1.choices[0].message.tool_calls[0]
          tool_name = tool_call.function.name
          tool_args = json.loads(tool_call.function.arguments)
          tool_call_id = tool_call.id

          # --- Execute your tool here ---
          # For demonstration, a mock weather result
          if tool_name == "get_weather":
              mock_weather_result = {"temperature": 28, "unit": "celsius", "description": "Partly cloudy"}
          else:
              mock_weather_result = {"error": "Tool not found"}
          # --- End tool execution ---

          # Second call to provide tool results back to the model
          response2 = client.chat.completions.create(
              model="nusantara-base",
              max_tokens=1024,
              tools=[
                  {
                      "type": "function",
                      "function": {
                          "name": "get_weather",
                          "description": "Get the current weather in a given location",
                          "parameters": {
                              "type": "object",
                              "properties": {
                                  "location": { "type": "string" },
                                  "unit": { "type": "string", "enum": ["celsius", "fahrenheit"] }
                              },
                              "required": ["location"]
                          }
                      }
                  }
              ],
              messages=[
                  {"role": "user", "content": "What is the weather like in Jakarta?"},
                  {"role": "assistant", "content": None, "tool_calls": [tool_call]}, # Pass the original tool_call back
                  {"role": "tool", "tool_call_id": tool_call_id, "content": json.dumps(mock_weather_result)} # Provide tool result
              ]
          )
          print(response2)
      ```
    </CodeGroup>

    This will print NeosantaraAI's final response, incorporating the weather data:

    ```json theme={null}
    {
      "id": "chatcmpl-...",
      "object": "chat.completion",
      "created": 1701234567,
      "model": "nusantara-base",
      "choices": [
        {
          "index": 0,
          "message": {
            "role": "assistant",
            "content": "The weather in Jakarta is currently 28 degrees Celsius, partly cloudy."
          },
          "finish_reason": "stop"
        }
      ],
      "usage": {
        "prompt_tokens": 70,
        "completion_tokens": 20,
        "total_tokens": 90
      },
      "_metadata": {
        "creator": "neosantara.xyz",
        "status": true,
        "tier": "Free"
        // ...
      }
    }
    ```
  </Accordion>

  <Accordion title="Parallel Tool Use">
    NeosantaraAI can call multiple tools in parallel within a single response, which is useful for tasks that require multiple independent operations. When using parallel tools, all `tool_calls` blocks are included in a single assistant message, and all corresponding `tool` results must be provided in the subsequent user message, each with its `tool_call_id`.

    <CodeGroup>
      ```bash Shell theme={null}
      curl https://api.neosantara.xyz/v1/chat/completions \
        --header "Content-Type: application/json" \
        --header "Authorization: Bearer $NEOSANTARA_API_KEY" \
        --data '{
          "model": "nusantara-base",
          "max_tokens": 1024,
          "tools": [{
              "type": "function",
              "function": {
                "name": "get_weather",
                "description": "Get the current weather in a given location",
                "parameters": {
                  "type": "object",
                  "properties": {
                    "location": { "type": "string", "description": "The city and state, e.g. Jakarta, ID" }
                  },
                  "required": ["location"]
                }
              }
            },
            {
              "type": "function",
              "function": {
                "name": "get_time",
                "description": "Get the current time in a given time zone",
                "parameters": {
                  "type": "object",
                  "properties": {
                    "timezone": { "type": "string", "description": "The IANA time zone name, e.g. Asia/Jakarta" }
                  },
                  "required": ["timezone"]
                }
              }
            }
          ],
          "messages": [{"role": "user", "content": "What is the weather like right now in Jakarta? Also what time is it there?"}]
        }'
      ```

      ```python Python theme={null}
      from openai import OpenAI
      import json

      client = OpenAI(api_key="YOUR_NEOSANTARA_API_KEY", base_url="https://api.neosantara.xyz/v1")

      # First call to get parallel tool_calls
      response1 = client.chat.completions.create(
          model="nusantara-base",
          max_tokens=1024,
          tools=[
              {
                  "type": "function",
                  "function": {
                      "name": "get_weather",
                      "description": "Get the current weather in a given location",
                      "parameters": {
                          "type": "object",
                          "properties": {
                              "location": { "type": "string" }
                          },
                          "required": ["location"]
                      }
                  }
              },
              {
                  "type": "function",
                  "function": {
                      "name": "get_time",
                      "description": "Get the current time in a given time zone",
                      "parameters": {
                          "type": "object",
                          "properties": {
                              "timezone": { "type": "string" }
                          },
                          "required": ["timezone"]
                      }
                  }
              }
          ],
          messages=[{"role": "user", "content": "What is the weather like right now in Jakarta? Also what time is it there?"}]
      )

      # Process parallel tool calls
      if response1.choices[0].message.tool_calls:
          tool_calls = response1.choices[0].message.tool_calls
          tool_outputs = []

          for tool_call in tool_calls:
              tool_name = tool_call.function.name
              tool_args = json.loads(tool_call.function.arguments)
              tool_call_id = tool_call.id

              # --- Execute your tools here in parallel ---
              if tool_name == "get_weather":
                  mock_result = {"temperature": 28, "unit": "celsius", "description": "Partly cloudy"}
              elif tool_name == "get_time":
                  mock_result = {"time": "04:30 AM", "timezone": "Asia/Jakarta"}
              else:
                  mock_result = {"error": "Tool not found"}
              # --- End tool execution ---
              
              tool_outputs.append({
                  "tool_call_id": tool_call_id,
                  "output": json.dumps(mock_result) # Output must be a string
              })

          # Construct the messages list for the second API call
          messages_for_second_call = [
              {"role": "user", "content": "What is the weather like right now in Jakarta? Also what time is it there?"},
              {"role": "assistant", "content": None, "tool_calls": tool_calls} # Pass the original tool_calls back
          ]
          for output in tool_outputs:
              messages_for_second_call.append({
                  "role": "tool",
                  "tool_call_id": output["tool_call_id"],
                  "content": output["output"] # content must be a string
              })

          # Second call to get the final response
          response2 = client.chat.completions.create(
              model="nusantara-base",
              max_tokens=1024,
              tools=[
                  # Redefine tools for the second call
                  { "type": "function", "function": { "name": "get_weather", "description": "...", "parameters": { "type": "object", "properties": { "location": { "type": "string" } }, "required": ["location"] } } },
                  { "type": "function", "function": { "name": "get_time", "description": "...", "parameters": { "type": "object", "properties": { "timezone": { "type": "string" } }, "required": ["timezone"] } } }
              ],
              messages=messages_for_second_call
          )
          print(response2)
      ```
    </CodeGroup>
  </Accordion>

  <Accordion title="Missing Information">
    If the user's prompt doesn't include enough information to fill all the required parameters for a tool, NeosantaraAI is designed to recognize that a parameter is missing and ask for it.

    For example, using the `get_weather` tool, if you ask "What's the weather?" without specifying a location, the model is likely to respond with a clarifying question instead of making a tool call.

    ```json theme={null}
    {
      "id": "chatcmpl-...",
      "object": "chat.completion",
      "created": 1701234567,
      "model": "nusantara-base",
      "choices": [
        {
          "index": 0,
          "message": {
            "role": "assistant",
            "content": "Sure, I can tell you the weather. What city and state (or country) are you interested in?"
          },
          "finish_reason": "stop"
        }
      ],
      "usage": {
        "prompt_tokens": 40,
        "completion_tokens": 20,
        "total_tokens": 60
      },
      "_metadata": {
        "creator": "neosantara.xyz",
        "status": true,
        "tier": "Free"
        // ...
      }
    }
    ```
  </Accordion>

  <Accordion title="Sequential Tools">
    Some tasks may require calling multiple tools in sequence, using the output of one tool as the input to another. In such a case, NeosantaraAI will call one tool at a time.

    Here's an example of using a `get_location_from_ip` tool to get the user's location based on their IP, then passing that location to the `get_weather` tool:

    <CodeGroup>
      ```bash Shell theme={null}
      curl https://api.neosantara.xyz/v1/chat/completions \
        --header "Content-Type: application/json" \
        --header "Authorization: Bearer $NEOSANTARA_API_KEY" \
        --data '{
          "model": "nusantara-base",
          "max_tokens": 1024,
          "tools": [
            {
              "type": "function",
              "function": {
                "name": "get_location_from_ip",
                "description": "Get the current user location based on their IP address. This tool has no parameters or arguments.",
                "parameters": {
                  "type": "object",
                  "properties": {}
                }
              }
            },
            {
              "type": "function",
              "function": {
                "name": "get_weather",
                "description": "Get the current weather in a given location",
                "parameters": {
                  "type": "object",
                  "properties": {
                    "location": {
                      "type": "string",
                      "description": "The city and state, e.g. Jakarta, ID"
                    },
                    "unit": {
                      "type": "string",
                      "enum": ["celsius", "fahrenheit"],
                      "description": "The unit of temperature, either \"celsius\" or \"fahrenheit\""
                    }
                  },
                  "required": ["location"]
                }
              }
            }
          ],
          "messages": [{"role": "user", "content": "What is the weather like where I am?"}]
        }'
      ```

      ```python Python theme={null}
      from openai import OpenAI
      import json

      client = OpenAI(api_key="YOUR_NEOSANTARA_API_KEY", base_url="https://api.neosantara.xyz/v1")

      # First call to get tool_calls for get_location_from_ip
      response1 = client.chat.completions.create(
          model="nusantara-base",
          max_tokens=1024,
          tools=[
              { "type": "function", "function": { "name": "get_location_from_ip", "description": "...", "parameters": { "type": "object", "properties": {} } } },
              { "type": "function", "function": { "name": "get_weather", "description": "...", "parameters": { "type": "object", "properties": { "location": { "type": "string" } }, "required": ["location"] } } }
          ],
          messages=[{"role": "user", "content": "What is the weather like where I am?"}]
      )

      # Process the tool call
      if response1.choices[0].message.tool_calls:
          tool_call1 = response1.choices[0].message.tool_calls[0]
          tool_name1 = tool_call1.function.name
          tool_call_id1 = tool_call1.id

          # --- Execute get_location_from_ip tool ---
          if tool_name1 == "get_location_from_ip":
              mock_location_result = {"city": "Bandung", "state": "West Java", "country": "Indonesia"}
          else:
              mock_location_result = {"error": "Tool not found"}
          # --- End tool execution ---

          # Second call: provide location result and ask for weather
          response2 = client.chat.completions.create(
              model="nusantara-base",
              max_tokens=1024,
              tools=[
                  { "type": "function", "function": { "name": "get_location_from_ip", "description": "...", "parameters": { "type": "object", "properties": {} } } },
                  { "type": "function", "function": { "name": "get_weather", "description": "...", "parameters": { "type": "object", "properties": { "location": { "type": "string" } }, "required": ["location"] } } }
              ],
              messages=[
                  {"role": "user", "content": "What is the weather like where I am?"},
                  {"role": "assistant", "content": None, "tool_calls": [tool_call1]},
                  {"role": "tool", "tool_call_id": tool_call_id1, "content": json.dumps(mock_location_result)},
                  # No new user message, model is expected to make another tool call
              ]
          )

          # Process the second tool call (get_weather)
          if response2.choices[0].message.tool_calls:
              tool_call2 = response2.choices[0].message.tool_calls[0]
              tool_name2 = tool_call2.function.name
              tool_args2 = json.loads(tool_call2.function.arguments)
              tool_call_id2 = tool_call2.id

              # --- Execute get_weather tool ---
              if tool_name2 == "get_weather":
                  mock_weather_result = {"temperature": 25, "unit": "celsius", "description": "Sunny"}
              else:
                  mock_weather_result = {"error": "Tool not found"}
              # --- End tool execution ---

              # Third call: provide weather result and get final response
              response3 = client.chat.completions.create(
                  model="nusantara-base",
                  max_tokens=1024,
                  tools=[
                      { "type": "function", "function": { "name": "get_location_from_ip", "description": "...", "parameters": { "type": "object", "properties": {} } } },
                      { "type": "function", "function": { "name": "get_weather", "description": "...", "parameters": { "type": "object", "properties": { "location": { "type": "string" } }, "required": ["location"] } } }
                  ],
                  messages=[
                      {"role": "user", "content": "What is the weather like where I am?"},
                      {"role": "assistant", "content": None, "tool_calls": [tool_call1]},
                      {"role": "tool", "tool_call_id": tool_call_id1, "content": json.dumps(mock_location_result)},
                      {"role": "assistant", "content": None, "tool_calls": [tool_call2]},
                      {"role": "tool", "tool_call_id": tool_call_id2, "content": json.dumps(mock_weather_result)},
                  ]
              )
              print(response3)
      ```
    </CodeGroup>

    The full conversation flow would involve multiple API calls:

    1. **User asks**: "What's the weather like where I am?"
    2. **AI responds (Tool Call 1)**: Calls `get_location_from_ip`.
    3. **Your code executes tool**: Gets location (e.g., "Bandung, West Java").
    4. **Your code sends result to AI**: Sends `tool` message with location.
    5. **AI responds (Tool Call 2)**: Calls `get_weather` with "Bandung, West Java".
    6. **Your code executes tool**: Gets weather data (e.g., "25°C, Sunny").
    7. **Your code sends result to AI**: Sends `tool` message with weather.
    8. **AI responds (Final Answer)**: "The weather in Bandung, West Java is currently 25°C and sunny."
  </Accordion>

  <Accordion title="JSON Mode">
    You can use tools to instruct NeosantaraAI to produce JSON output that follows a specific schema, even if you don't intend to execute the output through a tool or function. This is often used for structured data extraction or generation.

    When using tools in this way:

    * You typically provide a **single** tool.
    * You should set `tool_choice` to `{"type": "function", "function": {"name": "your_tool_name"}}` to explicitly instruct the model to use that tool.
    * The `function`'s `parameters` define the exact JSON schema the model should adhere to.

    The following uses a `record_summary` tool to describe an image following a particular JSON format. Note that this requires a model with vision capabilities (e.g., `vision-emas-2045`).

    <CodeGroup>
      ```bash Shell theme={null}
      #!/bin/bash
      IMAGE_URL="[https://upload.wikimedia.org/wikipedia/commons/a/a7/Camponotus_flavomarginatus_ant.jpg](https://upload.wikimedia.org/wikipedia/commons/a/a7/Camponotus_flavomarginatus_ant.jpg)"
      IMAGE_MEDIA_TYPE="image/jpeg"
      IMAGE_BASE64=$(curl "$IMAGE_URL" | base64)

      curl https://api.neosantara.xyz/v1/chat/completions \
        --header "Content-Type: application/json" \
        --header "Authorization: Bearer $NEOSANTARA_API_KEY" \
        --data '{
          "model": "vision-emas-2045",
          "max_tokens": 1024,
          "tools": [{
            "type": "function",
            "function": {
              "name": "record_summary",
              "description": "Record summary of an image using well-structured JSON.",
              "parameters": {
                "type": "object",
                "properties": {
                  "key_colors": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "r": { "type": "number", "description": "red value [0.0, 1.0]" },
                        "g": { "type": "number", "description": "green value [0.0, 1.0]" },
                        "b": { "type": "number", "description": "blue value [0.0, 1.0]" },
                        "name": { "type": "string", "description": "Human-readable color name in snake_case, e.g. \"olive_green\" or \"turquoise\"" }
                      },
                      "required": [ "r", "g", "b", "name" ]
                    },
                    "description": "Key colors in the image. Limit to less than four."
                  },
                  "description": {
                    "type": "string",
                    "description": "Image description. One to two sentences max."
                  },
                  "estimated_year": {
                    "type": "integer",
                    "description": "Estimated year that the image was taken, if it is a photo. Only set this if the image appears to be non-fictional. Rough estimates are okay!"
                  }
                },
                "required": [ "key_colors", "description" ]
              }
            }
          }],
          "tool_choice": {"type": "function", "function": {"name": "record_summary"}},
          "messages": [
              {"role": "user", "content": [
                  {"type": "image_url", "image_url": {"url": "'$IMAGE_URL'"}},
                  {"type": "text", "text": "Describe this image in JSON format using the provided tool schema."}
              ]}
          ]
        }'
      ```

      ```python Python theme={null}
      from openai import OpenAI
      import json

      client = OpenAI(api_key="YOUR_NEOSANTARA_API_KEY", base_url="https://api.neosantara.xyz/v1")

      image_url = "[https://upload.wikimedia.org/wikipedia/commons/a/a7/Camponotus_flavomarginatus_ant.jpg](https://upload.wikimedia.org/wikipedia/commons/a/a7/Camponotus_flavomarginatus_ant.jpg)"

      message = client.chat.completions.create(
          model="vision-emas-2045", # Use a vision-capable model
          max_tokens=1024,
          tools=[
              {
                  "type": "function",
                  "function": {
                      "name": "record_summary",
                      "description": "Record summary of an image using well-structured JSON.",
                      "parameters": {
                          "type": "object",
                          "properties": {
                              "key_colors": {
                                  "type": "array",
                                  "items": {
                                      "type": "object",
                                      "properties": {
                                          "r": {"type": "number"},
                                          "g": {"type": "number"},
                                          "b": {"type": "number"},
                                          "name": {"type": "string"}
                                      },
                                      "required": ["r", "g", "b", "name"]
                                  },
                                  "description": "Key colors in the image. Limit to less than four."
                              },
                              "description": {
                                  "type": "string",
                                  "description": "Image description. One to two sentences max."
                              },
                              "estimated_year": {
                                  "type": "integer",
                                  "description": "Estimated year that the image was taken, if it is a photo."
                              }
                          },
                          "required": ["key_colors", "description"]
                      }
                  }
              }
          ],
          tool_choice={"type": "function", "function": {"name": "record_summary"}},
          messages=[
              {"role": "user", "content": [
                  {"type": "image_url", "image_url": {"url": image_url}},
                  {"type": "text", "text": "Describe this image in JSON format using the provided tool schema."}
              ]}
          ],
      )
      print(message)
      ```
    </CodeGroup>

    NeosantaraAI will return a response containing the structured JSON output within a `tool_calls` block:

    ```json theme={null}
    {
      "id": "chatcmpl-...",
      "object": "chat.completion",
      "created": 1701234567,
      "model": "vision-emas-2045",
      "choices": [
        {
          "index": 0,
          "message": {
            "role": "assistant",
            "content": null,
            "tool_calls": [
              {
                "id": "call_...",
                "type": "function",
                "function": {
                  "name": "record_summary",
                  "arguments": "{\"key_colors\": [{\"r\": 0.2, \"g\": 0.2, \"b\": 0.1, \"name\": \"dark_brown\"}, {\"r\": 0.8, \"g\": 0.7, \"b\": 0.5, \"name\": \"light_beige\"}], \"description\": \"A close-up shot of a camponotus flavomarginatus ant on a light-colored surface.\", \"estimated_year\": 2008}"
                }
              }
            ]
          },
          "finish_reason": "tool_calls"
        }
      ],
      "usage": {
        "prompt_tokens": 1500,
        "completion_tokens": 100,
        "total_tokens": 1600
      },
      "_metadata": {
        "creator": "neosantara.xyz",
        "status": true,
        "tier": "Free"
        // ...
      }
    }
    ```
  </Accordion>
</AccordionGroup>

***

## Pricing

Tool use requests are priced based on:

1. The total number of input tokens sent to the model (including the tokens from tool definitions in the `tools` parameter and tool call/result messages).
2. The number of output tokens generated (including tool calls generated by the model).
3. Additional charges may apply for specific capabilities (e.g., vision processing for image inputs).

The additional tokens from tool use come from:

* The `tools` array in API requests (tool names, descriptions, and parameter schemas).
* `tool_calls` generated by the model in assistant messages.
* `tool` messages (containing `tool_call_id` and `content`) sent by your application.

These token counts are added to your normal input and output tokens to calculate the total cost of a request.

Refer to our [pricing documentation](https://app.neosantara.xyz/pricing) for current per-model prices and usage tiers.

When you send a tool use prompt, just like any other API request, the response will output both input and output token counts as part of the reported `usage` metrics.

***

## Next Steps

Explore our other capabilities and API references:

<CardGroup cols={3}>
  <Card title="Image Generation" icon="panorama" href="/en/capability/image-generation">
    Generate high-quality images from text prompts.
  </Card>

  <Card title="Embeddings" icon="bezier-curve" href="/en/capability/embeddings">
    Convert text into numerical vectors for semantic search.
  </Card>
</CardGroup>
