AI Agent for Loyalty Programs: Points Balance, Rewards, and Redemption Assistance
Build an AI agent that helps customers check loyalty points balances, browse reward catalogs, redeem rewards, and understand how to earn points faster — increasing program engagement and customer retention.
Why Loyalty Programs Need AI Agents
Most loyalty programs suffer from low engagement: customers earn points but never check their balance, miss expiration deadlines, and do not know what rewards are available. An AI agent changes this by proactively informing customers of their points status, suggesting optimal redemptions, and guiding them toward earning thresholds — all through natural conversation.
Modeling the Loyalty System
A loyalty system tracks member accounts, point balances, transaction history, and a reward catalog.
from agents import Agent, Runner, function_tool
from datetime import datetime, timedelta
# Member database
LOYALTY_MEMBERS = {
"MEM-001": {
"name": "Alex Rivera",
"email": "alex@example.com",
"tier": "Gold",
"points_balance": 4750,
"points_expiring": {"amount": 500, "date": "2026-04-15"},
"lifetime_points": 12300,
"tier_thresholds": {"Silver": 5000, "Gold": 10000, "Platinum": 25000},
"history": [
{"date": "2026-03-10", "description": "Purchase #ORD-8821",
"points": 150, "type": "earned"},
{"date": "2026-03-05", "description": "Birthday bonus",
"points": 200, "type": "earned"},
{"date": "2026-02-28", "description": "Redeemed: $10 coupon",
"points": -1000, "type": "redeemed"},
],
},
}
# Reward catalog
REWARDS_CATALOG = [
{"id": "RWD-01", "name": "$5 Store Credit", "points_cost": 500,
"category": "discount", "min_tier": "Silver"},
{"id": "RWD-02", "name": "$10 Store Credit", "points_cost": 1000,
"category": "discount", "min_tier": "Silver"},
{"id": "RWD-03", "name": "Free Shipping (1 month)", "points_cost": 750,
"category": "perk", "min_tier": "Silver"},
{"id": "RWD-04", "name": "$25 Store Credit", "points_cost": 2500,
"category": "discount", "min_tier": "Gold"},
{"id": "RWD-05", "name": "Early Access to Sales", "points_cost": 3000,
"category": "perk", "min_tier": "Gold"},
{"id": "RWD-06", "name": "Personal Shopping Session", "points_cost": 5000,
"category": "experience", "min_tier": "Platinum"},
]
TIER_ORDER = ["Silver", "Gold", "Platinum"]
@function_tool
def check_points_balance(member_id: str) -> str:
"""Check a member's current points balance and tier status."""
member = LOYALTY_MEMBERS.get(member_id)
if not member:
return "Member not found. Please provide a valid membership ID."
expiring = member["points_expiring"]
next_tier_idx = TIER_ORDER.index(member["tier"]) + 1
next_tier_info = ""
if next_tier_idx < len(TIER_ORDER):
next_tier = TIER_ORDER[next_tier_idx]
threshold = member["tier_thresholds"][next_tier]
needed = threshold - member["lifetime_points"]
if needed > 0:
next_tier_info = (
f" You need {needed} more lifetime points to "
f"reach {next_tier} tier."
)
return (
f"Member: {member['name']} | Tier: {member['tier']}\n"
f"Current Balance: {member['points_balance']} points\n"
f"Expiring Soon: {expiring['amount']} points by {expiring['date']}\n"
f"Lifetime Points: {member['lifetime_points']}{next_tier_info}"
)
@function_tool
def view_points_history(member_id: str, limit: int = 5) -> str:
"""View recent points transaction history."""
member = LOYALTY_MEMBERS.get(member_id)
if not member:
return "Member not found."
lines = ["Recent Points Activity:"]
for txn in member["history"][:limit]:
sign = "+" if txn["type"] == "earned" else ""
lines.append(
f" {txn['date']}: {txn['description']} "
f"({sign}{txn['points']} pts)"
)
return "\n".join(lines)
Reward Browsing and Redemption
@function_tool
def browse_rewards(member_id: str,
category: str = "all") -> str:
"""Browse available rewards filtered by member tier and category."""
member = LOYALTY_MEMBERS.get(member_id)
if not member:
return "Member not found."
member_tier_idx = TIER_ORDER.index(member["tier"])
available = []
for reward in REWARDS_CATALOG:
reward_tier_idx = TIER_ORDER.index(reward["min_tier"])
if reward_tier_idx > member_tier_idx:
continue
if category != "all" and reward["category"] != category:
continue
can_afford = member["points_balance"] >= reward["points_cost"]
available.append(
f" {reward['id']}: {reward['name']} - "
f"{reward['points_cost']} pts "
f"{'[CAN REDEEM]' if can_afford else '[Need more points]'}"
)
if not available:
return "No rewards available for your tier and category."
return f"Available Rewards for {member['tier']} members:\n" + \
"\n".join(available)
@function_tool
def redeem_reward(member_id: str, reward_id: str) -> str:
"""Redeem a reward using loyalty points."""
member = LOYALTY_MEMBERS.get(member_id)
if not member:
return "Member not found."
reward = next((r for r in REWARDS_CATALOG if r["id"] == reward_id), None)
if not reward:
return "Reward not found in catalog."
# Tier check
member_tier_idx = TIER_ORDER.index(member["tier"])
reward_tier_idx = TIER_ORDER.index(reward["min_tier"])
if reward_tier_idx > member_tier_idx:
return (
f"This reward requires {reward['min_tier']} tier. "
f"Your current tier is {member['tier']}."
)
# Balance check
if member["points_balance"] < reward["points_cost"]:
deficit = reward["points_cost"] - member["points_balance"]
return (
f"Insufficient points. You need {deficit} more points "
f"to redeem {reward['name']}."
)
member["points_balance"] -= reward["points_cost"]
member["history"].insert(0, {
"date": datetime.now().strftime("%Y-%m-%d"),
"description": f"Redeemed: {reward['name']}",
"points": -reward["points_cost"],
"type": "redeemed",
})
return (
f"Redeemed {reward['name']} for {reward['points_cost']} points. "
f"Remaining balance: {member['points_balance']} points. "
f"Your reward will be applied to your account within 24 hours."
)
@function_tool
def get_earning_tips(member_id: str) -> str:
"""Suggest ways for a member to earn more points."""
member = LOYALTY_MEMBERS.get(member_id)
if not member:
return "Member not found."
tips = [
"Earn 1 point per dollar spent on all purchases",
"Double points on purchases during your birthday month",
"Earn 50 bonus points for writing a product review",
"Refer a friend and earn 500 points when they make their first purchase",
"Shop during Double Points events (check your email for announcements)",
]
if member["tier"] == "Gold":
tips.append("Gold members earn 1.5x points on all purchases")
elif member["tier"] == "Platinum":
tips.append("Platinum members earn 2x points on all purchases")
return "Ways to earn more points:\n" + \
"\n".join(f" - {t}" for t in tips)
Assembling the Loyalty Agent
loyalty_agent = Agent(
name="Loyalty Program Assistant",
instructions="""You manage the loyalty rewards program.
Key responsibilities:
- Check and explain point balances, including expiring points
- Help members browse and redeem rewards
- Proactively warn about points expiring soon
- Suggest optimal redemptions based on balance and tier
- Explain how to earn more points and reach the next tier
- Show transaction history on request
Always mention expiring points if they exist. Recommend using
expiring points first. If a member is close to a tier upgrade,
encourage them with the specific points needed.""",
tools=[check_points_balance, view_points_history,
browse_rewards, redeem_reward, get_earning_tips],
)
FAQ
How do I handle points expiration without frustrating customers?
Send proactive notifications at 30 days, 14 days, and 3 days before expiration. When a customer interacts with the agent, always surface expiring points prominently. Offer easy low-cost redemptions (like small coupons) that let customers use expiring points immediately. Some programs extend expiration when any account activity occurs — this is generous but effective at reducing complaints.
See AI Voice Agents Handle Real Calls
Book a free demo or calculate how much you can save with AI voice automation.
How should the agent optimize redemption recommendations?
Calculate the value-per-point ratio for each reward. A $10 credit for 1000 points is $0.01/point, while a $25 credit for 2500 points is also $0.01/point — same value. But experiential rewards or exclusive perks may have higher perceived value. The agent should present options with their per-point value and let the customer decide, while highlighting the best-value options.
Can the loyalty agent help with tier qualification disputes?
Yes. Give the agent a tool that pulls the detailed points history for the qualification period. The agent can show exactly which transactions counted toward tier qualification, explain any pending points that have not posted yet, and identify the gap. If the customer believes points are missing, the agent should escalate to a human agent with the specific transaction details pre-gathered to speed up resolution.
#LoyaltyPrograms #RewardsAI #CustomerRetention #PointsRedemption #RetailAI #AgenticAI #LearnAI #AIEngineering
CallSphere Team
Expert insights on AI voice agents and customer communication automation.
Try CallSphere AI Voice Agents
See how AI voice agents work for your industry. Live demo available -- no signup required.