Skip to main content
In this lesson we’ll refactor the single-file demo into a small, well-structured project and implement a typed, validated ticket workflow using Pydantic. The goal is to keep the agent focused on orchestration while tools implement domain logic and validation.
A presentation slide titled "Implementing Ticket Schemas" with a dark curved shape on the right containing the word "Demo." A small "© Copyright KodeKloud" appears in the bottom-left corner.
Goals for this lesson:
  • Create a schemas package with a Pydantic Ticket model.
  • Move domain logic into a tools package.
  • Add a typed create_ticket tool that returns a validated, structured ticket.
  • Keep the agent orchestrator thin—use tools for lookup, checks, and ticket creation.
File layout

1) Ticket schema (Pydantic)

Use a Pydantic model to enforce a consistent ticket shape on the Python side. The LLM does not need to produce the exact JSON; instead, the agent will call a tool which builds and validates the Pydantic model, returning a reliable dict. Example schemas/ticket.py:
References:

2) Typed tool input: CreateTicketArgs

Define a typed input model for the create-ticket tool. This ensures the tool receives validated input and makes intent explicit. Example CreateTicketArgs (place this inside tools/helpdesk_tools.py or a shared module):

3) Tool implementations (lookup, service status, create ticket)

Move domain logic into tools/helpdesk_tools.py. For the demo we use simple in-memory backends and return structured dicts indicating “status” plus result payload or error message. Example excerpts for tools/helpdesk_tools.py:
Notes:
  • These implementations always return a small structured dict with a status field. This makes it easy for the agent to branch on success vs error.
  • In a real system, replace fake backends with database calls, API clients, or ticketing system integrations.

4) Wrapping tools for the agent

In your agent module you wrap these functions with FunctionTool so the agent can call them. The agent keeps instruction and orchestration logic, while tools encapsulate domain behavior and validation. Example agent.py excerpt:
Using tool-level structured outputs (tools return validated dicts produced from Pydantic models) provides strong guarantees about data shape while still letting the LLM decide when and how to call those tools.

5) Example run (console)

A typical session shows the agent calling tools, receiving structured outputs, and creating a ticket:
Behind the scenes
  • The agent called check_service_status and received a structured response: {status: "success", service: "vpn", status_text: "degraded"}.
  • Given the impact, the agent built a CreateTicketArgs payload and invoked create_ticket.
  • create_ticket_impl instantiated the Ticket Pydantic model, validated it, and returned ticket.model_dump() as a structured result.
  • The resulting dict can be logged, stored in a database, or sent to a ticketing API.
Summary
  • Refactored the demo into schemas/ and tools/.
  • Added a Pydantic Ticket model and a typed create-ticket tool that returns a validated ticket dictionary.
  • Moved domain logic into tools and left the agent focused on orchestration and instructions.
  • This pattern—tool-level structured outputs + typed inputs—maintains LLM flexibility while guaranteeing reliable data shapes for downstream systems.
Next steps
  • Add grounding sources (internal IT policies, runbooks) so the agent consults authoritative documentation.
  • Integrate a real user directory and ticketing API to replace demo backends.
  • Add telemetry and audit logging for ticket creation and tool calls.
Links and references

Watch Video