Introduction & Lesson Overview

Welcome back! In the previous lesson, you learned the basics of the OpenAI Agents SDK in Python. You discovered how agents differ from simple chat models, explored the agent loop, and practiced running agents synchronously, asynchronously, and with streaming. This foundation is essential, as it allows you to build agents that can reason, plan, and act in multiple steps.

In this lesson, we will take a closer look at what happens after you run an agent. Specifically, you will learn how to interpret the results returned by the agent, understand the structure of the RunResult object, and see how to use these results to chain agents together. By the end of this lesson, you will be able to extract key information from an agent’s run and use it to build more complex, multi-step workflows — such as having one agent generate a recipe and another agent write a blog post about it. This knowledge will prepare you for the hands-on practice exercises that follow.

Understanding The RunResult Object

When you run an agent using the OpenAI Agents SDK, the result is not just a simple string or message. Instead, the SDK returns a RunResult object, which contains detailed information about the agent’s execution. This object is your window into what happened during the agent’s run.

The most important properties of the RunResult object are:

  • input: The original input you provided to the agent.
  • new_items: A list of events or actions that occurred during the run, such as tool calls, reasoning steps, or messages.
  • final_output: The last response produced by the agent. This is usually what you want to show to the user.
  • last_agent: The last agent that was executed, which is useful if your workflow involves multiple agents.
  • to_input_list(): A method that converts the run’s context into a list of messages, preserving the full conversation history. This is especially useful for chaining agents or continuing a conversation, as it provides all the necessary context in the correct format.

These properties help you understand not just the answer, but also how the agent arrived at it. This is especially important when you want to chain agents together or keep track of the conversation’s context.

Example: Creating a Recipe Agent

Before we look at the different properties of the RunResult object, let’s quickly revisit how you might define and run an agent that generates recipes. Suppose you want an agent that acts as a creative chef and provides detailed smoothie recipes. You can set this up as follows:

import asyncio
from agents import Agent, Runner

# Define a Recipe Chef agent
recipe_agent = Agent(
    name="Recipe Chef",
    instructions=(
        "You are a creative chef. Provide a detailed healthy smoothie recipe with a title, a list of ingredients, "
        "and step-by-step instructions. Do not include extra commentary. Output only the recipe text."
    ),
    model="gpt-4.1"
)

async def main():
    # Run the Recipe Chef agent
    result = await Runner.run(
        starting_agent=recipe_agent,
        input="Give me a recipe for a healthy smoothie."
    ) 

    # Process result...

if __name__ == "__main__":
    asyncio.run(main())

In this example, the recipe_agent is set up with clear instructions and a model. When you run the agent with a prompt like "Give me a recipe for a healthy smoothie," you receive a RunResult object. Next, let’s look at each part of the RunResult object in more detail, using simple code snippets to illustrate how they work.

The input Property

The input property holds the original prompt or message you sent to the agent. This is the starting point for the agent’s reasoning and response. For example, if you ask for a smoothie recipe, the input will simply be your request:

print(result.input)

When you print this property, you’ll see exactly what was provided to the agent at the beginning of its run:

Give me a recipe for a healthy smoothie.

This is useful for logging, debugging, or when you want to confirm exactly what was asked of the agent.

The new_items Property

The new_items property is a list of all the events or actions that occurred during the agent’s run. This includes messages generated by the agent, tool calls, and any intermediate reasoning steps. By inspecting new_items, you can see the agent’s process and how it arrived at its answer.

print(result.new_items)

The output reveals the internal steps and messages produced by the agent. For example:

