The desk agent and its tools
The shop desk is an Agent that answers an order question by calling a tool, the first piece of the support desk you finish in this part.
Last updated: 28 Sep, 2026 · openai-agents 0.22.3
Runner and the RunResult object arrived in the lesson on Runner and the RunResult object, and the tool decorator arrived in function_tool: a function the model can call. Here they meet: one agent, one tool, one order question, run against the ShopModel stand-in so no API key is needed.
The pieces, and where each came from
| Piece | From lesson |
|---|---|
| An Agent with a name and instructions | Agent: name, instructions and tools |
| A @function_tool the model can call | function_tool: a function the model can call |
| Runner.run_sync and result.final_output | Runner and the RunResult object |
| ShopModel, a model that runs with no key | Model: a stand-in you can run without a key |
The lookup tool
A tool is a plain function with the @function_tool decorator. Its docstring tells the model what it does.
@function_tool
def lookup_order(order_id: str) -> str:
"Look up an order by its id."
return f"Order {order_id}: shipped on 3 March, arriving 7 March."The desk agent
The desk is an Agent that carries the tool in its tools list and uses the stand-in model.
desk = Agent(
name="Shop desk",
instructions="Help shoppers with their orders.",
tools=[lookup_order], # the desk may call this tool
model=ShopModel(), # the stand-in, no API key
)Asking one order question
Runner.run_sync drives the run and hands back a result; final_output is the answer.
result = Runner.run_sync(desk, "Where is my order A17?")
print(result.final_output)The desk answering an order question
The whole desk in one file, ready to run against the stand-in.
from agents import Agent, Runner, function_tool, set_tracing_disabled
from shop_model import ShopModel
set_tracing_disabled(True)
@function_tool
def lookup_order(order_id: str) -> str:
"Look up an order by its id."
return f"Order {order_id}: shipped on 3 March, arriving 7 March."
desk = Agent(
name="Shop desk",
instructions="Help shoppers with their orders.",
tools=[lookup_order],
model=ShopModel(),
)
result = Runner.run_sync(desk, "Where is my order A17?")
print(result.final_output)
What the run produced
- The stand-in saw the word order, so it asked to call
lookup_orderwith id A17 instead of answering straight away. - The runner ran the tool and fed its return value back to the model.
- The final answer is the tool's line, because the model turns a tool result into the reply.
A desk with a tool vs a desk with none
| Setup | The desk's reply to the order question |
|---|---|
| Desk with lookup_order | Order A17: shipped on 3 March, arriving 7 March. |
| Desk with no tools | How can I help with your order? |
When the desk needs a tool
- Any answer that depends on live data, an order status, a balance, a booking, belongs in a tool, not in the instructions.
- The desk stays small: the model decides, the tool fetches, the model replies.
Related
- Previous: Capping a run with max_turns
- Next: A refund specialist by handoff
- Reference: Tools
- Ask about a different order id and notice the stand-in still returns A17; a real model would read the id from your message.
- Remove
tools=[lookup_order]and rerun; the desk falls back to the greeting. - Add a second tool,
store_hours(), and see that the stand-in still reaches for lookup_order on an order question.
Every expert started right here.