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}."