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.
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 in an options object, and if you need to provide more context, you add it to that same string. Each call is independent and self-contained, with no conversation state carried between calls.
Notice that we're using TypeScript's native async/await patterns with for await...of to iterate over the streaming responses. TypeScript's built-in async support handles all the complexity of managing the asynchronous stream, allowing you to focus on processing each message as it arrives. We cast the result to to help TypeScript understand the type of messages you'll receive.
The responses stream back as an async iterable 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 for await...of loop waits for each message to arrive, processes it, and then waits for the next one until the agent completes its work.
When you run the code, you'll see a sequence of messages arrive:
This simple example shows three message types streaming back:
- System message (
type: "system"): Initializes the agent session with configuration details, including the working directory, available tools, model version, slash commands, Claude Code version, and session settings.
To get the actual text the agent is saying, you need to filter the stream for assistant messages and extract text from their content blocks. TypeScript's discriminated unions make this elegant — the message.type property determines which other properties are available. Here's the complete pattern with comments explaining each step:
The pattern uses a switch statement on message.type to identify assistant messages, then iterates through the message.message.content array to find text blocks. This type checking is necessary because the stream can contain other message types, and even within an assistant message, the content array might include tool use blocks or other types of content alongside text. The block.text property gives you the agent's natural language response as a string you can display, log, or process further.
Notice the use of the nullish coalescing operator (??) when accessing message.message.content — this provides a safe fallback to an empty array if content is undefined, preventing runtime errors. TypeScript's type system helps catch these potential issues at compile time.
When you run this code, you'll see the agent's introduction:
After the agent completes its work, the final result message provides valuable metrics about the interaction. Here's how to extract and display this information:
The result message 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 object. The usage object also includes information about cache usage (cache_read_input_tokens) and service tier, which help you understand how efficiently the agent is using cached context. These metrics help you understand the efficiency and cost of your agent interactions — essential information when building applications that make many agent calls.
Notice how we use TypeScript's optional chaining (message.usage?.input_tokens) combined with the nullish coalescing operator (?? 0) to safely access nested properties that might be undefined. We also check if the property exists using the operator before accessing it, since not all result messages include this field. These TypeScript patterns help you write robust code that handles edge cases gracefully.
You've now learned the fundamental pattern for working with the Claude Agent SDK: import the necessary functions and types using ES6 imports with import type for type-only imports, define an async function, call query() with your prompt in an options object, iterate over streaming messages with for await...of, use switch statements on message.type to handle different message types, extract text from blocks where block.type === "text" within message.message.content, leverage TypeScript's type system features like discriminated unions and optional chaining, and read metrics from the final result message. 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.
