n4nAI

How to train an AI sales agent on your pricing rules

Step-by-step guide to train AI sales agent pricing rules using structured prompts, function calls, and validation to enforce margins and discounts reliably.

n4n Team3 min read755 words

Audio narration

Coming soon — every post will get a voice note here.

Most sales automation breaks the moment a rep asks for a custom discount outside the approved band. To train AI sales agent pricing rules that hold up in production, you need more than a prompt—you need a structured policy, a validation layer, and a test harness. This guide walks through building an agent that quotes correctly against your real pricing matrix.

Step 1: Model your pricing rules as executable policy

Don’t bury pricing logic in a paragraph of natural language. Extract it into a version-controlled schema. At minimum, capture: list prices, volume tiers, allowed discount bands per tier, margin floors, and regional multipliers.

{
  "skus": {
    "PRO-100": { "base_price": 1200, "margin_floor": 0.35 },
    "ENT-500": { "base_price": 5400, "margin_floor": 0.40 }
  },
  "volume_tiers": [
    { "min_qty": 1, "max_qty": 10, "discount_pct": 0 },
    { "min_qty": 11, "max_qty": 50, "discount_pct": 0.05 },
    { "min_qty": 51, "max_qty": null, "discount_pct": 0.12 }
  ],
  "region_multipliers": { "US": 1.0, "EU": 1.08, "APAC": 0.95 },
  "max_discount_override": 0.15
}

Load this into your agent process as a frozen config. Any change goes through code review. When you train AI sales agent pricing rules, treat the schema as the source of truth; the model is just a negotiator that must obey it. Store the file in Git, tag releases, and inject the exact commit hash into the agent’s runtime context so quotes are reproducible.

Step 2: Write a system prompt that states non-negotiable constraints

The LLM needs explicit boundaries. Give it the rules in compact form and forbid deviations.

SYSTEM_PROMPT = """You are a sales quoting agent for Acme Corp.
You MUST compute prices using the provided pricing tool.
Rules:
- Never quote below margin_floor for any SKU.
- Discounts outside volume_tier bands require manager approval; do not grant them.
- Apply region_multiplier to base_price before volume discount.
- If a request violates a rule, respond with 'POLICY_BLOCKED' and reason.
You are helpful but strict. Do not invent SKUs."""

Notice we did not paste the full JSON into the prompt. Instead we inject it at runtime via a tool description or a separate context block. When you train AI sales agent pricing rules, keep the prompt about behavior, not data. The model should understand it is a clerk, not an oracle. Few-shot examples are unnecessary if the tool is deterministic.

Step 3: Expose a deterministic quote function via tool calling

The model should never multiply prices itself. Define a Python function and register it as an OpenAI-style tool.

from typing import TypedDict

class QuoteRequest(TypedDict):
    sku: str
    qty: int
    region: str
    requested_discount: float

def compute_quote(req: QuoteRequest, policy: dict) -> dict:
    sku = policy["skus"].get(req["sku"])
    if not sku:
        return {"error": "unknown_sku"}
    tier = next(t for t in policy["volume_tiers"]
                if t["min_qty"] <= req["qty"] and (t["max_qty"] is None or req["qty"] <= t["max_qty"]))
    region_mult = policy["region_multipliers"].get(req["region"], 1.0)
    base = sku["base_price"] * region_mult * req["qty"]
    vol_disc = tier["discount_pct"]
    # requested discount cannot exceed tier discount + override buffer
    allowed_disc = min(vol_disc + policy["max_discount_override"], req["requested_discount"])
    if allowed_disc < req["requested_discount"]:
        return {"error": "discount_exceeds_policy", "max_allowed": allowed_disc}
    final = base * (1 - allowed_disc)
    if (final / (sku["base_price"] * req["qty"])) < sku["margin_floor"]:
        return {"error": "margin_floor_breached"}
    return {"unit_price": sku["base_price"] * region_mult * (1 - allowed_disc),
            "total": final, "applied_discount": allowed_disc}

Register the tool with the model:

{
  "name": "compute_quote",
  "description": "Calculate a binding price quote for a SKU given qty, region, and requested discount.",
  "parameters": {
    "type": "object",
    "properties": {
      "sku": {"type": "string"},
      "qty": {"type": "integer"},
      "region": {"type": "string"},
      "requested_discount": {"type": "number"}
    },
    "required": ["sku", "qty", "region", "requested_discount"]
  }
}

The agent calls compute_quote, gets back validated numbers, and relays them. This is the core of how you train AI sales agent pricing rules without fine-tuning weights. The LLM learns to map free-text negotiations to structured arguments, while the math stays in code.

