# Table of Contents - [Introduction | Parlant](#introduction-parlant) - [Guidelines | Parlant](#guidelines-parlant) - [Ensuring Coherence | Parlant](#ensuring-coherence-parlant) - [Sessions | Parlant](#sessions-parlant) - [Glossary | Parlant](#glossary-parlant) - [Context Variables | Parlant](#context-variables-parlant) - [Tools & APIs | Parlant](#tools-apis-parlant) --- # Introduction | Parlant [Skip to main content](#__docusaurus_skipToContent_fallback) On this page Welcome to Parlant![​](#welcome-to-parlant "Direct link to Welcome to Parlant!") --------------------------------------------------------------------------------- ![Parlant Funny Agent](/img/cartoon_2_3.png) Parlant is a framework that transforms how AI agents make decisions in customer-facing scenarios. With Parlant, you can not only **spin up and serve an LLM agent in minutes**—with a full-fledged & responsive conversation management API—but, more importantly, you can **continuously guide and improve its decision making** and general behavior, easily and reliably. ### 🥜 Parlant in a Nutshell[​](#-parlant-in-a-nutshell "Direct link to 🥜 Parlant in a Nutshell") Unlike traditional approaches that rely on prompt engineering or conversational flow charts, **Parlant introduces a dynamic control system that ensures agents follow your specific business rules**, in the form of behavioral guidelines that you provide, by matching and activating the appropriate combination of guidelines for every specific context. When an agent needs to respond to a customer, Parlant's engine evaluates the situation, checks relevant guidelines, gathers necessary information through your tools, and continuously re-evaluates its approach based on your guidelines as new information emerges. When it's time to generate a message, **Parlant implements self-critique mechanisms** to ensure that the agent's responses precisely align with your intended behavior as given by the contextually-matched guidelines. Parlant comes pre-built with responsive session (conversation) management, a **detection mechanism for incoherence and contradictions in guidelines**, content-filtering, jailbreak protection, an integrated sandbox UI for behavioral testing, native API clients in Python and TypeScript, and other goodies. The entire source code—licensed under Apache 2.0—can be found [on GitHub](https://github.com/emcie-co/parlant) . Parlant is developed and maintained primarily by [Emcie](/docs/about) , along with other contributors. ### 🙋‍♂️ Who Is Parlant For?[​](#️-who-is-parlant-for "Direct link to 🙋‍♂️ Who Is Parlant For?") Parlant is the right tool for the job if you're building an LLM-based chat agent, and: 1. Your use case places a high importance on **behavioral precision and consistency**, particularly in customer-facing scenarios 2. Your agent is expected to undergo **continuous behavioral refinements** and changes, and you need a way to implement those changes efficiently and confidently 3. You're expected to **maintain a large set of behavioral guidelines**, and you need to maintain them coherently and with version-tracking 4. Conversational **UX and user-engagmeent is an important concern** for your use case, and you want to easily control the flow and tone of conversations ### 🌟 What Makes Parlant Different?[​](#-what-makes-parlant-different "Direct link to 🌟 What Makes Parlant Different?") In a word: _guidance._ Parlant's engine revolves around solving one key problem: How can we reliably guide customer-facing agents to behave in alignment with our needs and intentions? Hence Parlant's fundamentally different approach to agent building: [Managed Guidelines](/docs/concepts/customization/guidelines) . $ parlant guideline create \ --agent-id MY_AGENT_ID \ --condition "the customer wants to return an item" \ --action "get the order number and item name and then help them return it" By giving structure to behavioral guidelines, and _granularizing_ guidelines (i.e. making each behavioral guideline a first-class entity in the engine), Parlant's engine is able to offer unprecedented control, quality, and efficiency in building LLM-based agents: 1. **Reliability:** Running focused self-critique in real-time, per guideline, to ensure it is actually followed 2. **Explainability:** Providing feedback around its interpretation of guidelines in each real-life context, which helps in troubleshooting and improvement 3. **Maintainability:** Helping you maintain a coherent set of guidelines by detecting and alerting you to possible contradictions (gross or subtle) in your instructions ### 😤 The Pain Point[​](#-the-pain-point "Direct link to 😤 The Pain Point") Think of an [LLM](https://en.wikipedia.org/wiki/Large_language_model) like a stranger with an encyclopedic knowledge of different approaches to every possible situation. Although incredibly powerful, **this combination of versatility and lack of context is precisely why it so rarely behaves as we'd expect**—there are too many options. This is why, without clear [guidelines](/docs/concepts/customization/guidelines) , an LLM will always try to draw optimistically from its vast but unfiltered set of observations, potentially using tones that are out of touch with the customer and the situation, making irrelevant offers, getting into loops, or just losing focus and going off on tangents. ![Cartoon2](/img/cartoon_1_1.png) ![Cartoon2](/img/cartoon_1_2.png) **Parlant lets you step in and guide your agent easily**, every time you see it missing the mark. You do this primarily by using [guidelines](/docs/concepts/customization/guidelines) , as well as other behavioral control structures that Parlant supports, like [tools](/docs/concepts/customization/tools) , [glossary terms](/docs/concepts/customization/glossary) , and [context variables](/docs/concepts/customization/context-variables) . Parlant is designed from the ground up to let you easily and **quickly train and align your agent's behavior when you find issues** or get feedback from customers and business experts. The result is an effective, controlled, and incremental process of improvement. The premise behind Parlant is that [unguided AI agents are a dead-end](/docs/about#the-intrinsic-need-for-guidance) . Without guidance, an AI agent is bound to encounter numerous ambiguities, and end up trying to resolve them using many incorrect or even problematic approaches. **Only we can authoritatively disambiguate the agent's choices**—so we should be able to do so dynamically, thus gradually guiding them to become better performers. ![Cartoon2](/img/cartoon_2_1.png) ![Cartoon2](/img/cartoon_2_2.png) ![Cartoon2](/img/cartoon_2_3.png) Parlant was designed to let you guide the behavior of customer-facing agents simply, quickly, and reliably—so you can feel confident to iterate on your agents' behavior whenever necessary, teaching them how to best serve your customers. Instead of an agent that goes around the bush, meanders, and offers irrelevant solutions or answers, **Parlant paves the way for you to build an agent that is guided, focused, and feels well-designed.** A focused and guided agent is one your customers could actually use! ![Cartoon3](/img/cartoon_1_1.png) ![Cartoon3](/img/cartoon_3_2.png) So pack your bags and get ready to create some awesome customer-facing agents. Or crappy ones. You've got the controls now and the choice is yours. Let's start! * [Welcome to Parlant!](#welcome-to-parlant) * [🥜 Parlant in a Nutshell](#-parlant-in-a-nutshell) * [🙋‍♂️ Who Is Parlant For?](#️-who-is-parlant-for) * [🌟 What Makes Parlant Different?](#-what-makes-parlant-different) * [😤 The Pain Point](#-the-pain-point) --- # Guidelines | Parlant [Skip to main content](#__docusaurus_skipToContent_fallback) On this page Guidelines[​](#guidelines-1 "Direct link to Guidelines") --------------------------------------------------------- Guidelines are the most powerful customization feature within Parlant. So although they are quite simple in principle, there is a lot to say about them. ### What Are Guidelines[​](#what-are-guidelines "Direct link to What Are Guidelines") Guidelines allow us to shape an [agent](/docs/concepts/entities/agents) 's behavior in two key scenarios: when out-of-the-box responses don't meet our expectations, or when we simply want to ensure consistent behavior across all interactions. For example, an AI Travel Agent's out-of-the-box response to a customer wanting to book a room may be, _"Sure, I can help you book a room. When will you be staying?"_ If we wanted the response to be more energetic and appreciative of the customer's business, yet we liked how it's immediately leading with a question, we could add guidelines to these effects, making our agent consistently answer along the lines of, _"I'm so happy you chose our hotel! Let's get you the best room for your needs, right away. When will you be staying?"_ ### The Structure of Guidelines[​](#the-structure-of-guidelines "Direct link to The Structure of Guidelines") In Parlant, each guideline is composed of two parts: the **condition** and the **action**. The action is the actual instruction part of the guideline. For example, "Offer a discount." The condition is the part the specifies _the condition in which the action should take place_. For example, "It is a holiday". In this example, the guideline would be: > * **Condition:** It is a holiday > * **Action:** Offer a discount When speaking informally about guidelines, we often describe them in _when/then_ form: When , Then , or in this case, When it is a holiday, Then offer a discount. ### How Parlant Uses Guidelines[​](#how-parlant-uses-guidelines "Direct link to How Parlant Uses Guidelines") LLMs are a magnificent creation, built on the principle of [statistical attention](https://arxiv.org/abs/1706.03762) in text. Yet this attention span is finite—and when it comes to following instructions, they need some support. Behind the scenes, Parlant ensures that agent responses are precisely guided, by dynamically managing the LLM's context. Before each response, Parlant loads only the guidelines relevant to the conversation's current state. This real-time context management maximizes the alignment of each response with intended behavior. info Another important trick that Parlant employs here is supervising the agent's outputs before it reaches the [customer](/docs/concepts/entities/customers) , to ensure to the utmost degree that guidelines were correctly adhered to. To achieve this, researchers working on Parlant have devised a prompting mechanism called **Conformal Guidance**. This page will be updated with a link to the research paper when it's out. For now, you can find more information on this under [Coherence](/docs/concepts/customization/coherence) . ### Managing Guidelines[​](#managing-guidelines "Direct link to Managing Guidelines") Parlant is built to make guideline management as simple as possible. Normally, guidelines are added when business experts request behavioral changes in the agent. In such cases, developers can use Parlant to make those changes and iterate quickly and reliably with business experts. Here's a practical example: When Sales requests: "The agent should first ask about customer pain points before discussing our solution," implementing this takes just a minute by adding the following guideline: > * **Condition:** The customer has yet to specify their current pain points > * **Action:** Seek to understand their pain points before talking about our solution Once added, Parlant automatically ensures this guideline is followed consistently across all conversations. Here's an example of how to add a guideline: * CLI * Python * TypeScript $ parlant guideline create \ --agent-id AGENT_ID \ --condition CONDITION \ --action ACTION from parlant.client import ( GuidelineContent, GuidelinePayload, ParlantClient, Payload,)client = ParlantClient(base_url=SERVER_ADDRESS)# Start evaluating the guideline's impactevaluation = client.evaluations.create( agent_id=AGENT_ID, payloads=[ Payload( kind="guideline", guideline=GuidelinePayload( content=GuidelineContent( condition=CONDITION, action=ACTION, ), operation="add", coherence_check=True, connection_proposition=True, ) ) ],)# Wait for the evaluation to complete and get the invoiceinvoices = client.evaluations.retrieve( evaluation.id, wait_for_completion=60, # Wait up to 60 seconds).invoices# Only continue if the guideline addition was approvedif all(invoice.approved for invoice in invoices): client.guidelines.create(AGENT_ID, invoices)else: print("Guideline was not approved:") print(invoices) import { ParlantClient } from 'parlant-client';const client = new ParlantClient({ environment: SERVER_ADDRESS });// Start evaluating the guideline's impactconst evaluation = await client.evaluations.create({ agentId: AGENT_ID, payloads: [{ kind: "guideline", guideline: { content: { condition: CONDITION, action: ACTION, }, operation: "add", coherenceCheck: true, connectionProposition: true, }}] }); // Wait for the evaluation to complete and get the invoice const { invoices } = await client.evaluations.retrieve(evaluation.id, { waitForCompletion: 60, // Wait up to 60 seconds }); // Only continue if the guideline addition was approved if (invoices.every(invoice => invoice.approved)) { await client.guidelines.create(AGENT_ID, { invoices }); } else { console.error("Guideline was not approved:"); console.dir(invoices, { depth: null }); } The examples above start the creation process with something called an _evaluation_, which has a bit of complexity to it. Let's now take a look at what that is and why it's there. ### Maintaining Coherence[​](#maintaining-coherence "Direct link to Maintaining Coherence") When managing guidelines in natural language, contradictions can easily creep in—not because of poor planning, but simply because we're human. We express our intentions in natural language, and sometimes what seems clear to us might have subtle ambiguities. For instance, adding a guideline When user has items in cart, Then lead them to check out with express shipping ASAP" could conflict with an existing guideline, When user is a first-time visitor with items in cart, Then build trust by highlighting our return policy and inviting them to ask questions.. While both guidelines make perfect sense on their own, they create an unclear priority for cart interactions with new customers. This is exactly the kind of nuanced overlap that's hard to spot when writing guidelines, especially as your set grows. This is where Parlant's [evaluations](/docs/concepts/customization/coherence#the-guidline-evaluation-process) come in. It helps catch these inconsistencies before they affect your agent's behavior, and in fact is a prerequisite whenever we add guidelines (though it can be explicitly ignored if you're sure you know what you're doing). To learn how the evaluation system works and how to control its nuances, check out the [Coherence](/docs/concepts/customization/coherence) section. note To learn more about how Parlant helps you ensure that guidelines are coherent and correctly followed in real-time, please refer to the [Coherence](/docs/concepts/customization/coherence) section. ### How Many Guidelines Can You Have?[​](#how-many-guidelines-can-you-have "Direct link to How Many Guidelines Can You Have?") While Parlant can theoretically handle thousands of guidelines, current LLM technology imposes practical constraints. Today's LLMs—still relatively slow, limited, and expensive—mean that more guidelines translate to higher costs, longer response times, and potential accuracy trade-offs. We're constantly improving Parlant as LLM capabilities advance, but working within these limitations is key. Our current recommendation: stay under 200 total guidelines. This might seem modest, but don't underestimate the impact—even 20 thoughtfully designed guidelines can transform agent behavior in practical applications. It's about precision, not volume. note For deeper insights into our strategy and Parlant's design principles, including our industry and technology forecasts, explore our [Design Philosophy](/docs/about#design-philosophy) . ### Formulating Guidelines[​](#formulating-guidelines "Direct link to Formulating Guidelines") Formulating Guidelines ====================== Think of an LLM as a highly knowledgeable stranger who's just walked into your business. They might have years of general experience, but they don't know your specific context, preferences, or way of doing things. Yet, this stranger is eager to help and will always try to respond—even when uncertain. This is where guidelines come in. They're your way of channeling this endless enthusiasm and broad knowledge into focused, appropriate responses. But crafting effective guidelines is a bit of an art—just like with people. #### The Art of Guidance[​](#the-art-of-guidance "Direct link to The Art of Guidance") Consider a customer service scenario. As a very naive example, we might be tempted to write a guideline like: > * **Condition:** Customer is unhappy > * **Action:** Make them feel better While well-intentioned, this is an example of a guideline that is just too vague. The LLM might interpret this in countless ways, from offering discounts it can't actually provide to making jokes that might be inappropriate for your brand. Instead, consider: > * **Condition:** Customer expresses dissatisfaction with our service > * **Action:** Acknowledge their frustration specifically, express sincere empathy, and ask for details about their experience so we can address it properly. Notice how this guideline is both specific and bounded. #### Context is Key[​](#context-is-key "Direct link to Context is Key") Guidelines have two crucial parts: Condition and Action. Think of Condition as the "when" and Action as the "what." Both require attentive crafting: Too broad: > * **Condition:** Customer asks about products > * **Action:** Recommend something they might like > * **Condition:** Customer asks about product recommendations without specifying preferences > * **Action:** Ask about their specific needs, previous experience with similar products, and any particular features they're looking for before making recommendations #### Finding the Right Balance[​](#finding-the-right-balance "Direct link to Finding the Right Balance") In principle, we're looking for guidelines that are "just right"—neither over nor under specified. Consider these iterations for a technical support agent: Too vague: > * **Condition:** Customer has a technical problem > * **Action:** Help them fix it Too rigid: > * **Condition:** Customer reports an error message > * **Action:** First ask for their operating system version, then their browser version, then their last system update date Just right: > * **Condition:** Customer reports difficulty accessing our platform > * **Action:** Express understanding of their situation, ask for key details about their setup (OS and browser), and check if they've tried some concrete troubleshooting steps Remember, the LLM will usually take your guidelines quite literally. If you tell it to "always suggest premium features," it might do so even when talking to a customer who's complaining about pricing. Always consider the broader context and potential edge cases when formulating your guidelines. **If in doubt, err on the side of vagueness.** The goal isn't to script every possible interaction but to provide clear, contextual guidance that shapes the LLM's natural abilities into reliable, appropriate responses for your specific use case. * [Guidelines](#guidelines-1) * [What Are Guidelines](#what-are-guidelines) * [The Structure of Guidelines](#the-structure-of-guidelines) * [How Parlant Uses Guidelines](#how-parlant-uses-guidelines) * [Managing Guidelines](#managing-guidelines) * [Maintaining Coherence](#maintaining-coherence) * [How Many Guidelines Can You Have?](#how-many-guidelines-can-you-have) * [Formulating Guidelines](#formulating-guidelines) --- # Ensuring Coherence | Parlant [Skip to main content](#__docusaurus_skipToContent_fallback) On this page Ensuring Coherence[​](#ensuring-coherence-1 "Direct link to Ensuring Coherence") --------------------------------------------------------------------------------- Parlant helps you ensure that your [guidelines](/docs/concepts/customization/guidelines) work together cleanly and are followed reliably. Let's dive into how it validates guideline consistency and provides visibility into your agent's decision-making process. note To learn about protecting agents from inappropriate or otherwise problematic user inputs, check out the section on [Guardrails & Moderation](/docs/guides/guardrails) . In this section, you'll learn: 1. What guideline coherence means and why it matters 2. Where and how coherence checks happen 3. How _Conformal Guidance_ makes guidelines more reliable 4. How to use coherence artifacts to troubleshoot and improve behavior ### Understanding Coherence[​](#understanding-coherence "Direct link to Understanding Coherence") Coherence in Parlant works at two key points in the system, each serving a distinct purpose. #### Guideline Management[​](#guideline-management "Direct link to Guideline Management") First, at the guideline management level, Parlant prevents conflicting or contradictory guidelines from being added to your system—think of it like dependency resolution in package management, where you wouldn't want conflicting package versions or incompatible dependencies breaking your system. When you add new guidelines, Parlant automatically checks them against your existing set to catch potential conflicts early. This early detection is important because conflicting guidelines can lead to unpredictable agent behavior—which, incidentally, can also be hard to understand and troubleshoot. In other words, instead of discovering conflicts through unexpected responses in live conversations, Parlant lets you catch and address many of them during the design phase—ensuring your agent's behavior aligns more closely with your intentions. #### Message Generation[​](#message-generation "Direct link to Message Generation") Second, during message generation, Parlant ensures guidelines are followed consistently in real-time conversations through our Conformal Guidance technique. Rather than simply adding guidelines to prompts and hoping for the best, Parlant employes techniques such as echoing and self-critique to ensure the LLM actually follows the guidelines. This approach (research paper on the way) leads to more consistent and natural responses while maximizing guideline adherence. Together, these coherence mechanisms create a system that's both well-defined and reliably executed. ### The Guidline Evaluation Process[​](#the-guidline-evaluation-process "Direct link to The Guidline Evaluation Process") To ensure your agent stays consistent, Parlant requires you to go through an evaluation step before adding any new guidelines to your agent. Think of it like a code review, but for your agent's behavioral instructions. This process protects your agent's internal consistency and helps maintain a coherent worldview. When Parlant identifies potential conflicts, it provides specific feedback about the nature of the contradiction. This allows you to either: 1. Modify your new guidelines to align with existing ones 2. Update existing guidelines to accommodate your new requirements 3. Refine both to create a coherent set of instructions This approach ensures your agent maintains consistent, predictable behavior as your set of guidelines grows and evolves. ### Evaluation Types[​](#evaluation-types "Direct link to Evaluation Types") Currently, two types of guideline evaluations are supported in Parlant: 1. **Coherence Checks** 2. **Connection Propositions**. When creating evaluations, you can control what checks, if any, should be performed. * Python * TypeScript from parlant.client import ( GuidelineContent, GuidelinePayload, ParlantClient, Payload,)client = ParlantClient(base_url=SERVER_ADDRESS)# Start evaluating the guideline's impactevaluation = client.evaluations.create( agent_id=AGENT_ID, payloads=[ Payload( kind="guideline", guideline=GuidelinePayload( content=GuidelineContent( condition=CONDITION, action=ACTION, ), operation="add", coherence_check=CHECK_COHERENCE, connection_proposition=PROPOSE_CONNECTIONS, ) ) ],) import { ParlantClient } from 'parlant-client';const client = new ParlantClient({ environment: SERVER_ADDRESS });// Start evaluating the guideline's impactconst evaluation = await client.evaluations.create({ agentId: AGENT_ID, payloads: [{ kind: "guideline", guideline: { content: { condition: CONDITION, action: ACTION, }, operation: "add", coherenceCheck: CHECK_COHERENCE, connectionProposition: PROPOSE_CONNECTIONS, }}] }); #### Coherence Check[​](#coherence-check "Direct link to Coherence Check") This is to ensure that agents aren't confused by self-contradicting guidelines. Here, there may be very obvious contradictions, such as: > When X, Then Y and When X, Then not(Y). But there may also be subtler ones (which Parlant also helps you catch), such as: > When X, Then Y and When A, then not(B) such that _A_ is a sub-case of _X_, and _B_ is a sub-case of _Y_. For example: > When the customer has items in the cart, Then quickly lead them to express checkout and: > When the customer has an item in the cart that costs more than $300, Then engage them in discussion on its unique qualities #### Connection Proposition[​](#connection-proposition "Direct link to Connection Proposition") To understand connection proposition, we first need to understand how Parlant chooses which guidelines activate for an agent when it's about to say something to the customer. Basically, Parlant examines the session at its current state, and asks questions about it: "Is this guideline relevant now?", "Is that guideline relevant now?". To do this, it primarily tests the guidelines' _conditions_. This would have worked perfectly by itself, until we considered having two guidelines following the form: > When X, Then Y and When Y, Then Z Now imagine a situation where, by looking at a session, we infer that _X_ does in fact apply, but not _Y_. With the naive logic above, Parlant would have only fed the agent with the guideline to do _Y_. But when we step back and analyze this case, we know that the agent is just about to do _Y_, which means that, according to the guidelines we have installed, _Z_ should also apply. To overcome this challenge, Parlant semantically evaluates causal connections between the guideline you're about to add and the agent's existing guidelines, and indexes them behind the scenes in the form of a graph—a graph of causal connections. ### Explaining and Troubleshooting Agent Behavior[​](#explaining-and-troubleshooting-agent-behavior "Direct link to Explaining and Troubleshooting Agent Behavior") Message generation in Parlant goes through quite a lot of quality checks. These checks produce artifacts that can help explain how the agent interpreted elements such as guidelines, glossary terms, and tools. When you run into issues, you can inspect these artifacts to better understand why the agent responded the way it did, and whether it correctly interpreted your intentions. * CLI * Python * TypeScript $ parlant session inspect \ --session-id SESSION_ID \ --event-id EVENT_ID from parlant.client import ParlantClientclient = ParlantClient(base_url=SERVER_ADDRESS)agent_message_trace = client.sessions.inspect_event( SESSION_ID, EVENT_ID,).trace import { ParlantClient } from 'parlant-client';const client = ParlantClient({ environment: SERVER_ADDRESS });const { trace } = await client.sessions.inspectEvent( SESSION_ID, EVENT_ID,); Over time, this feedback loop helps you build more precise and effective sets of guidelines. * [Ensuring Coherence](#ensuring-coherence-1) * [Understanding Coherence](#understanding-coherence) * [The Guidline Evaluation Process](#the-guidline-evaluation-process) * [Evaluation Types](#evaluation-types) * [Explaining and Troubleshooting Agent Behavior](#explaining-and-troubleshooting-agent-behavior) --- # Sessions | Parlant [Skip to main content](#__docusaurus_skipToContent_fallback) On this page Sessions[​](#sessions-1 "Direct link to Sessions") --------------------------------------------------- A session represents a continuous interaction between an [agent](/docs/concepts/entities/agents) and a [customer](/docs/concepts/entities/customers) . When we want to start a new interaction between a customer and an agent, we create a new session for that. Each customer can have as many different sessions with an agent as is desired, and different agents can interact with the same customers—albeit in different sessions. ### Session Storage[​](#session-storage "Direct link to Session Storage") Sessions are stored in a database, and you can have as many of them as you'd like. It all depends on your storage capacity—but keep in mind that storing sessions for an extended period of time can be a good way to gather data for later analysis and improvement of the conversation experience. ### Session Observability[​](#session-observability "Direct link to Session Observability") In addition to the conversational details themselves, a session also stores information pertaining to the generative process of the agent's responses: 1. An explanation of how the agent interpreted each stage of the conversation 2. The [guidelines](/docs/concepts/customization/guidelines) that were activated for each agent response 3. The time it took for the agent to respond 4. The breakdown of generative models and tokens used for each response This additional information serves to make it as simple as possible to understand and optimize an agent's behavior. tip By default, an agent's memory about a particular customer is confined to a session. However, we can implement _persistent memory_ for customers using [context variables](/docs/concepts/customization/context-variables) . ### Session Events[​](#session-events "Direct link to Session Events") Think of a session in Parlant as a timeline of everything that happens in a conversation. Each moment in this timeline—whether it's someone speaking, the agent thinking, or a system update—is captured as an event. These events line up one after another, each with its own position number (called its _offset_), starting from 0. From a simplistic perspective, when a conversation unfolds, it creates a sequence of these events. A user might start the session by saying _"Hello"_—that's event 0. The system then notes that the agent is preparing a response by outputting a status event—that's event 1. The agent's _"Hi there!"_ becomes event 2, and so on. Each event, whether it's a message being exchanged, the agent typing, or even an error occurring, takes its place in this ordered sequence. Every event in this sequence carries important information: what type of event it is (like a message or a status update), what actually happened (the data), and when it occurred. This creates a complete record of the conversation that helps us understand exactly how things unfolded, making it easier to track the conversation's state, handle any issues that arise, or review the interaction later. Each event is also associated with a **correlation ID**. This ID primarily helps to correlate between AI-generated messages and the tool events that fed data into them. This lets us easily fetch and display the data that went into generated messages. A common use case for this is to show "sources" or "footnotes" under agent messages in our frontend. ### Event-Driven Communication[​](#event-driven-communication "Direct link to Event-Driven Communication") Unlike traditional LLM APIs where you send a prompt and wait for a direct response, Parlant agents operate more like real conversation partners. Much like a human service representative, they process information and decide when and how to respond based on their understanding of the context. This means we need to approach communication with them differently. Instead of the familiar request-response pattern of completion APIs, Parlant uses an event-driven model. When you send a message to an agent, you're really adding an event to their conversation stream. The agent then processes this independently, potentially generating multiple events in response—they might acknowledge receipt, indicate they're thinking, ask for clarification, or provide a full response. This more natural conversation flow requires us to listen for events—ideally in asynchronous fashion—rather than waiting for an immediate response. Here's a simple, synchronous example of how this looks in practice: * Python * TypeScript from parlant.client import ParlantClientclient = ParlantClient(base_url=SERVER_ADDRESS)# Post customer messagecustomer_message_event = client.sessions.create_event( session_id=SESSION_ID, kind="message", source="customer", message=MESSAGE,)# Wait for and get the agent's replyagent_message_event = client.sessions.list_events( session_id=SESSION_ID, kinds="message", source="ai_agent", min_offset=customer_message_event.offset, wait_for_data=60, # wait for up to 60 seconds for an answer)[0]# Print the agent's replyprint(agent_message_event.data)# Inspect the details of the message generation processagent_message_trace = client.sessions.inspect_event( SESSION_ID, agent_message_event.id,).trace import { ParlantClient } from 'parlant-client';const client = new ParlantClient({ environment: SERVER_ADDRESS });// Post customer messageconst customerMessageEvent = await client.sessions.createEvent(SESSION_ID, { kind: "message", source: "customer", message: MESSAGE,});// Wait for and get the agent's replyconst [agentMessageEvent] = (await client.sessions.listEvents(SESSION_ID, { kinds: "message", source: "ai_agent", minOffset: customerMessageEvent.offset, waitForData: 60 // wait for up to 60 seconds for an answer}));// Print the agent's replyconst { message } = agentMessageEvent.data as { message: string };console.log(message);// Inspect the details of the message generation processconst { trace } = await client.sessions.inspectEvent( SESSION_ID, agentMessageEvent.id); ### Event Kinds[​](#event-kinds "Direct link to Event Kinds") There are two kinds of events you really need to know: `message` and `status`. #### Message Event[​](#message-event "Direct link to Message Event") A message event, as its name suggests, represents a message written by someone. There are several possible sources for a message within Parlant: 1. `"customer"`: The message came from a customer (using some frontend application) 2. `"ai_agent"`: The message was auto-generated by an AI agent 3. `"human_agent"`: The message came from a human agent who took over the session 4. `"human_agent_on_behalf_of_ai_agent"`: The message came from a human message, but for all intents and purposes (both within Parlant and to the customer) appears to have come from an AI agent Message Event Structure { id: EVENT_ID, kind: "message", source: EVENT_SOURCE, offset: N, correlation_id: CORRELATION_ID, data: { message: MESSAGE, participant={ id: PARTICIPANT_ID, display_name: PARTICIPANT_DISPLAY_NAME } }} #### Status Event[​](#status-event "Direct link to Status Event") A status event represents an update on the status of the AI agent, and currently always has the source `"ai_agent"`. Status events are great for displaying conversational updates during a chat with a customer. For example, you can have your frontend indicate when the agent is thinking or typing. There are 6 kinds of status events that you can make use of: 1. `"acknowledged"`: The agent has acknowledged the customer's message and started working on a reply 2. `"cancelled"`: The agent has cancelled its reply in the middle, normally because new data was added to the session 3. `"processing"`: The agent is evaluating the session in preparation for generating an appropriate reply 4. `"typing"`: The agent has finished evaluating the session and is currently generating a message 5. `"ready"`: The agent is idle and ready to receive new events 6. `"error"`: The agent encountered an error while trying to generate a reply Status Event Structure { id: EVENT_ID, kind: "status", source: "ai_agent", offset: N, correlation_id: CORRELATION_ID, data: { status: STATUS_KIND, data: OPTIONAL_DATA }} API Highlights[​](#api-highlights "Direct link to API Highlights") ------------------------------------------------------------------- ### Creating a new session[​](#creating-a-new-session "Direct link to Creating a new session") * CLI * Python * TypeScript $ parlant session create \ --agent-id AGENT_ID \ --customer-id CUSTOMER_ID \ --title TITLE from parlant.client import ParlantClientclient = ParlantClient(base_url=SERVER_ADDRESS)session = client.sessions.create( agent_id=AGENT_ID, customer_id=CUSTOMER_ID, # Optional: defaults to the guest customer's ID title=SESSION_TITLE, # Optional: session can be untitled allow_greeting=False, # Optional: allow the agent to actively start the chat) import { ParlantClient } from 'parlant-client';const client = new ParlantClient({ environment: SERVER_ADDRESS });const session = await client.sessions.create({ agentId: AGENT_ID, customerId: CUSTOMER_ID, // Optional: defaults to the guest customer's ID title: SESSION_TITLE, // Optional: session can be untitled allowGreeting: false, // Optional: allow the agent to actively start the chat}); ### Listing status events[​](#listing-status-events "Direct link to Listing status events") * CLI * Python * TypeScript $ parlant session view \ --id SESSION_ID \ from parlant.client import ParlantClientclient = ParlantClient(base_url=SERVER_ADDRESS)status_events = client.sessions.list_events( session_id=SESSION_ID, min_offset=MIN_OFFSET, kinds="status",) import { ParlantClient } from 'parlant-client';const client = new ParlantClient({ environment: SERVER_ADDRESS });const statusEvents = await client.sessions.list_events(SESSION_ID, { minOffset: MIN_OFFSET, kinds: "status",}); ### Listing sessions[​](#listing-sessions "Direct link to Listing sessions") * CLI * Python * TypeScript $ parlant session list \ --agent-id AGENT_ID \ --customer-id CUSTOMER_ID from parlant.client import ParlantClientclient = ParlantClient(base_url=SERVER_ADDRESS)sessions = client.sessions.list( agent_id=AGENT_ID, # Optional: filter by agent ID customer_id=CUSTOMER_ID, # Optional: filter by agent ID) import { ParlantClient } from 'parlant-client';const client = new ParlantClient({ environment: SERVER_ADDRESS });const sessions = await client.sessions.list({ agentId: AGENT_ID, // Optional: filter by agent ID customerId: CUSTOMER_ID, // Optional: filter by customer ID}); * [Sessions](#sessions-1) * [Session Storage](#session-storage) * [Session Observability](#session-observability) * [Session Events](#session-events) * [Event-Driven Communication](#event-driven-communication) * [Event Kinds](#event-kinds) * [API Highlights](#api-highlights) * [Creating a new session](#creating-a-new-session) * [Listing status events](#listing-status-events) * [Listing sessions](#listing-sessions) --- # Glossary | Parlant [Skip to main content](#__docusaurus_skipToContent_fallback) On this page Glossary[​](#glossary-1 "Direct link to Glossary") --------------------------------------------------- The glossary is a fundamental part of shaping your agent's understanding of its domain. Think of it as your agent's dictionary—a collection of terms specific to your business or service context. ### When to Use the Glossary[​](#when-to-use-the-glossary "Direct link to When to Use the Glossary") When you create an agent to handle specific tasks, it needs to understand the unique vocabulary of your domain. For example, if your agent helps guests book rooms at the Boogie Nights hotel, it needs to know what "Boogie Nights" means in your context—it's not just a movie title, but your hotel's name. ### Structure of Terms[​](#structure-of-terms "Direct link to Structure of Terms") Each glossary entry consists of three components: > * **Term:** The word or phrase being defined > * **Definition:** What this term means in your specific context > * **Synonyms:** Alternative ways users might refer to this term For example, > * **Term:** Boogie Nights > * **Definition:** Our luxury beachfront hotel located in Miami > * **Synonyms:** BN Hotel, The Boogie, Boogie Hotel ### How Agents Use the Glossary[​](#how-agents-use-the-glossary "Direct link to How Agents Use the Glossary") The glossary serves two crucial purposes in agent interactions. First, it helps your agent understand users better. When a guest says "I'd like to stay at The Boogie," the agent knows they're referring to your hotel. Second, it helps the agent interpret your guidelines correctly. Consider this guideline: > * **Condition:** The user asks about Ocean View rooms > * **Action:** Explain the Sunrise Package benefits For this to work effectively, your glossary might include: > * **Term:** Ocean View > * **Definition:** Our premium rooms on floors 15-20 facing the Atlantic > * **Synonyms:** seaside rooms, beach view > * **Term:** Sunrise Package > * **Definition:** Complimentary breakfast and early check-in for Ocean View bookings > * **Synonyms:** morning special, sunrise special Here's how to create a new glossary term: * CLI * Python * TypeScript $ parlant glossary create \ --agent-id AGENT_ID \ --name TERM_NAME \ --description TERM_DESCRIPTION \ --synonyms COMMA_SEPARATED_LSIT # Optional from parlant.client import ParlantClientclient = ParlantClient(base_url=SERVER_ADDRESS)term = client.glossary.create_term( agent_id=AGENT_ID, name=TERM_NAME, description=TERM_DESCRIPTION, synonyms=[...], # Optional) import { ParlantClient } from 'parlant-client';const client = new ParlantClient({ environment: SERVER_ADDRESS });const term = await client.glossary.createTerm(AGENT_ID, { name: TERM_NAME, description: TERM_DESCRIPTION, synonyms: [...], // Optional}); ### Glossary vs Guidelines vs Agent Description[​](#glossary-vs-guidelines-vs-agent-description "Direct link to Glossary vs Guidelines vs Agent Description") Each component serves a distinct purpose in shaping your agent's behavior: 1. The Glossary teaches your agent "what things are". For example, _"A Club Member is a guest who has stayed with us more than 5 times"_ 2. Guidelines teach your agent "how to act in situations". For example, _"When speaking with Club Members, acknowledge their loyalty status"_ 3. Agent Description provides overall context and personality. For example, _"You are a helpful hotel booking assistant for Boogie Nights"_ Think of it this way: the glossary builds your agent's vocabulary, guidelines shape its behavior, and the agent description sets its overall context and tone. ### Glossary vs Tools[​](#glossary-vs-tools "Direct link to Glossary vs Tools") While both glossary terms and tools help your agent understand your domain, they serve fundamentally different purposes. The glossary provides static knowledge, while tools enable dynamic data access. Consider a hotel booking scenario: **Glossary Term:** > * **Term:** Club Member > * **Definition:** A guest who has stayed with us more than 5 times > * **Synonyms:** loyal guest, regular guest **Tool:** `check_member_status(user_id) # Returns current stay count and benefits` The glossary term provides a consistent definition of what a Club Member is, while the tool can check a specific user's actual status in your database. Similarly: **Glossary Term:** > * **Term:** Ocean View Room > * **Definition:** Premium rooms on floors 15-20 facing the Atlantic > * **Synonyms:** seaside room, beach view **Tool:** `check_room_availability(room_type, dates) # Returns current availability and rates` The glossary helps your agent understand what an Ocean View Room is, while the tool provides real-time information about specific rooms' availability and pricing. This separation between static knowledge (glossary) and dynamic data access (tools) helps create clear, maintainable agent implementations that can handle both general inquiries and specific, data-driven interactions. * [Glossary](#glossary-1) * [When to Use the Glossary](#when-to-use-the-glossary) * [Structure of Terms](#structure-of-terms) * [How Agents Use the Glossary](#how-agents-use-the-glossary) * [Glossary vs Guidelines vs Agent Description](#glossary-vs-guidelines-vs-agent-description) * [Glossary vs Tools](#glossary-vs-tools) --- # Context Variables | Parlant [Skip to main content](#__docusaurus_skipToContent_fallback) On this page Context Variables[​](#context-variables-1 "Direct link to Context Variables") ------------------------------------------------------------------------------ Every customer is unique, and your agent should treat them accordingly where appropriate. Context variables enrich the context that the agent sees about the customer it's talking to. They are meant to give your agent awareness to information that helps it personalize its service, much like how a seasoned customer service representative knows and remembers important details about each client. When a customer interacts with your agent, their context variables are automatically loaded, allowing the agent to tailor its responses based on their specific situation. ### Real World Applications[​](#real-world-applications "Direct link to Real World Applications") Let's walk through how context variables transform customer interactions. Imagine you're running a SaaS platform's support agent. You might track variables like subscription plan, last login date, which features each customer uses, and their company size. Consider two different customers reaching out about data exports. Sarah, a startup founder on the free plan, asks "Can I export my data to Excel?" Your agent, aware of her free plan status, can respond thoughtfully: "While Excel export is a premium feature, I can show you how to use our basic CSV export. Would you also like to learn about the advanced reporting capabilities in our premium plan?" Now imagine Tom from an enterprise account reaches out with the same question. The agent sees his enterprise status but also notices his team hasn't explored many advanced features. It might respond: "I'll help you with Excel exports! I notice your team hasn't tried our automated reporting suite yet - this is included in your enterprise plan and could save you hours each week. Would you like me to show you both features?" ### Working with Context Variables[​](#working-with-context-variables "Direct link to Working with Context Variables") A single context variable identifies a particular piece of information. For example, you might create a variable called `"subscription_plan"`. Each customer can then have a unique value assigned to them, under that context variable. For example, Tom might have `"enterprise"` as the variable's value. Here's how to create a new context variable and assign a value to a customer: * CLI * Python * TypeScript $ parlant variable create \ --agent-id AGENT_ID \ --name VARIABLE_NAME \ --description VARIABLE_DESCRIPTION # Optional$ parlant variable set \ --agent-id AGENT_ID \ --id VARIABLE_ID \ --key CUSTOMER_ID \ --value VARIABLE_VALUE from parlant.client import ParlantClientclient = ParlantClient(base_url=SERVER_ADDRESS)variable = client.context_variables.create( agent_id=AGENT_ID, name=VARIABLE_NAME, description=VARIABLE_DESCRIPTION,)client.context_variables.set_value( agent_id=AGENT_ID, variable_id=variable.id, key=CUSTOMER_ID, data=VARIABLE_VALUE,) import { ParlantClient } from 'parlant-client';const client = new ParlantClient({ environment: SERVER_ADDRESS });const variable = await client.contextVariables.create(AGENT_ID, { name: VARIABLE_NAME, description: VARIABLE_DESCRIPTION,});await client.contextVariables.setValue(AGENT_ID, variable.id, CUSTOMER_ID, { data: VARIABLE_VALUE,}); Alternatively, you can also create [tags](/docs/concepts/entities/customers#tags) for customers—say, to assign them to groups—and then to configure variable values for tags (customer groups) instead of individual customers. * CLI * Python * TypeScript $ parlant variable create \ --agent-id AGENT_ID \ --name VARIABLE_NAME \ --description VARIABLE_DESCRIPTION # Optional$ parlant variable set \ --agent-id AGENT_ID \ --id VARIABLE_ID \ --key CUSTOMER_ID \ --value VARIABLE_VALUE from parlant.client import ParlantClientclient = ParlantClient(base_url=SERVER_ADDRESS)variable = client.context_variables.create( agent_id=AGENT_ID, name=VARIABLE_NAME, description=VARIABLE_DESCRIPTION,)client.context_variables.set_value( agent_id=AGENT_ID, variable_id=variable.id, key=CUSTOMER_ID, data=VARIABLE_VALUE,) import { ParlantClient } from 'parlant-client';const client = new ParlantClient({ environment: SERVER_ADDRESS });const variable = await client.contextVariables.create(AGENT_ID, { name: VARIABLE_NAME, description: VARIABLE_DESCRIPTION,});await client.contextVariables.setValue(AGENT_ID, variable.id, CUSTOMER_ID, { data: VARIABLE_VALUE,}); ### Combining Context Variables with Guidelines[​](#combining-context-variables-with-guidelines "Direct link to Combining Context Variables with Guidelines") Let's explore how guidelines and context variables work together to create truly intelligent interactions. Imagine you're running an AI support agent for a digital bank where customers have different account tiers and transaction patterns. Here's a focused guideline: > * **Condition:** customer's account tier is 'basic' AND they ask about instant international transfers > * **Action:** Highlight our same-day domestic transfers that are free on their plan, then mention how premium enables instant global payments When Mark asks about sending money to his daughter studying abroad, instead of a flat "that's premium only" response, he hears: "I can help you send that money today using our standard international transfer. By the way, our premium accounts get this done instantly with lower fees—would you like to know more?" For high-value customers who haven't explored wealth management: > * **Condition:** customer's balance is at least 100k AND they aren't using our investment products > * **Action:** After you're done helping them with their inquiry, mention our personalized investment advisory service So when Jessica checks her substantial balance, the agent notes: "I see you've built up some significant savings. Did you know our wealth management team can help create a personalized investment strategy for you?" * [Context Variables](#context-variables-1) * [Real World Applications](#real-world-applications) * [Working with Context Variables](#working-with-context-variables) * [Combining Context Variables with Guidelines](#combining-context-variables-with-guidelines) --- # Tools & APIs | Parlant [Skip to main content](#__docusaurus_skipToContent_fallback) On this page Tools & APIs in Parlant[​](#tools--apis-in-parlant "Direct link to Tools & APIs in Parlant") --------------------------------------------------------------------------------------------- Parlant provides a principled approach to tool usage, tightly integrated with the guideline system. The tool-calling implementation is built from the ground up for two main reasons: both to provide a stable abstraction layer across different LLM versions and providers, and to enable seamless integration with guideline-based behavior control. In addition, tools are run in sandboxed mode—in a different process—to protect the Parlant server from crashing or malfunctioning because of logic or security issues in tool code. ### Getting Started with Tool Services[​](#getting-started-with-tool-services "Direct link to Getting Started with Tool Services") The best way to get started is to clone the [tool service starter repo](https://github.com/emcie-co/parlant-tool-service-starter) : $ git clone https://github.com/emcie-co/parlant-tool-service-starter Inside the starter repo, run the following commands to install and run the tool service: $ poetry install$ poetry run python parlant_tool_service_starter/service.py Now head over to [http://localhost:8089/docs](http://localhost:8089/docs) and try out the `Call Tool` endpoint, providing the following arguments: > * **name:** get\_random\_number > * **body:** > > { "agent_id": "string", "session_id": "string", "arguments": {}} You should see a new random number appearing in the tool result every time you run call it. #### Reviewing the Tool Service's Code[​](#reviewing-the-tool-services-code "Direct link to Reviewing the Tool Service's Code") Here's what you'll find under `parlant_tool_service_starter/service.py`: import asynciofrom random import randomfrom parlant.sdk import ( PluginServer, ToolContext, ToolResult, tool,)PORT = 8089@toolasync def get_random_number(context: ToolContext) -> ToolResult: return ToolResult(data=int(random() * 1000))TOOLS = [ get_random_number,]async def main() -> None: async with PluginServer(tools=TOOLS, port=PORT): passif __name__ == "__main__": asyncio.run(main()) There are two important parts to this code snippet. 1. The `main` function, which starts something called a `PluginServer`. A plugin server, as its name suggests, is a part of Parlant's SDK which lets you plug into your Parlant server. In this case, we use it to expose tools, which means it can function as a tool service for agents to use. 2. The `@tool` function definition. Let's dive into that a bit more in depth for just a minute. #### Tool Functions[​](#tool-functions "Direct link to Tool Functions") 1. **Function name:** Here the function is defined as `async def get_random_number`. The function can be named however you want, but it's recommended to prioritize readability when choosing a name, since Parlant agents will try to understand what it does based on its name. 2. **Sync/Async:** Here the function is defined as `async` which allows you to run other `async` functions without blocking the execution. However, it's optional, so feel free to remove the `async` keyword if you don't need it. 3. `ToolContext`: This gives you access to the agent, session, and customer ID for the current execution context. You can use this, for example, to fetch data based on the specific customer you're interacting with. 4. In addition, `ToolContext` allows you to emit intermediate messages. This is useful if your tool takes a long time to run, and you want the agent to say something like, "Just a second, I'm checking something." You can emit tools and status updates at any point throughout your tool call execution. 5. `ToolResult`: Here you can return both the actual `data` that the agent sees and takes into consideration when replying, as well as `metadata` which can be inspected on the client side. `metadata` is great for when you want to provide additional information on the `data` returned; for example, listing the sources from which some answer was generated, to display as footnotes on the frontend. We will release a guide on this soon! #### Registring the Service with Parlant[​](#registring-the-service-with-parlant "Direct link to Registring the Service with Parlant") The next step is to give Parlant agents access to your server. Assuming you already have a `parlant-server` running, go ahead and run the following command in your shell: $ parlant service create \ --name my-service --kind sdk \ --url http://localhost:8089 ### Understanding Tool Usage[​](#understanding-tool-usage "Direct link to Understanding Tool Usage") In Parlant, tools are always associated with specific guidelines. This means a tool only executes when its associated guideline becomes relevant to the conversation. This design creates a clear chain of intent: guidelines determine when and why tools are used, rather than leaving it to the LLM's judgment. In addition, **business logic** (encoded in tools) can be separated and worked on independently from **presentation** (or user-interface) concerns, which are the behavior that's controlled by the guidelines themselves. This allows you to have developers work out the logic in code, with full control—offering these tools in the "tool shed" of Parlant—for business experts to then go and utilize in their guidelines. As an analogy, you can think of Guidelines and Tools like Widgets and Event Handlers in Graphical UI frameworks. A GUI Button has an `onClick` handler which we can associate with some API function to say, _"When this button is clicked, run this function."._ In the same way, in Parlant—which is essentally a Conversational UI framework—the Guideline is like the Button, the Tool is like the API function, and the association connects the two to say, _"When this guideline is applied, run this tool."_ Here's a concrete example to illustrate these concepts: > * **Condition:** The user asks about service features > * **Action:** Understand their intent and consult documentation to answer > * **Tools Associations:** `[query_docs(user_query)]` Here, the documentation query tool only runs after the guideline instructs that we should be consulting documentation for this user interaction. #### Associating Between a Guideline and a Tool[​](#associating-between-a-guideline-and-a-tool "Direct link to Associating Between a Guideline and a Tool") To allow a guideline to run a tool, here's what you do: * CLI * Python * TypeScript $ parlant guideline tool-enable \ --agent-id AGENT_ID \ --id GUIDELINE_ID \ --service SERVICE_NAME \ --tool TOOL_NAME from parlant.client import ParlantClient, GuidelineToolAssociationUpdateParams, ToolIdclient = ParlantClient(base_url=SERVER_ADDRESS)client.guidelines.update( agent_id=AGENT_ID, guideline_id=GUIDELINE_ID, tool_associations=GuidelineToolAssociationUpdateParams( add=[ ToolId( service_name=SERVICE_NAME, tool_name=TOOL_NAME, ), ], ),) import { ParlantClient } from 'parlant-client';const client = new ParlantClient({ environment: SERVER_ADDRESS });await client.guidelines.update(AGENT_ID, GUIDELINE_ID, { toolAssociations: { add: [{ serviceName: SERVICE_NAME, toolName: TOOL_NAME }] },}); ### Dynamic Behavior with Tool Outputs[​](#dynamic-behavior-with-tool-outputs "Direct link to Dynamic Behavior with Tool Outputs") Tool outputs can influence which guidelines become relevant, creating dynamic, data-driven behavior that remains under guideline control. Here's how this works in practice: Consider a banking agent handling transfers. When a user requests a transfer, a guideline with the condition the user wants to make a transfer activates the `get_user_account_balance()` tool to check available funds. This tool returns the current balance, which can then trigger additional guidelines based on its value. For instance, if the balance is below $500, we could have a low-balance guideline activate, instructing the agent to say something like: _"I see your balance is getting low. Are you sure you want to proceed with this transfer? This transaction might put you at risk of overdraft fees."_ This interplay between tools and guidelines ensures that every tool execution has clear context and intent, while tool outputs can trigger precisely defined behavioral responses—all within the guideline framework. ### Best Practices[​](#best-practices "Direct link to Best Practices") #### A Note on Natural Language Programming[​](#a-note-on-natural-language-programming "Direct link to A Note on Natural Language Programming") While LLMs excel at conversational tasks, they struggle with complex logical operations and multi-step planning. Recent research in LLM architectures shows that even advanced models have difficulty with consistent logical reasoning and sequential decision-making. The "planning problem" in LLMs—breaking down complex tasks into ordered steps—remains a significant challenge, as highlighted in papers exploring [Chain-of-Thought and related techniques](https://arxiv.org/abs/2410.14198) . Given these limitations, Parlant takes a pragmatic approach: keep logic in code, conversation in guidelines. Instead of embedding business logic in natural language guidelines, Parlant encourages a clean separation between conversational behavior and underlying business operations. Consider your tools as your business logic API, and guidelines as your conversational interface. This separation creates cleaner, more maintainable, and more reliable systems. #### Examples[​](#examples "Direct link to Examples") **1\. E-commerce Product Recommendations:** DON'T > * **Guideline Action:** If user mentions sports, check their purchase history. If they bought running gear, recommend premium shoes. If they're new, suggest starter kit. > * **Tool Associations:** `[get_product_catalog()]` This puts complex business logic in the guideline, relying on the LLM to handle multiple conditions consistently. Instead: DO > * **Guideline Action:** Offer personalized recommendations > * **Tool Associations:** `[get_personalized_recommendations(user_context)]` Keep the logic in your recommendation engine, where it belongs. **2\. Financial Advisory:** DON'T > * **Guideline Action:** Check account balance and recent transactions. If spending exceeds 80% of usual pattern, suggest budget review. If investment returns are down, recommend portfolio adjustment. > * **Tool Associations:** `[get_account_data()]` Financial analysis logic shouldn't rely on LLM interpretation. DO > * **Guideline Action:** Get personalized financial insights > * **Tool Associations:** `[get_financial_insights(account_id)]` * [Tools & APIs in Parlant](#tools--apis-in-parlant) * [Getting Started with Tool Services](#getting-started-with-tool-services) * [Understanding Tool Usage](#understanding-tool-usage) * [Dynamic Behavior with Tool Outputs](#dynamic-behavior-with-tool-outputs) * [Best Practices](#best-practices) ---