[MessageOutputItem(agent=Agent(name='Recipe Chef', instructions='You are a creative chef. Provide a detailed healthy smoothie recipe with a title, a list of ingredients, and step-by-step instructions. Do not include extra commentary. Output only the recipe text.', ...), raw_item=ResponseOutputMessage(id='msg_6810db1bf920819285a3139f5ff7f11301a3f563cfc91bb3', content=[ResponseOutputText(annotations=[], text='**Green Energy Breakfast Smoothie**\n\n**Ingredients:**\n- 1 cup unsweetened almond milk\n- 1 cup fresh spinach leaves, packed\n- 1/2 cup frozen mango chunks\n- 1/2 frozen banana\n- 1 tablespoon chia seeds\n- 1 tablespoon almond butter\n- 1/4 teaspoon ground cinnamon\n- 1/2 teaspoon fresh grated ginger (optional)\n- 1 teaspoon honey or maple syrup (optional)\n- 4-5 ice cubes\n\n**Instructions:**\n1. Add the almond milk and spinach to a blender. Blend until smooth and no leafy chunks remain.\n2. Add the frozen mango, frozen banana, chia seeds, almond butter, cinnamon, ginger, honey or maple syrup (if using), and ice cubes.\n3. Blend until creamy and smooth, about 30-45 seconds.\n4. Pour into a glass and serve immediately.', type='output_text')], role='assistant', status='completed', type='message'), type='message_output_item')]

This property is especially helpful for understanding the agent’s reasoning, debugging, or building features that need to explain the agent’s steps.

The final_output Property

The final_output property contains the agent’s final answer or response. This is typically what you want to display to the user or use as the result of the agent’s work. For a recipe agent, this would be the complete recipe text:

print(result.final_output)

When you print this property, you get the main output from the agent, ready to be shown to the user or passed to another agent:

**Green Energy Breakfast Smoothie**

**Ingredients:**
- 1 cup unsweetened almond milk
- 1 cup fresh spinach leaves, packed
- 1/2 cup frozen mango chunks
- 1/2 frozen banana
- 1 tablespoon chia seeds
- 1 tablespoon almond butter
- 1/4 teaspoon ground cinnamon
- 1/2 teaspoon fresh grated ginger (optional)
- 1 teaspoon honey or maple syrup (optional)
- 4-5 ice cubes

**Instructions:**
1. Add the almond milk and spinach to a blender. Blend until smooth and no leafy chunks remain.
2. Add the frozen mango, frozen banana, chia seeds, almond butter, cinnamon, ginger, honey or maple syrup (if using), and ice cubes.
3. Blend until creamy and smooth, about 30-45 seconds.
4. Pour into a glass and serve immediately.

This is the main output you’ll use in your application or pass to another agent.

The to_input_list() Method

The to_input_list() method converts the run’s context into a list of messages, preserving the full conversation history. This is especially useful for chaining agents or continuing a conversation, as it provides all the necessary context in the correct format.

print(result.to_input_list())

When you print the result of this method, you’ll see a list of message dictionaries, each with a role and content. This format is ideal for passing context to another agent or continuing the conversation seamlessly:

[{'role': 'user', 'content': 'Give me a recipe for a healthy smoothie.'}, {'role': 'assistant', 'content': '**Green Energy Breakfast Smoothie**\n\n**Ingredients:**\n- 1 cup unsweetened almond milk\n- 1 cup fresh spinach leaves, packed\n- 1/2 cup frozen mango chunks\n- 1/2 frozen banana\n- 1 tablespoon chia seeds\n- 1 tablespoon almond butter\n- 1/4 teaspoon ground cinnamon\n- 1/2 teaspoon fresh grated ginger (optional)\n- 1 teaspoon honey or maple syrup (optional)\n- 4-5 ice cubes\n\n**Instructions:**\n1. Add the almond milk and spinach to a blender. Blend until smooth and no leafy chunks remain.\n2. Add the frozen mango, frozen banana, chia seeds, almond butter, cinnamon, ginger, honey or maple syrup (if using), and ice cubes.\n3. Blend until creamy and smooth, about 30-45 seconds.\n4. Pour into a glass and serve immediately.'}]

This method ensures that when you pass information to another agent, it has access to the full context, leading to more accurate and relevant responses.

Chaining Agents Using Results

A powerful feature of the OpenAI Agents SDK is the ability to chain agents together, passing the output and context from one agent directly into another. This allows you to build multi-step workflows where each agent builds on the work of the previous one.

Let’s look at a practical example. Suppose you have a recipe_agent that generates a smoothie recipe, and a blog_agent that writes a blog post about that recipe. After running the first agent, you can use its result to provide full context to the second agent. Here’s how you can do this:

import asyncio
from agents import Agent, Runner

