Agents

How to Build AI Chatbots That Actually Work Using Parlant

Parlant is a framework designed to help developers create AI chatbots that don't randomly break or give weird responses when users ask simple questions. This guide walks you through building conversational agents that actually understand context, remember what they're talking about, and respond in ways that make sense to real humans.

Parlant is a framework that helps developers build AI agents that won't embarrass you when real customers start using them. You know that frustrating situation where your AI chatbot works perfectly during testing, but the moment actual users get their hands on it, everything falls apart?

That's exactly what Parlant is trying to solve. These AI agents love to ignore your carefully crafted system prompts, give completely wrong answers at the worst possible moments, crash and burn on edge cases you never thought of, or just act totally different from one conversation to the next.

Parlant tackles this mess by moving away from the whole "cross your fingers and hope the prompt works" approach. Instead of just writing better prompts and praying the AI follows them, it gives you actual tools to set clear rules and integrate systems properly. This way, your agent can handle real-world data in ways that are both safe and predictable, instead of randomly deciding to go rogue when someone asks it something unexpected.

In this tutorial, we will create an insurance agent that can retrieve open claims, file new claims, and provide detailed policy information, demonstrating how to integrate domain-specific tools into a Parlant-powered AI system for consistent and reliable customer support. Check out the FULL CODES here.

Getting Everything Set Up and Ready to Go

pip install parlant
import asyncio
from datetime import datetime
import parlant.sdk as p


Setting Up What Your Agent Can Actually Do

The following code block introduces three tools that simulate interactions an insurance assistant might need.

  • The get_open_claims tool represents an asynchronous function that retrieves a list of open insurance claims, allowing the agent to provide users with up-to-date information about pending or approved claims.
  • The file_claim tool accepts claim details as input and simulates the process of filing a new insurance claim, returning a confirmation message to the user.

Finally, the get_policy_details tool provides essential policy information, such as the policy number and coverage limits, enabling the agent to respond accurately to questions about insurance coverage. Check out the FULL CODES here.

@p.tool
async def get_open_claims(context: p.ToolContext) -> p.ToolResult:
    return p.ToolResult(data=["Claim #123 - Pending", "Claim #456 - Approved"])
@p.tool
async def file_claim(context: p.ToolContext, claim_details: str) -> p.ToolResult:
    return p.ToolResult(data=f"New claim filed: {claim_details}")
@p.tool
async def get_policy_details(context: p.ToolContext) -> p.ToolResult:
    return p.ToolResult(data={
        "policy_number": "POL-7788",
        "coverage": "Covers accidental damage and theft up to $50,000"
    })

Setting Up Your Agent's Vocabulary and Conversation Flows

Here's where we teach the agent the important stuff it needs to know and how conversations should actually flow. The glossary is basically like giving your agent a cheat sheet with all the key business info - things like your customer service phone number, when you're open, and other details it needs to get right every single time.

This way, when someone asks "What are your hours?" the agent isn't guessing or making stuff up - it's pulling from the reliable information you've already defined.

The journeys describe step-by-step processes for specific tasks. In this example, one journey walks a customer through filing a new insurance claim, while another focuses on retrieving and explaining policy coverage details. Check out the FULL CODES here.

1async def add_domain_glossary(agent: p.Agent):
2    await agent.create_term(
3        name="Customer Service Number",
4        description="You can reach us at +1-555-INSURE",
5    )
6    await agent.create_term(
7        name="Operating Hours",
8        description="We are available Mon-Fri, 9AM-6PM",
9    )
10async def create_claim_journey(agent: p.Agent) -> p.Journey:
11    journey = await agent.create_journey(
12        title="File an Insurance Claim",
13        description="Helps customers report and submit a new claim.",
14        conditions=["The customer wants to file a claim"],
15    )
16    s0 = await journey.initial_state.transition_to(chat_state="Ask for accident details")
17    s1 = await s0.target.transition_to(tool_state=file_claim, condition="Customer provides details")
18    s2 = await s1.target.transition_to(chat_state="Confirm claim was submitted")
19    await s2.target.transition_to(state=p.END_JOURNEY)
20    return journey
21async def create_policy_journey(agent: p.Agent) -> p.Journey:
22    journey = await agent.create_journey(
23        title="Explain Policy Coverage",
24        description="Retrieves and explains customer's insurance coverage.",
25        conditions=["The customer asks about their policy"],
26    )
27    s0 = await journey.initial_state.transition_to(tool_state=get_policy_details)
28    await s0.target.transition_to(
29        chat_state="Explain the policy coverage clearly",
30        condition="Policy info is available",
31    )
32    await agent.create_guideline(
33        condition="Customer presses for legal interpretation of coverage",
34        action="Politely explain that legal advice cannot be provided",
35    )
36    return journey

Defining the main runner

The main runner ties together all the components defined in earlier cells and launches the agent. It starts a Parlant server, creates the insurance support agent, and loads its glossary, journeys, and global guidelines. It also handles edge cases such as ambiguous customer intent by prompting the agent to choose between relevant journeys. Finally, once the script is executed, the server becomes active and prints a confirmation message. You can then open your browser and navigate to http://localhost:8800 to access the Parlant UI and begin interacting with the insurance agent in real time. Check out the FULL CODES here.

1async def main():
2    async with p.Server() as server:
3        agent = await server.create_agent(
4            name="Insurance Support Agent",
5            description="Friendly and professional; helps with claims and policy queries.",
6        )
7        await add_domain_glossary(agent)
8        claim_journey = await create_claim_journey(agent)
9        policy_journey = await create_policy_journey(agent)
10        # Disambiguation: if intent is unclear
11        status_obs = await agent.create_observation(
12            "Customer mentions an issue but doesn't specify if it's a claim or policy"
13        )
14        await status_obs.disambiguate([claim_journey, policy_journey])
15        # Global guideline
16        await agent.create_guideline(
17            condition="Customer asks about unrelated topics",
18            action="Kindly redirect them to insurance-related support only",
19        )
20        print("✅ Insurance Agent is ready! Open the Parlant UI to chat.")
21if __name__ == "__main__":
22    import asyncio
23    asyncio.run(main())

Wrapping Up

Parlant is a framework that helps developers build AI chatbots that won't randomly break or act weird when real users start chatting with them. Instead of just writing better prompts and hoping for the best, Parlant lets you set up clear rules, define important business terms in a glossary, map out conversation flows, and integrate tools properly. The end result? AI agents that actually behave consistently and handle real-world interactions without going off the rails or ignoring what you've taught them.