Customer personalization
Different customers, different behavior
Your business already knows things about its customers: what they bought, which services they can use, and how their account is set up. Customer groups let your agent use those facts. You put customers in groups, and you tie policies and tools to each group, so that two customers who ask the same question get the handling that fits their account. This playbook builds an account-support agent that helps individual and company-managed customers sign in again, each in the right way.
- Two customers with the same question and different right answers
- How to create customer groups and assign customers to them
- How an observation judged by code anchors each group
- How policies and tools depend on that observation
Let's build an account-support agent for a SaaS product used by individuals and companies. Two customers ask, "I can't sign in. Can you help?" One needs a product password reset. The other uses a company-managed login, so a product password reset is not an option for them.
We use customer groups to represent these different login setups, then connect each group to the policies and tools for its recovery process.
Example: individual and company-managed logins
Consider two customers. Dana manages her own product password, while Sam works at Acme and uses single sign-on (his company controls his login). Their records determine which help the agent offers.
This is the behavior we want from our support agent:
| Dana | Sam | |
|---|---|---|
| Use case | Registered email and password login | Company sign-in instructions and IT support team |
| First step | Offer a password-reset email | Explain how to use company sign-in |
| Action | Send the reset email | Create an IT access ticket if company sign-in failed |
| Result | Email confirmation and instructions to reset the password | Ticket reference and an explanation of who will follow up |
Handling groups of customers
Dana and Sam are specific instances of broader groups of customers, say, private and business ones.
Parlant lets you set special behavior for specific customers. But it is usually more effective to define behavior for customer groups, and assign each customer to the right group.
Let's set it up. Add this setup inside your async with p.Server() as server: block. create_customer takes the Group objects themselves, not their ids:
private_users = await server.create_group(name="Private Users")
business_users = await server.create_group(name="Business Users")
# Make sure to assign the relevant customers groups as needed
dana = await server.create_customer(id="u1", name="Dana", groups=[private_users])
sam = await server.create_customer(id="u2", name="Sam", groups=[business_users])
Later, you can look a group up with await server.get_group(name="Business Users") (or by id), and move a customer with await sam.groups.add(business_users) or await sam.groups.remove(private_users). customer.groups also supports len, iteration, and in checks for reading a customer's current memberships.
To connect your own customer database, you can provide a customer store instead of creating duplicate records.
Apply different policies to different customer groups
Now that we have set up our customers and customer groups, it is time to set different handling for each group.
We create an observation with a code matcher that triggers every time the customer is in a specific group. This serves as an anchor, to which we tie the handling policies for each customer group.
talking_to_a_private_user = await agent.create_observation(
condition="The customer is a private user",
evaluation_func=private_users.includes_current_customer,
)
talking_to_a_business_user = await agent.create_observation(
condition="The customer is a business user",
evaluation_func=business_users.includes_current_customer,
)
Group.includes_current_customer is a built-in contextual evaluation function that checks if the conversation's current customer belongs to the group. It triggers on each turn in every conversation whose current customer is a member.
There is also the inverse method, Group.excludes_current_customer, which triggers when the current customer is not a member.
With our anchoring observations in place, we can add the different handling policies. They depend on the right context being established by the observations, and that check is made by code, not by the model.
await agent.create_policy(
title="Help with an individual login",
content=(
"When the customer cannot sign in, offer to send a password-reset email "
"to their registered address. If they agree, call `send_password_reset`."
),
dependencies=[talking_to_a_private_user],
tools=[send_password_reset],
)
await agent.create_policy(
title="Help with a company-managed login",
content=(
"When the customer cannot sign in, explain that their company manages "
"their login. Ask them to choose Company sign-in and enter their work email. "
"If they have already tried that route and it failed, offer to create "
"an access request with their company's IT team. If they agree, "
"call `create_access_ticket` with a brief description of the problem. "
"Explain the result. If a ticket was created, share its reference, assigned "
"support team, and next step. Do not offer a product "
"password reset or claim access has already been restored."
),
dependencies=[talking_to_a_business_user],
tools=[create_access_ticket],
)
That's it. Dana and Sam now get personalized handling for their login issues based on their group membership. The send_password_reset and create_access_ticket tools are your own integrations, which your coding agent writes.
If your agent also needs customer facts before it takes an action, see customer variables. To reuse facts a customer shared in an earlier conversation, see Cross-session memory.