DRAFT ONLY

Building AI Agents: Agentic Workflows, Tool Use, and External Actions

Introduction: From Single-Turn Bots to True AI Agents

AI is rapidly evolving beyond simple Q&A. Instead of just responding to questions, modern AI agents can plan, take actions, use external tools, and adapt to new situations. In this chapter, you'll learn how to build such agents using DSPy's agentic workflows—unlocking automation that goes far beyond traditional chatbots. All examples use DSPy 2.6.14 or later, ensuring compatibility with current and upcoming releases.

Let's start with a simple analogy. Most LLM-powered apps today are like calculators: you provide an input, get an answer, and that's it. This is called a single-turn interaction—one prompt, one response, with no persistent memory or follow-up.

Agents, by contrast, act more like digital assistants. They can break a complex goal into steps, make decisions, use external tools or APIs, and adapt their plan as new information comes in. This is called an agentic workflow: a dynamic, multi-step process where the AI pursues a goal, not just a single answer.

Let's compare these two patterns with some code.

Comparing Single-Turn and Agentic Patterns

# Single-turn (classic LLM app)
def ask_llm(question):
    return llm.generate(question)

# Multi-turn agentic pattern (conceptual pseudocode)
def agent_conversation(user_goal):
    plan = agent.plan(user_goal)
    while not plan.is_complete():
        next_action = plan.next_step()
        result = agent.act(next_action)
        plan.update(result)
    return plan.final_result()

# Note: This is conceptual pseudocode. DSPy provides similar primitives in its agent APIs.

The first function, 'ask_llm', is typical of most prompt-based apps: send a question, get an answer. The second, 'agent_conversation', illustrates the agentic approach: the agent plans, acts, and adapts step by step until it achieves the goal.

Why does this matter? Because real-world tasks rarely fit into a single step. Imagine a travel assistant that finds flights, checks the weather, books hotels, and notifies you if your passport is expiring. Or a customer support agent that handles refunds, sends follow-up messages, and updates your account—without human intervention. These are agentic workflows, and they're the key to real business automation.

Until recently, building such agents required complex, fragile code. DSPy changes that. With DSPy, you define clear workflows, register external tools, and let your agent decide when and how to use them—all in modular, maintainable Python. DSPy also supports async (asynchronous) tools for high-performance, scalable agent actions.

Let's see a quick example. Suppose you want your agent to check the weather for a city. Here's how you define and register an async tool in DSPy 2.6.14+:

Defining and Registering an Async Tool in DSPy

import dspy

@dspy.Tool(
    name="get_weather",
    description="Get current weather for a city",
    async_tool=True  # Enables async execution in DSPy 2.6.14+
)
async def get_weather(city: str) -> str:
    # In production, replace with an async call to a real weather API
    return f"Sunny in {city}"

# Register the tool with the agent
agent = dspy.Agent(tools=[get_weather])

Here's what's happening:

  1. Define an async Python function, 'get_weather', that takes a city and returns a (mock) weather report. In real usage, this would make an asynchronous call to a weather API.
  2. Decorate it with '@dspy.Tool', specifying 'async_tool=True' so DSPy recognizes it as an async tool.
  3. Register the tool when creating your agent. Now, the agent can call 'get_weather' as part of its reasoning process, and can run multiple such tools in parallel for efficiency.