Caicaini
Get started

Capabilities

Tools

Tools turn the model into a function caller. You declare what you want it to be able to do, the model decides when to call, you execute, and the result re-enters the conversation.

The tool-use loop

  1. Send the request with tools declared.
  2. The model either replies normally (stop_reason: end_turn) or asks to call a tool (stop_reason: tool_use).
  3. On tool_use, find the tool_use block in content, run your code with the supplied input, and append a user message containing a tool_result block referencing the same tool_use_id.
  4. Send the updated message list back. The model continues with the result in context. Repeat until stop_reason is no longer tool_use.

Declaring a tool

A tool is a name, a description, and a JSON schema for the input. Spend time on the description and on each parameter description — that text is what the model reads to decide whether to call your tool.

tool definition
{
  "name": "get_weather",
  "description": "Get the current weather for a city. Use this when the user asks about temperature, rain, or conditions outside.",
  "input_schema": {
    "type": "object",
    "properties": {
      "city": { "type": "string", "description": "City name in plain English." },
      "units": { "type": "string", "enum": ["celsius","fahrenheit"], "description": "Default celsius." }
    },
    "required": ["city"]
  }
}

Full loop, end to end

The example below sends one prompt, handles the resulting tool call, and prints the model's final answer. In production you would also handle the case where the model asks for a tool you do not recognize (return an error in the tool_result content) and the case where the loop runs more than a sensible number of iterations (cap at 8 or 10).

curl https://caicaini.com/v1/messages \
  -H "Authorization: Bearer cai_api_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "caicaini/sonnet",
    "max_tokens": 1024,
    "tools": [{
      "name": "get_weather",
      "description": "Get the current weather for a city.",
      "input_schema": {
        "type": "object",
        "properties": {
          "city": {"type": "string"},
          "units": {"type": "string", "enum": ["celsius","fahrenheit"]}
        },
        "required": ["city"]
      }
    }],
    "messages": [
      {"role": "user", "content": "What is the weather in Lisbon right now?"}
    ]
  }'

What a tool_use response looks like

response · stop_reason: tool_use
{
  "id": "msg_01H...",
  "type": "message",
  "role": "assistant",
  "content": [
    {
      "type": "tool_use",
      "id": "toolu_01XyZ...",
      "name": "get_weather",
      "input": { "city": "Lisbon", "units": "celsius" }
    }
  ],
  "model": "caicaini/sonnet",
  "stop_reason": "tool_use",
  "usage": { "input_tokens": 122, "output_tokens": 38, "credits_consumed": 76 }
}

Replying with a tool_result

user message
{
  "role": "user",
  "content": [
    {
      "type": "tool_result",
      "tool_use_id": "toolu_01XyZ...",
      "content": "{\"city\":\"Lisbon\",\"temperature\":21,\"units\":\"celsius\",\"conditions\":\"Sunny\"}"
    }
  ]
}

Forcing a tool call

By default the model decides whether to call a tool. Override that with tool_choice:

  • developers.docs.tools.toolChoiceItem1
  • developers.docs.tools.toolChoiceItem2
  • developers.docs.tools.toolChoiceItem3

Parallel tool calls

A single assistant turn can include multiple tool_use blocks. Run them in parallel client-side and reply with one user message containing the same number of tool_result blocks, in the same order.

Reporting errors back

If your tool fails, return a tool_result with a JSON-encoded error body and set is_error to true. The model will see the failure and either retry with different inputs or apologize to the user.

tool_result with is_error
{
  "type": "tool_result",
  "tool_use_id": "toolu_01XyZ...",
  "is_error": true,
  "content": "{\"error\":\"city_not_found\",\"city\":\"Atlantis\"}"
}

Which models support tools

All five virtual ids accept tools. Quality and reliability are highest on caicaini/opus and caicaini/sonnet; the smaller models are excellent for narrow, low-ambiguity tools. For complex agent loops with many tools and long-running reasoning, pair tools with extended thinking on caicaini/opus.