Introduction: Your First Agent Call

In the previous lesson, you learned the conceptual foundation of the Claude Agent SDK — understanding that Claude Code is the local agent runtime and the SDK is your programmatic interface to control it. Now it's time to write your first actual code that launches an agent and handles its response. You'll learn how to use the query() function to send a prompt, process streaming messages, extract text content, and read valuable metrics about the interaction.

Async-First Design: Powered by anyio

Before diving into agent interactions, you need to understand a key architectural choice in the Claude Agent SDK: it's built on anyio, not the standard asyncio library. This choice affects how you structure your code and run async functions.

If you've worked with Python's built-in asyncio library, you're already familiar with async programming patterns. The Claude Agent SDK uses similar patterns but through anyio, which is a compatibility layer that works with both asyncio and trio. While asyncio is Python's standard async library, anyio provides a cleaner, more consistent API and better handling of subprocesses and streaming—exactly what the SDK needs for managing the Claude Code runtime.

Here's how the two libraries compare in practice:

The patterns are nearly identical—you still define async functions, use await for async operations, and run your main function through a runtime. The key differences are:

  • anyio.run() instead of — handles event loop setup automatically
Understanding query(): One-Shot Agent Tasks

Building on your understanding of the Claude Agent SDK's async foundation, the query() function is your simplest entry point for interacting with the Claude Code agent. It allows you to send a single prompt to the agent runtime and stream back everything the agent does in response—all without needing to manage a session or conversation history.

Here's what that looks like in code:

When you use query(), the SDK launches a temporary agent instance, sends your prompt as the only message, and then streams back each step of the agent's reasoning and actions. Here's what happens behind the scenes:

  • The SDK starts a short-lived Claude Code agent session using the local runtime.
  • Your prompt is delivered as the sole message in this session.
  • The agent reasons about the task and plans its approach.
  • The agent generates responses based on what it's allowed to do.
    • By default, the agent can see available tools (like Read, Write, or Bash) but cannot execute them without explicit permission configuration. We'll explore tool configuration and permission modes in later lessons.
  • Each step is streamed back to you in real time as a sequence of typed messages.
  • When the agent finishes, the session closes—no memory or context is kept.

This stateless, one-shot approach makes query() ideal for single, self-contained actions such as "summarize this file," "create a script," or "refactor this function." You simply pass your prompt as a single string, and if you need to provide more context, you add it to that same string. This differs from working directly with the Anthropic API, where you'd build context by passing an array of message objects with roles and content—with query(), you manage all your context within a single string instead. Each call is independent and self-contained, with no conversation state carried between calls. While the function also supports an for more advanced batching scenarios, we'll focus on simple string prompts for now.

The Streaming Pattern: How Responses Arrive

The responses stream back as an async generator that yields message objects as the agent works. Rather than waiting for the entire process to complete, you receive each step as it happens, allowing you to display progress, log actions, or react to specific tool uses in real time. The async for loop waits for each message to arrive, processes it, and then waits for the next one until the agent completes its work. Notice that we're using anyio.run() to execute our async function—the SDK is built on async Python patterns, which allow it to handle streaming efficiently.

When you run the code, you'll see a sequence of messages arrive:

Extracting Text from Assistant Messages

To get the actual text the agent is saying, you need to filter the stream for AssistantMessage objects and extract text from their content blocks. Here's the complete pattern with comments explaining each step:

The pattern uses isinstance() to identify AssistantMessage objects in the stream, then iterates through the content array to find TextBlock instances. This type checking is necessary because the stream can contain other message types, and even within an AssistantMessage, the content array might include tool use blocks or other types of content alongside text. The block.text attribute gives you the agent's natural language response as a string you can display, log, or process further.

When you run this code, you'll see the agent's introduction:

Extracting Metrics from the Result Message

After the agent completes its work, the final ResultMessage provides valuable metrics about the interaction. Here's how to extract and display this information:

The ResultMessage includes the final output in result, the number of reasoning cycles in num_turns, the total cost in total_cost_usd, and detailed token counts in the usage dictionary. These metrics help you understand the efficiency and cost of your agent interactions—essential information when building applications that make many agent calls. Notice we use .get() when accessing the usage dictionary to safely handle cases where certain keys might not be present, providing a default value of 0.

When you run this code, you'll see the metrics output:

Summary: The Complete Query Pattern

You've now learned the fundamental pattern for working with the Claude Agent SDK: import the necessary types, define an async function, call query() with your prompt, iterate over streaming messages with async for, check message types with isinstance(), extract text from TextBlock objects within AssistantMessage content, and read metrics from the final ResultMessage. In the practice exercises ahead, you'll write this pattern yourself and build the hands-on experience that will serve you throughout the rest of this course.

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal