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

# Agent with Tool Calling

> Build a Claude agent that orchestrates complex workflows using tool calls.

<Card title="View Source Code" icon="github" href="https://github.com/tensorlakeai/cookbooks/tree/main/agent_with_tools">
  Check out the full source code for this example on GitHub.
</Card>

This tutorial demonstrates how to build an **Agent with Tool Calling** using Tensorlake and the Anthropic API. This agent orchestrates a multi-step workflow where Claude decides which tools to call and in what order to answer user queries effectively.

## Overview

The Agent with Tool Calling follows this pattern:

1. **User Query**: The user asks a question that requires external data or actions (e.g., "What's the weather like at my current location?").
2. **Tool Selection**: Claude analyzes the query and selects the appropriate tool(s) to call (e.g., `get_ip_address`, `get_location_info`).
3. **Tool Execution**: The selected tool functions are executed within Tensorlake's isolated environment.
4. **Information Synthesis**: The tool outputs are fed back to Claude, which then synthesizes a final answer or decides to call more tools.

## Prerequisites

* **Python 3.11+**
* **Tensorlake Account** and CLI installed.
* **Anthropic API Key**

## Implementation (`app.py`)

Here is the complete implementation for the Agent with Tool Calling.

```python theme={null}
import os
from typing import Dict, Any

from anthropic import Anthropic
from pydantic import BaseModel, Field
from tensorlake import application, function, Image

# Define the runtime environment
image = Image(name="agent-with-tools").run("pip install anthropic requests tensorlake pydantic")

class ToolInput(BaseModel):
    name: str
    arguments: Dict[str, Any]

@application()
@function(image=image, secrets=["ANTHROPIC_API_KEY"])
def agent_loop(query: str) -> str:
    """
    Main entry point for the Agent with Tool Calling.
    Orchestrates the conversation loop between Claude and the tools.
    """
    client = Anthropic()
    messages = [{"role": "user", "content": query}]
    
    # Define available tools for Claude
    tools = [
        {
            "name": "get_ip_address",
            "description": "Get the public IP address of the current execution environment.",
            "input_schema": {"type": "object", "properties": {}}
        },
        {
            "name": "get_location_info",
            "description": "Get location information based on an IP address.",
            "input_schema": {
                "type": "object",
                "properties": {
                    "ip_address": {"type": "string", "description": "The IP address to lookup."}
                },
                "required": ["ip_address"]
            }
        },
        {
            "name": "get_weather_alerts",
            "description": "Get current weather alerts for a location.",
            "input_schema": {
                "type": "object",
                "properties": {
                    "location": {"type": "string", "description": "City or location name."}
                },
                "required": ["location"]
            }
        }
    ]

    while True:
        # Ask Claude for the next step
        response = client.messages.create(
            model="claude-3-opus-20240229",
            max_tokens=1024,
            tools=tools,
            messages=messages
        )
        
        # If Claude decides to stop and give an answer
        if response.stop_reason == "end_turn":
            return response.content[0].text

        # If Claude wants to use a tool
        if response.stop_reason == "tool_use":
            tool_use = next(block for block in response.content if block.type == "tool_use")
            tool_name = tool_use.name
            tool_input = tool_use.input
            tool_use_id = tool_use.id

            print(f"Tool Call: {tool_name} with input: {tool_input}")
            
            # Execute the requested tool
            if tool_name == "get_ip_address":
                tool_result = get_ip_address()
            elif tool_name == "get_location_info":
                tool_result = get_location_info(tool_input["ip_address"])
            elif tool_name == "get_weather_alerts":
                tool_result = get_weather_alerts(tool_input["location"])
            else:
                tool_result = f"Error: Tool {tool_name} not found."

            # Add tool result to conversation history
            messages.append({"role": "assistant", "content": response.content})
            messages.append({
                "role": "user",
                "content": [
                    {
                        "type": "tool_result",
                        "tool_use_id": tool_use_id,
                        "content": str(tool_result)
                    }
                ]
            })

@function(image=image)
def get_ip_address() -> str:
    """Simulates getting the public IP address."""
    # In a real scenario, you might use `requests.get('https://api.ipify.org').text`
    return "203.0.113.1"

@function(image=image)
def get_location_info(ip_address: str) -> str:
    """Simulates getting location info for an IP."""
    return f"Location for {ip_address}: San Francisco, CA"

@function(image=image)
def get_weather_alerts(location: str) -> str:
    """Simulates getting weather alerts."""
    return f"No active weather alerts for {location}."
```

## Running Locally

To test the agent locally, add this code block to the end of `app.py`:

```python theme={null}
if __name__ == "__main__":
    from tensorlake.applications import run_local_application
    
    # Run the application locally
    result = run_local_application(agent_loop, "What are the current weather alerts for my location?")
    print(f"Agent Output: {result}")
```

Then run the script:

```bash theme={null}
export ANTHROPIC_API_KEY=your_key_here
python app.py
```

## Deploying to Tensorlake

Deploy your agent to the cloud for production use:

```bash theme={null}
tl secrets set ANTHROPIC_API_KEY=your_key_here
tl deploy app.py
```

Your agent is now live! It can autonomously chain tool calls to solve complex user requests, all running within secure, scalable Tensorlake functions.
