Skip to content

Tools (function calling)

Give the model a set of callable functions and let it decide when to invoke them. The model returns tool-call requests; your code executes them; you pass the results back for the model's final reply.

The tool-schema shape differs per provider — this page shows the native flagship for each cloud. The Anthropic through-line's tool API is documented in Claude tool use and works identically on Bedrock / Vertex / Foundry with the same tools=[...] payload.

Official docs verified 2026-08-08

Native flagship

The example: a get_current_temperature tool. The reader can swap in any function-schema — the shape is the load-bearing part.

import os, json
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["AZURE_OPENAI_API_KEY"],
    base_url=os.environ["AZURE_OPENAI_BASE_URL"],
)

tools = [{
    "type": "function",
    "function": {
        "name": "get_current_temperature",
        "description": "Get current temperature for a given location.",
        "parameters": {
            "type": "object",
            "properties": {
                "location": {"type": "string", "description": "City name"},
            },
            "required": ["location"],
        },
    },
}]

resp = client.chat.completions.create(
    model=os.environ["AZURE_OPENAI_DEPLOYMENT"],
    messages=[{"role": "user", "content": "Temperature in London?"}],
    tools=tools,
)
call = resp.choices[0].message.tool_calls[0]
args = json.loads(call.function.arguments)
print(call.function.name, args)   # get_current_temperature {'location': 'London'}
import os
from google import genai
from google.genai import types

client = genai.Client(
    vertexai=True,
    project=os.environ["GOOGLE_CLOUD_PROJECT"],
    location=os.environ.get("GOOGLE_CLOUD_LOCATION", "us-central1"),
)

get_temp = types.FunctionDeclaration(
    name="get_current_temperature",
    description="Get current temperature for a given location.",
    parameters=types.Schema(
        type=types.Type.OBJECT,
        properties={
            "location": types.Schema(type=types.Type.STRING),
        },
        required=["location"],
    ),
)

resp = client.models.generate_content(
    model=os.environ.get("GEMINI_MODEL", "gemini-3.6-flash"),
    contents="Temperature in London?",
    config=types.GenerateContentConfig(tools=[types.Tool(function_declarations=[get_temp])]),
)
fc = resp.candidates[0].content.parts[0].function_call
print(fc.name, dict(fc.args))     # get_current_temperature {'location': 'London'}
import os, boto3

client = boto3.client(
    "bedrock-runtime",
    region_name=os.environ.get("AWS_REGION", "us-east-1"),
)

tool_config = {
    "tools": [{
        "toolSpec": {
            "name": "get_current_temperature",
            "description": "Get current temperature for a given location.",
            "inputSchema": {"json": {
                "type": "object",
                "properties": {
                    "location": {"type": "string", "description": "City name"},
                },
                "required": ["location"],
            }},
        },
    }],
}

resp = client.converse(
    modelId=os.environ.get("BEDROCK_MODEL_ID", "amazon.nova-pro-v1:0"),
    messages=[{"role": "user", "content": [{"text": "Temperature in London?"}]}],
    toolConfig=tool_config,
)
# tool call arrives as a contentBlock of type toolUse
for block in resp["output"]["message"]["content"]:
    if "toolUse" in block:
        print(block["toolUse"]["name"], block["toolUse"]["input"])

Claude through-line (same shape on all 3 clouds)

Claude's tools shape is one dict passed to messages.create(tools=[...]) regardless of which client you use (AnthropicFoundry / AnthropicVertex / AnthropicBedrock). No per-cloud adaptation.

tools = [{
    "name": "get_current_temperature",
    "description": "Get current temperature for a given location.",
    "input_schema": {
        "type": "object",
        "properties": {"location": {"type": "string"}},
        "required": ["location"],
    },
}]

msg = client.messages.create(          # client from any of Foundry / Vertex / Bedrock
    model=…,
    max_tokens=1024,
    tools=tools,
    messages=[{"role": "user", "content": "Temperature in London?"}],
)
for block in msg.content:
    if block.type == "tool_use":
        print(block.name, block.input)

The pattern in code

  • tools=[…] on the request.
  • Model returns a tool-call content block (not final text).
  • Your app executes the tool, appends its result as a new turn, and re-calls the model to get the final natural-language reply.
  • The reply is normal chat text — the loop is optional; call once, execute, call again.

The full multi-turn tool loop for each provider is in examples/call-an-llm/service/tools_loop.py.