Workshops ... Part 4: From toyaikit to PydanticAI

Part 4: From toyaikit to PydanticAI

The last step is to run the same agent with PydanticAI instead of ToyAIKit. We keep the same prompt and the same underlying tool implementations, but register the tools directly in PydanticAI and run the Q&A loop ourselves.

Installing PydanticAI

Install the PydanticAI package:

uv add pydantic-ai

Creating the Agent

We remove ToyAIKit completely and use PydanticAI's Agent directly:

from pydantic_ai import Agent, RunUsage

coding_agent = Agent(
    'openai:gpt-5.4-mini',
    instructions=AGENT_WITH_SKILLS_INSTRUCTIONS,
    tools=[
        agent_tools.read_file,
        agent_tools.write_file,
        agent_tools.see_file_tree,
        agent_tools.execute_bash_command,
        agent_tools.search_in_files,
        skills_tool.skill,
    ],
)

The agent gets the same instructions, the same tools, and the same model. Only the framework changes.

The print_messages helper

To show progress in the notebook, we use a helper that prints each message kind and its content:

def print_messages(messages):
    for m in messages:
        print(m.kind)
        for p in m.parts:
            part_kind = p.part_kind
            if part_kind == "user-prompt":
                print("USER:", p.content)
            if part_kind == "tool-call":
                print("TOOL CALL:", p.tool_name, p.args)
            if part_kind == "tool-return":
                print("TOOL RETURN:", p.tool_name)
            if part_kind == "text":
                print("ASSISTANT:", p.content)
        print()

The Q&A loop with message_history

PydanticAI supports message_history so we can maintain conversation state across turns:

messages = []
usage = RunUsage()

while True:
    user_prompt = input(">> ").strip()
    if not user_prompt or user_prompt.lower() == "stop":
        break

    result = await coding_agent.run(
        user_prompt,
        message_history=messages,
    )
    usage = usage + result.usage()

    print_messages(result.new_messages())
    messages.extend(result.new_messages())

Type stop to end the chat loop. After the conversation, inspect total usage:

usage

This is the same coding agent, now running with plain PydanticAI instead of ToyAIKit. The prompt, the tools, and the behavior are identical - only the framework plumbing changed.

Continue with Where to go from here for what was intentionally not covered.

Questions & Answers

Sign in to ask questions