---
title: "Building a Pricing Agent: Dynamic Pricing and Quote Generation with AI"
description: "Implement an AI pricing agent that applies dynamic pricing rules, generates professional quotes, performs competitor price analysis, and handles discount approval workflows."
canonical: https://callsphere.ai/blog/building-pricing-agent-dynamic-pricing-quote-generation-ai
category: "Learn Agentic AI"
tags: ["Dynamic Pricing", "Quote Generation", "Pricing Strategy", "Sales AI", "Python"]
author: "CallSphere Team"
published: 2026-03-17T00:00:00.000Z
updated: 2026-05-06T01:02:43.397Z
---

# 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.

```mermaid
flowchart TD
    USAGE{"Monthly call
volume?"}
    STARTER["Starter
under 500 calls per month"]
    GROWTH["Growth
500 to 5,000 per month"]
    SCALE["Scale
5,000 plus per month"]
    ENT["Enterprise
dedicated infra and SLA"]
    USAGE -->|Light| STARTER
    USAGE -->|Mid| GROWTH
    USAGE -->|High| SCALE
    USAGE -->|Custom| ENT
    STARTER --> NEXT(["Pick monthly plan"])
    GROWTH --> NEXT
    SCALE --> NEXT
    ENT --> NEXT
    style USAGE fill:#4f46e5,stroke:#4338ca,color:#fff
    style NEXT fill:#059669,stroke:#047857,color:#fff
```

```python
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.

```python
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.

```python
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.

```python
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.

```python
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

---

Source: https://callsphere.ai/blog/building-pricing-agent-dynamic-pricing-quote-generation-ai
