Skip to main content

Tutorial: Your First Anthropic Agent

In this tutorial, you will build a Claude-powered agent that can solve complex tasks by calling custom tools. You will learn how to define Flyte tasks as tools, configure an agent with specific instructions, and execute the agent loop using the Anthropic plugin.

By the end of this guide, you will have a working agent that can fetch weather data and perform calculations to answer multi-step questions.

Prerequisites

Before you begin, ensure you have the following:

  1. Anthropic API Key: You need a valid API key from Anthropic.
  2. Installation: Install the necessary plugin:
    pip install flyteplugins-anthropic
  3. Flyte Environment: This tutorial assumes you are running code within a Flyte-enabled environment where secrets can be managed.

Step 1: Define Your Tools

Tools in this framework are simply Flyte tasks. The agent uses the task's docstring and type hints to understand when and how to call it.

Create a file named agent_tutorial.py and define two tasks:

import flyte
from flyteplugins.anthropic import function_tool, Agent, run_agent

# Configure the environment with your Anthropic API key
env = flyte.TaskEnvironment(
"claude-agent",
secrets=[flyte.Secret(key="anthropic_api_key", as_env_var="ANTHROPIC_API_KEY")],
)

@env.task
async def get_weather(city: str) -> str:
"""Get the current weather for a specific city."""
# In a real app, you'd call a weather API here
weather_data = {
"New York": "72°F and Sunny",
"London": "60°F and Rainy",
"Tokyo": "75°F and Cloudy"
}
return weather_data.get(city, "Weather data not available.")

@env.task
async def multiply(a: float, b: float) -> float:
"""Multiply two numbers together."""
return a * b

In this step, you defined two standard Flyte tasks. Note that the docstrings are critical; Claude uses them as the "tool description" to decide which tool to invoke.

Step 2: Create the Agent Configuration

The Agent class allows you to define the personality and constraints of your Claude assistant. You can specify the model, system instructions, and the list of tools it has access to.

# Convert the Flyte tasks into Anthropic-compatible tools
weather_tool = function_tool(get_weather)
math_tool = function_tool(multiply)

# Configure the agent
my_agent = Agent(
name="WeatherMathAssistant",
instructions="You are a helpful assistant that can check weather and do math. "
"Always use the provided tools for these tasks.",
model="claude-sonnet-4-20250514",
tools=[weather_tool, math_tool],
max_iterations=5
)

The function_tool function inspects your Flyte tasks and automatically generates the JSON schema Claude needs. By wrapping them in an Agent object, you group the configuration and tools into a single reusable entity.

Step 3: Run the Agent Loop

To execute the agent, use the run_agent function. This function manages the conversation loop: it sends your prompt to Claude, executes any tools Claude requests, sends the results back, and repeats until a final answer is reached.

@env.task
async def run_my_agent(prompt: str) -> str:
return await run_agent(
prompt=prompt,
agent=my_agent
)

The run_agent function handles the anthropic.AsyncAnthropic client internally. It uses the ANTHROPIC_API_KEY provided in the TaskEnvironment to authenticate.

Step 4: Putting It All Together

Here is the complete script. You can run this locally or register it to a Flyte cluster.

import asyncio
import flyte
from flyteplugins.anthropic import function_tool, Agent, run_agent

env = flyte.TaskEnvironment(
"claude-agent",
secrets=[flyte.Secret(key="anthropic_api_key", as_env_var="ANTHROPIC_API_KEY")],
)

@env.task
async def get_weather(city: str) -> str:
"""Get the current weather for a specific city."""
weather_data = {"New York": "72", "London": "60", "Tokyo": "75"}
return weather_data.get(city, "unknown")

@env.task
async def multiply(a: float, b: float) -> float:
"""Multiply two numbers together."""
return a * b

@env.task
async def weather_math_agent(city: str, factor: float) -> str:
# 1. Define tools
tools = [function_tool(get_weather), function_tool(multiply)]

# 2. Configure Agent
agent_cfg = Agent(
instructions="Check the weather and multiply the temperature by the factor.",
tools=tools
)

# 3. Run the loop
prompt = f"What is the weather in {city} multiplied by {factor}?"
return await run_agent(prompt=prompt, agent=agent_cfg)

if __name__ == "__main__":
# Local execution example
result = asyncio.run(weather_math_agent(city="New York", factor=2.0))
print(f"Agent Result: {result}")

What happens behind the scenes?

  1. Prompt Sent: Claude receives your prompt: "What is the weather in New York multiplied by 2.0?"
  2. Tool Call 1: Claude identifies it needs get_weather(city="New York").
  3. Execution: The run_agent loop executes the get_weather Flyte task and receives "72".
  4. Tool Call 2: Claude receives the result and now calls multiply(a=72, b=2.0).
  5. Final Response: Claude receives 144.0 and generates the final text: "The weather in New York is 72°F, and multiplied by 2.0, the result is 144.0."

Next Steps

  • Complex Types: Try using dataclasses or FlyteFile as inputs to your tools; function_tool uses the Flyte type engine to handle them automatically.
  • Iteration Limits: If your agent gets stuck in a loop, adjust max_iterations in the Agent configuration.
  • Tracing: Use @flyte.trace on your tool functions to see detailed execution logs in the Flyte UI.