Step 4: Add a post-hoc validation gate

Tool calls can still be mis-specified by the model (e.g., wrong region string). Wrap the agent output in a validator that re-runs the policy check on the returned numbers.

def validate_agent_output(agent_msg: dict, policy: dict) -> bool:
    # agent_msg contains the tool call args and the returned quote
    req = agent_msg["tool_call"]["arguments"]
    quote = agent_msg["tool_response"]
    if "error" in quote:
        return agent_msg["text"].startswith("POLICY_BLOCKED")
    recomputed = compute_quote(req, policy)
    return recomputed == quote

If validation fails, discard the turn and return a canned “system error” response. This guarantees the pricing rules are enforced even if the LLM drifts. Log the mismatch as a regression signal.

Step 5: Build an adversarial test suite

You cannot ship without tests. Write pytest cases covering edge cases:

def test_volume_tier_discount():
    policy = load_policy()
    req = {"sku": "PRO-100", "qty": 20, "region": "US", "requested_discount": 0.1}
    q = compute_quote(req, policy)
    assert q["applied_discount"] == 0.05  # tier discount only, override not needed

def test_margin_floor_blocks():
    policy = load_policy()
    req = {"sku": "PRO-100", "qty": 100, "region": "APAC", "requested_discount": 0.5}
    q = compute_quote(req, policy)
    assert "error" in q and q["error"] == "margin_floor_breached"

def test_unknown_sku():
    policy = load_policy()
    req = {"sku": "BOGUS", "qty": 1, "region": "US", "requested_discount": 0}
    q = compute_quote(req, policy)
    assert q["error"] == "unknown_sku"

Run these in CI. When you train AI sales agent pricing rules, the test suite is the real curriculum; the model learns the boundaries by being constrained, not by seeing examples. Add tests for region typos, negative quantities, and floating point discount requests.

Step 6: Deploy behind a resilient inference layer

In production, model providers throttle or degrade. If your quoting agent depends on a single LLM endpoint, a 429 kills the sales motion. Front the agent with an OpenAI-compatible gateway that supports fallback.

If you serve this through n4n.ai, you point your OpenAI client at a single endpoint that fronts 240+ models and automatically routes to a healthy provider when the primary is rate-limited. Your tool-calling schema stays identical; only the base_url changes.

from openai import OpenAI

client = OpenAI(
    base_url="https://api.n4n.ai/v1",  # OpenAI-compatible
    api_key="YOUR_KEY"
)
resp = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[{"role": "system", "content": SYSTEM_PROMPT},
              {"role": "user", "content": "Quote 30 ENT-500 in EU at 10% discount"}],
    tools=[QUOTE_TOOL],
    tool_choice="auto"
)

The gateway forwards provider cache-control hints, so repeated policy injections cost less. That’s the only infrastructure change required to make the agent resilient.

Step 7: Monitor, meter, and iterate

Log every tool call with the policy version. Track how often POLICY_BLOCKED triggers—that tells you where sales reps push limits. Use per-token metering to attribute cost per quote; if a single negotiation burns 5k tokens, tighten the prompt. If you use n4n.ai, its per-token usage metering breaks down cost per negotiation, which exposes prompt bloat.

Quarterly, revisit the JSON policy. Add new SKUs, adjust margin floors. Because the model never learned prices as weights, updating the file retrains the agent instantly. That is the practical end state when you train AI sales agent pricing rules as code plus guardrails.

Verifying success

Success means: (1) unit tests pass, (2) a manual chat with the agent yields POLICY_BLOCKED for an illegal discount and a correct number for a legal one, (3) chaos test by killing the primary model provider still returns quotes via fallback. Run a scripted conversation:

curl -X POST https://api.n4n.ai/v1/chat/completions \
  -H "Authorization: Bearer $KEY" \
  -d '{"model":"gpt-4o-mini","messages":[{"role":"user","content":"Give me 60 PRO-100 in APAC at 20% off"}],"tools":[...]}'

Expect either a blocked response or a quote with discount capped at policy max. If you see a raw number below margin floor, your validator has a bug. Fix before launch.

That’s the full loop. No fine-tuning required, just disciplined engineering.

Tagsai-sales-agentspricingtrainingsales-automation

Written by

n4n Team

The team building n4n — a single OpenAI-compatible API in front of 240+ models, with automatic fallback, load balancing and pay-per-token metering.

More from n4n Team →

All ai agents in sales & crm posts →