OpenAI Agents SDKopenai-agents 0.22 · Python 3.10+
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
25 small wins to finish your pathNext lesson

A model you can run for free

A browser cannot call OpenAI. So rather than stop here, you are going to write a model.

The SDK reaches a model through exactly one method, get_response. Anything that provides it is a model as far as the SDK is concerned. That is the whole opening, and it is what makes this course runnable.

What a model hands back

Two shapes, and no more. Either words, or a request for a tool. These two helpers build them, and they are the only verbose part of the file because they are the real types the SDK uses.

python
def say(text):
    """Plain words, in the shape the SDK expects back."""
    return ResponseOutputMessage(
        id="msg", role="assistant", status="completed", type="message",
        content=[ResponseOutputText(text=text, type="output_text", annotations=[])],
    )
python
def call(tool_name, **arguments):
    """A request for a tool, instead of an answer."""
    n = next(_calls)
    return ResponseFunctionToolCall(
        id=f"fc_{n}", call_id=f"call_{n}", name=tool_name,
        arguments=json.dumps(arguments), type="function_call",
    )

Each request gets its own number. Reusing one makes the SDK think the same request came back twice, and it stops with an error rather than guessing. Worth knowing, because it is the sort of thing a hand written fake gets wrong.

The model itself

It works two ways, and every lesson after this uses one of them.

python
class PretendModel(Model):
    def __init__(self, replies=None):
        self.replies = list(replies) if replies else None
        self.turn = 0

    async def get_response(self, system_instructions, input, model_settings, tools,
                           output_schema, handoffs, tracing, **kwargs):
        item = self._next(input, tools)
        self.turn += 1
        return ModelResponse(output=[item], usage=Usage(), response_id=None)

That signature is long because it is the real one. The SDK hands a model everything it might need: the instructions, the conversation, the tools, the shape the answer should take, and the agents this one is allowed to pass work to. This model reads two of them and ignores the rest, and lessons 10 and 13 are where the other two start to matter.

Hand it a list of replies and it returns them in order. Most lessons do that, because the lesson is about the plumbing and not about guessing what a model would say.

Hand it nothing and it falls back on three rules: if a tool has just answered, repeat what it said; if the question mentions an order id and there are tools, ask for one; otherwise ask a question back.

python
    def _next(self, input, tools):
        if self.replies is not None:
            i = min(self.turn, len(self.replies) - 1)
            reply = self.replies[i]
            return say(reply) if isinstance(reply, str) else reply
        answered = _last_tool_output(input)
        if answered:
            return say(f"Here is what I found. {answered}")
        ...

Run it and see both shapes

The bottom of the file builds one of each and prints them, so you can see exactly what the SDK is handed.

python
words = say("Order A17 shipped on 3 March.")
request = call("lookup_order", order_id="A17")

print("answering with words:", words.content[0].text)
print("asking for a tool:   ", request.name, request.arguments)

A real model reads the words and predicts. This one reads the words and follows rules you can point at. Everything else about it, the types it returns and the method it provides, is exactly what a real one does.

Keep this one
This file is used by every lesson after this one, and the panel loads it for you. You can also download it to use on your own machine.
Try it yourself
  • Change the text in say and run it again.
  • Build a scripted model with two replies and print what each turn returns.
  • Print the whole words object and look at the fields a real model fills in.

Slow is fine. Stopping is the only problem.