Reading the run result
Runner.run gives back one object, and almost everything you will want to know about a run is on it.
The four you will use
print("final_output:", result.final_output)
print("last_agent: ", result.last_agent.name)
print("turns used: ", len(result.raw_responses))What it cost
The same object carries the token count, one level down, on the context wrapper.
usage = result.context_wrapper.usage
print("requests:", usage.requests)
print("tokens: ", usage.total_tokens)requests is how many times a model was called, input_tokens and output_tokens split the cost, and total_tokens adds them up. This is the number that grows quietly as a conversation gets long, which is what lesson 20 is about.
Two requests here and zero tokens, because our stand-in never tokenised anything. Against a real model the requests stay the same and the tokens do not.
| Field | What it holds |
|---|---|
final_output | The answer. A string, unless you asked for a shape in lesson 10. |
new_items | Everything that happened, in order. Tool calls, tool answers, messages. |
last_agent | Which agent finished the run. It is not always the one you started, as lesson 13 shows. |
raw_responses | One entry per trip to the model, so its length is the number of turns. |
Walking the items
Every item has a type, and ItemHelpers pulls the text out of a message without you reaching into the raw shapes.
for item in result.new_items:
if item.type == "message_output_item":
print(ItemHelpers.text_message_output(item))print("final_output:", result.final_output)
print("last_agent: ", result.last_agent.name)
print("turns used: ", len(result.raw_responses))
print()
for item in result.new_items:
print(f"{type(item).__name__:<20} {ItemHelpers.text_message_output(item) if item.type == 'message_output_item' else ''}")Two turns for a three item run. The first turn produced the tool request, the tool ran without going near the model, and the second turn produced the words. Turns and items are not the same count, and that is worth holding on to when you start reading traces.
final_output is a convenience. It is the text of the last message, and it is the field you reach for ninety per cent of the time. new_items is the field you reach for when something went wrong.- Print
result.to_input_list()and see the conversation the next run would start from. - Ask a question with no order id and compare the item count.
- Print
item.raw_itemfor the tool call and read the arguments.
Little by little, you're building something great.