Building a Pricing Agent: Dynamic Pricing and Quote Generation with AI
Implement an AI pricing agent that applies dynamic pricing rules, generates professional quotes, performs competitor price analysis, and handles discount approval workflows.
The Complexity of B2B Pricing
B2B pricing is rarely as simple as a price tag. Deals involve volume discounts, contract length tiers, bundle pricing, competitive matching, and approval chains. Sales reps spend hours assembling quotes manually, and inconsistent pricing erodes margins. An AI pricing agent codifies your pricing rules, generates professional quotes instantly, and enforces approval workflows for discounts that exceed predefined thresholds.
Pricing Rule Engine
The foundation is a rule engine that encodes your pricing logic. Rules are composable — each rule can modify the base price, and they apply in order.
from dataclasses import dataclass, field
from typing import Optional
from enum import Enum
class DiscountType(Enum):
PERCENTAGE = "percentage"
FIXED = "fixed"
@dataclass
class PricingRule:
name: str
discount_type: DiscountType
value: float
condition: str # e.g., "quantity >= 100"
max_discount_pct: float = 30.0 # ceiling to protect margins
requires_approval: bool = False
@dataclass
class LineItem:
product_id: str
product_name: str
base_price: float
quantity: int
applied_rules: list[str] = field(default_factory=list)
final_unit_price: float = 0.0
@property
def line_total(self) -> float:
return self.final_unit_price * self.quantity
@dataclass
class Quote:
quote_id: str
customer_name: str
items: list[LineItem]
valid_until: str
notes: str = ""
requires_approval: bool = False
approval_reason: Optional[str] = None
@property
def total(self) -> float:
return sum(item.line_total for item in self.items)
def evaluate_condition(condition: str, context: dict) -> bool:
"""Safely evaluate a pricing condition against context."""
allowed_names = {
"quantity": context.get("quantity", 0),
"contract_months": context.get("contract_months", 1),
"total_value": context.get("total_value", 0),
"is_new_customer": context.get("is_new_customer", False),
"customer_tier": context.get("customer_tier", "standard"),
}
try:
return bool(eval(condition, {"__builtins__": {}}, allowed_names))
except Exception:
return False
Applying Pricing Rules
The pricing engine iterates through rules, applies matching discounts, and tracks which rules were used for audit purposes.
PRICING_RULES = [
PricingRule(
name="Volume 50+",
discount_type=DiscountType.PERCENTAGE,
value=10.0,
condition="quantity >= 50",
),
PricingRule(
name="Volume 200+",
discount_type=DiscountType.PERCENTAGE,
value=20.0,
condition="quantity >= 200",
),
PricingRule(
name="Annual contract",
discount_type=DiscountType.PERCENTAGE,
value=15.0,
condition="contract_months >= 12",
),
PricingRule(
name="Enterprise deep discount",
discount_type=DiscountType.PERCENTAGE,
value=35.0,
condition="quantity >= 500 and contract_months >= 24",
requires_approval=True,
),
]
def calculate_price(
base_price: float,
quantity: int,
context: dict,
rules: list[PricingRule] = PRICING_RULES,
) -> tuple[float, list[str], bool]:
"""Apply pricing rules and return final unit price, applied rules, approval flag."""
ctx = {**context, "quantity": quantity}
total_discount_pct = 0.0
applied = []
needs_approval = False
for rule in rules:
if not evaluate_condition(rule.condition, ctx):
continue
if rule.discount_type == DiscountType.PERCENTAGE:
total_discount_pct += rule.value
if rule.requires_approval:
needs_approval = True
applied.append(rule.name)
# Cap total discount
max_cap = max((r.max_discount_pct for r in rules), default=30.0)
total_discount_pct = min(total_discount_pct, max_cap)
final_price = base_price * (1 - total_discount_pct / 100)
return round(final_price, 2), applied, needs_approval
Competitor Price Analysis
When a prospect mentions a competitor's price, the agent should be able to assess the competitive position and recommend a response.
from openai import AsyncOpenAI
import json
client = AsyncOpenAI()
COMPETITOR_ANALYSIS_PROMPT = """A prospect mentioned a competitor's pricing.
Our product: {our_product} at ${our_price}/unit
Competitor: {competitor} at ${competitor_price}/unit
Deal size: {quantity} units, {contract_months}-month contract
Customer tier: {customer_tier}
Our differentiation points:
{differentiators}
Return JSON with:
- "price_gap_pct": percentage difference
- "recommendation": "match", "hold", or "counter"
- "suggested_price": our recommended price per unit
- "talk_track": 2-3 sentences the sales rep can use
- "max_discount_pct": maximum discount percentage to recommend
"""
async def analyze_competitor_price(
our_product: str,
our_price: float,
competitor: str,
competitor_price: float,
quantity: int,
contract_months: int,
customer_tier: str,
differentiators: str,
) -> dict:
response = await client.chat.completions.create(
model="gpt-4o",
response_format={"type": "json_object"},
messages=[
{"role": "system", "content": "Return valid JSON only."},
{
"role": "user",
"content": COMPETITOR_ANALYSIS_PROMPT.format(
our_product=our_product,
our_price=our_price,
competitor=competitor,
competitor_price=competitor_price,
quantity=quantity,
contract_months=contract_months,
customer_tier=customer_tier,
differentiators=differentiators,
),
},
],
)
return json.loads(response.choices[0].message.content)
Quote Generation
The agent assembles all pricing decisions into a professional quote document.
See AI Voice Agents Handle Real Calls
Book a free demo or calculate how much you can save with AI voice automation.
import uuid
from datetime import datetime, timedelta
async def generate_quote(
customer_name: str,
items: list[dict],
context: dict,
) -> Quote:
"""Generate a complete quote with pricing rules applied."""
line_items = []
needs_approval = False
for item in items:
final_price, applied_rules, approval = calculate_price(
base_price=item["base_price"],
quantity=item["quantity"],
context=context,
)
if approval:
needs_approval = True
line_items.append(LineItem(
product_id=item["product_id"],
product_name=item["product_name"],
base_price=item["base_price"],
quantity=item["quantity"],
applied_rules=applied_rules,
final_unit_price=final_price,
))
valid_until = (datetime.utcnow() + timedelta(days=30)).strftime("%Y-%m-%d")
quote = Quote(
quote_id=f"Q-{uuid.uuid4().hex[:8].upper()}",
customer_name=customer_name,
items=line_items,
valid_until=valid_until,
requires_approval=needs_approval,
approval_reason="Deep discount rules triggered" if needs_approval else None,
)
return quote
def format_quote_text(quote: Quote) -> str:
lines = [
f"QUOTE: {quote.quote_id}",
f"Customer: {quote.customer_name}",
f"Valid until: {quote.valid_until}",
"",
"Line Items:",
]
for item in quote.items:
savings = (item.base_price - item.final_unit_price) * item.quantity
lines.append(
f" {item.product_name}: {item.quantity} x "
f"${item.final_unit_price:.2f} = ${item.line_total:.2f}"
f" (saves ${savings:.2f})"
)
if item.applied_rules:
lines.append(f" Discounts: {', '.join(item.applied_rules)}")
lines.append(f"\nTOTAL: ${quote.total:.2f}")
if quote.requires_approval:
lines.append(f"\n** REQUIRES APPROVAL: {quote.approval_reason} **")
return "\n".join(lines)
Discount Approval Workflow
Discounts that exceed thresholds need manager approval before the quote can be sent. The agent routes these through an approval queue.
async def submit_for_approval(quote: Quote, db_pool, notifier):
async with db_pool.acquire() as conn:
await conn.execute(
"""INSERT INTO quote_approvals
(quote_id, customer, total, reason, status, requested_at)
VALUES ($1, $2, $3, $4, 'pending', NOW())""",
quote.quote_id, quote.customer_name,
quote.total, quote.approval_reason,
)
await notifier.send(
channel="#pricing-approvals",
message=(
f"Quote {quote.quote_id} for {quote.customer_name} "
f"(${quote.total:.2f}) needs approval.\n"
f"Reason: {quote.approval_reason}"
),
)
FAQ
How do I prevent the pricing agent from offering discounts that are too deep?
Implement hard caps at the rule engine level using the max_discount_pct field. Even if multiple rules stack, the total discount cannot exceed the cap. Additionally, any discount above a configurable threshold (e.g., 25 percent) should automatically flag the quote for manager approval rather than applying it directly.
How do I handle pricing for custom or non-standard configurations?
Define a fallback rule that routes non-standard requests to a human pricing specialist. The agent collects the requirements in a structured format — quantities, contract terms, special needs — and creates an approval ticket with all the context the pricing team needs to respond quickly.
Should I let the LLM set prices directly?
Never. The LLM should recommend pricing strategies and generate talk tracks, but actual price calculations must come from your deterministic rule engine. LLMs are not reliable for precise arithmetic, and pricing errors have direct financial consequences. Use the LLM for analysis and presentation, not for the math.
#DynamicPricing #QuoteGeneration #PricingStrategy #SalesAI #Python #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.