Part 2: ToyAIKit runner
We have a Python function and its OpenAI tool schema. Now we put the same example behind a small chat runner, so we don't have to write the function-calling loop by hand.
ToyAIKit pieces
ToyAIKit is an educational library I use across workshops. It's not the
framework you'd reach for in a serious production system. It keeps the
notebook short and makes the tool calls visible enough for learning.
Import the pieces we need:
from toyaikit.tools import Tools
from toyaikit.chat import IPythonChatInterface
from toyaikit.llm import OpenAIClient
from toyaikit.chat.runners import OpenAIResponsesRunner
The four pieces each have one job:
Toolsstores Python callables and their tool descriptions.IPythonChatInterfacegives us a small chat UI inside Jupyter.OpenAIClientwraps the OpenAI SDK client.OpenAIResponsesRunnerruns the Responses API tool loop.
Register the joke tool
Create a Tools object and add the function with the schema from the
previous step:
tools_obj = Tools()
tools_obj.add_tool(make_joke, make_joke_description)
The schema is still useful here because we already wrote it by hand. Later,
when we add methods from an object, ToyAIKit can infer schemas from type
hints and docstrings.
Create the runner
The chat interface handles input and output in the notebook:
chat_interface = IPythonChatInterface()
openai_client = OpenAIClient(client=OpenAI())
Pass the tools, developer prompt, chat interface, and client into the runner:
runner = OpenAIResponsesRunner(
tools=tools_obj,
developer_prompt=system_prompt,
chat_interface=chat_interface,
llm_client=openai_client,
)
Now run it.
runner.run()
Try a message like this in the notebook chat:
Tell me a personalized joke. My name is Alex.
You should see a function call to make_joke, the arguments the model
chose, the function output, and the final assistant message.
Jupyter is useful here
Agents don't require Jupyter, but it helps here. We can run one cell, look at the result, then change a small piece and run again. You build a coding agent through iteration, so a fast feedback loop matters.
We can move the same runner pattern into a web application later. For today, we get the chat interface for free in the notebook.
Read the runner later
You don't need to understand all of ToyAIKit before continuing, but read
through the runner code once we wrap up.
The code shows the tool loop that the OpenAI API requires:
- send messages and tool definitions to the model
- receive model output
- execute requested tool calls
- append tool results to the conversation
- continue until the assistant returns text
As an exercise, paste the runner class into ChatGPT and ask why there are two loops. That's a good way to see what the educational wrapper is hiding.
Continue with Part 3: Django template.