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

# Tool calling agent

> Build a complete agent loop with external tools

# Tool calling agent

This example shows a complete agent that can use external tools. The model decides when to call a tool, your code executes it, and the result goes back into the conversation.

## Define your tools

```python agent.py theme={null}
from openai import OpenAI
import os
import json

client = OpenAI(
    api_key=os.environ["RADIUM_API_KEY"],
    base_url="https://api.radium.cloud/v1",
)

# 1. Define the tools the model can use
TOOLS = [
    {
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "Get the current weather for a city",
            "parameters": {
                "type": "object",
                "properties": {
                    "city": {
                        "type": "string",
                        "description": "The city name, e.g. Toronto",
                    }
                },
                "required": ["city"],
            },
        },
    },
    {
        "type": "function",
        "function": {
            "name": "calculate",
            "description": "Evaluate a mathematical expression",
            "parameters": {
                "type": "object",
                "properties": {
                    "expression": {
                        "type": "string",
                        "description": "A math expression, e.g. 2 + 2 * 3",
                    }
                },
                "required": ["expression"],
            },
        },
    },
]


# 2. Implement the tool logic
def get_weather(city: str) -> str:
    # In production, call a real weather API
    return f"22°C and sunny in {city}."


def calculate(expression: str) -> str:
    try:
        # Use a safe evaluator in production
        result = eval(expression, {"__builtins__": {}}, {})
        return str(result)
    except Exception as e:
        return f"Error: {e}"


TOOL_MAP = {
    "get_weather": get_weather,
    "calculate": calculate,
}


# 3. Run the agent loop
def run_agent(user_message: str, model: str = "clarke-1.0") -> str:
    messages = [{"role": "user", "content": user_message}]
    max_iterations = 5

    for _ in range(max_iterations):
        response = client.chat.completions.create(
            model=model,
            messages=messages,
            tools=TOOLS,
            tool_choice="auto",
        )

        message = response.choices[0].message

        # If the model just replies with text, we're done
        if not message.tool_calls:
            return message.content or ""

        # Otherwise, execute each tool call and append results
        messages.append({
            "role": "assistant",
            "content": message.content or "",
            "tool_calls": [
                {
                    "id": tc.id,
                    "type": tc.type,
                    "function": {
                        "name": tc.function.name,
                        "arguments": tc.function.arguments,
                    },
                }
                for tc in message.tool_calls
            ],
        })

        for tool_call in message.tool_calls:
            name = tool_call.function.name
            args = json.loads(tool_call.function.arguments)
            result = TOOL_MAP[name](**args)

            messages.append({
                "role": "tool",
                "tool_call_id": tool_call.id,
                "content": result,
            })
            print(f"  🔧 {name}({args}) → {result}")

    return "Agent reached the maximum number of tool calls."


if __name__ == "__main__":
    query = "What is the weather in Tokyo and what is 15 * 23?"
    print(f"User: {query}\n")
    answer = run_agent(query)
    print(f"\nAgent: {answer}")
```

## Expected output

```
User: What is the weather in Tokyo and what is 15 * 23?

  🔧 get_weather({'city': 'Tokyo'}) → 22°C and sunny in Tokyo.
  🔧 calculate({'expression': '15 * 23'}) → 345

Agent: The weather in Tokyo is 22°C and sunny, and 15 * 23 = 345.
```

## How it works

1. **Define tools** as JSON schemas — the model uses the `description` to decide which tool to call.
2. **First request** → model sees the tools and the user query. It may emit `tool_calls` instead of text.
3. **Execute tools** → your code runs the matching function with the parsed arguments.
4. **Return results** → append a `tool` message with the output for each call.
5. **Second request** → model sees the tool results and generates the final answer.

## Parallel tool calls

Radium models support **parallel tool calls** — the model can request multiple tools at once. The example above handles this by iterating over `message.tool_calls` and executing each one before sending results back.

## Next steps

<CardGroup cols={2}>
  <Card title="Structured extraction" icon="table" href="/examples/structured-extraction">Extract typed data from text</Card>
  <Card title="RAG chatbot" icon="messages" href="/examples/rag-chatbot">Give your agent access to documents</Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.