# Define a Recipe Chef agent
recipe_agent = Agent(
    name="Recipe Chef",
    instructions=(
        "You are a creative chef. Provide a detailed healthy smoothie recipe with a title, a list of ingredients, "
        "and step-by-step instructions. Do not include extra commentary. Output only the recipe text."
    ),
    model="gpt-4.1"
)

# Define a Blog Writer agent
blog_agent = Agent(
    name="Blog Writer",
    instructions=(
        "You are an engaging blog writer. Given the recipe text for a healthy smoothie, write an inspiring blog post "
        "that includes an introduction, a detailed description of the recipe, and a conclusion. Output only the blog post text."
    ),
    model="gpt-4.1"
)

async def main():
    # Run the Recipe Chef agent
    result = await Runner.run(
        starting_agent=recipe_agent,
        input="Give me a recipe for a healthy smoothie."
    )

    # Run the Blog Writer agent with the Recipe Chef agent's results
    result = await Runner.run(
        starting_agent=blog_agent,
        input=result.to_input_list() + [{"role": "user", "content": "Write a blog post about the recipe."}]
    )

    # Process the result...

if __name__ == "__main__":
    asyncio.run(main())

In this workflow, after the recipe_agent generates a recipe, you use the to_input_list() method to capture the full conversation context. You then append a new user message asking for a blog post about the recipe. This combined input is passed to the blog_agent, ensuring it has all the information it needs to write a relevant and accurate blog post.

Viewing the Final Output (Blog Post)

After running the blog_agent, you can access the final blog post text using the final_output property:

print(result.final_output)

This will output something like:

### Energize Your Morning with the Ultimate Green Breakfast Smoothie

There’s something empowering about starting the day off on a healthy note. For me, nothing sets the tone quite like a vibrant, nutrient-packed smoothie that fuels my morning with energy, flavor, and a little bit of zen. That’s why I’m excited to share my go-to recipe: the Green Energy Breakfast Smoothie! This wholesome blend of greens, fruits, and superfoods is perfect for busy mornings or as a quick pick-me-up any time of day.

#### Why You’ll Love This Smoothie

This recipe is more than just a pretty green drink—it’s a powerhouse of vitamins, fiber, and healthy fats to keep you full and focused. Fresh spinach loads you up on antioxidants and iron, while frozen mango and banana give natural sweetness and a creamy, dreamy texture. Chia seeds add a boost of omega-3s and protein, almond butter offers a touch of richness, and warming cinnamon and ginger give it a spicy kick. The best part? It’s incredibly easy to make and delicious enough for the whole family to enjoy.

#### Recipe: Green Energy Breakfast Smoothie

**Ingredients:**
- 1 cup unsweetened almond milk
...
Viewing the Last Agent Executed

You can also check which agent produced the final output by accessing the last_agent property:

print(result.last_agent)

This will show you the details of the agent that generated the blog post:

Agent(name='Blog Writer', instructions='You are an engaging blog writer. Given the recipe text for a healthy smoothie, write an inspiring blog post that includes an introduction, a detailed description of the recipe, and a conclusion. Output only the blog post text.', handoff_description=None, handoffs=[], model='gpt-4.1', model_settings=ModelSettings(temperature=None, top_p=None, frequency_penalty=None, presence_penalty=None, tool_choice=None, parallel_tool_calls=False, truncation=None, max_tokens=None), tools=[], mcp_servers=[], input_guardrails=[], output_guardrails=[], output_type=None, hooks=None, tool_use_behavior='run_llm_again', reset_tool_choice=True)

This is useful for debugging or for tracking which agent handled the final step in a multi-agent workflow.

Summary & Preparation For Practice

In this lesson, you learned how to interpret the results of an agent run using the RunResult object. You explored its key properties — input, new_items, final_output, last_agent, and to_input_list() — and saw how to use them to chain agents together in a multi-step workflow. By understanding how to extract and use these results, you are now ready to build more advanced applications that combine the strengths of multiple agents.

In the next set of practice exercises, you will get hands-on experience working with agent results and chaining agents together. This will help you solidify your understanding and prepare you for even more powerful agentic workflows. Well done on reaching this point — let’s continue building your skills!

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