EvalLayerTry the demo

Writing commercial policies for AI agents

Published 2026-07-27 · EvalLayer

A commercial policy for an AI agent is a short, machine-checkable specification of what the agent may spend, discount, promise, claim, and discuss. Not a values statement, and not a paragraph in the system prompt: a data structure that an enforcement layer can evaluate against every outbound action. The test of a good policy is that a computer can apply it the same way twice. This guide builds one field by field, ends with a complete worked example, and covers the mistakes that make policies unenforceable.

Why the policy is a separate artifact

Every business already has these rules. They live in a sales handbook, a pricing sheet, and the heads of three senior people. The agent does not read any of those, and the system prompt version ("be careful with discounts") is advice, not a limit. Writing the policy as data does two things at once: it forces the business to state its actual numbers, and it gives a pre-action authorization layer something exact to enforce. The policy is the contract between the business and its agent. Everything below is about writing that contract well.

Start from the money

Money is where incidents concentrate and where checking is easiest, so it goes first.

  • max_discount_pct is the largest discount the agent may offer, as a number. In February 2026 a customer talked a UK retailer's after-hours chatbot into 80% off an 8,000 GBP order by getting it to invent a promo code and then escalating. A cap of 15 turns that entire negotiation into a single deterministic question: is the number in the outbound message bigger than 15.
  • commitment_authority_usd is the largest dollar amount the agent may commit to in one action: a quote, a credit, a refund, a spend. It is the agent's signing authority, the same concept every company already applies to human reps.

Both fields are countable, which means they are enforced with exact checks rather than model judgment. A good deterministic layer normalizes the formats money actually arrives in: percentages with and without spaces, dollar amounts with commas, shorthand like 12k or 1.2M. The point is that the check reads the same message the customer will, and arithmetic does not have moods. The full division of labor with semantic checks is covered below.

Forbidden commitments

forbidden_commitments lists the categories of promise the agent must never make at any amount. The usual three: delivery date guarantees, legal indemnification, refund promises. These are the sentences that bind the company. When Air Canada's chatbot described a refund policy that did not exist, a tribunal held the airline to it, and the case is now the reference point for every conversation about agent liability.

The field holds plain descriptions ("delivery date guarantees") because the check is semantic: a model pass with the policy in context decides whether a sentence in the draft is a binding commitment of that type. A good enforcement layer distinguishes commitments from conversation. Promising to send a document or schedule a call is not a commercial commitment, and flagging it as one buries reviewers in noise.

Approved claims

approved_claims is an allowlist of factual assertions the agent may make about the product and the company. An allowlist rather than a blocklist, because agents fail by invention. Cursor's support bot fabricated a licensing policy in April 2025, and the correction arrived after the Reddit thread and the cancellations, not before. You cannot enumerate every false claim an agent might invent. You can enumerate the true ones it is allowed to repeat: certifications, integrations, support response times, published pricing.

Required disclaimers and blocked topics

  • required_disclaimers lists text that must appear in applicable messages, like "Pricing valid for 30 days" on anything that quotes a price. Presence is a literal string check: cheap, exact, and a quiet workhorse, because a missing disclaimer is one of the most common real-world violations.
  • blocked_topics lists subjects the agent does not discuss at all: competitor pricing, unreleased features, legal advice. Topic detection is semantic, and a violation is treated as a hard failure, because there is no compliant rewrite of a paragraph about a topic the agent should never have entered.

A complete worked example

A full policy for a sales-side support agent, using the exact field names EvalLayer's authorization endpoint accepts:

{
  "max_discount_pct": 15,
  "commitment_authority_usd": 5000,
  "forbidden_commitments": [
    "delivery date guarantees",
    "legal indemnification",
    "refund promises"
  ],
  "approved_claims": [
    "integrates with Shopify and Stripe",
    "SOC 2 Type II certified",
    "support responds within one business day"
  ],
  "required_disclaimers": [
    "Pricing valid for 30 days"
  ],
  "blocked_topics": [
    "competitor pricing",
    "unreleased features",
    "legal advice"
  ]
}

Twenty lines. It fits in a code review, it versions cleanly in git, and every line is checkable. Compare that with the same content written as prompt prose, where "be careful with big discounts" has to survive contact with a customer who negotiates for a living.

On authorship: the business owner of the channel writes this, not the ML team. The sales lead knows the real discount cap, legal knows which commitments are radioactive, support knows which topics blow up. The engineering work is wiring the fields into the send path. From then on, treat the policy like code: reviewed changes, version history, and a hash of the active version stamped into every decision record.

How deterministic and semantic rules divide the work

Each field maps to one of two check types, and the type determines what happens on a violation.

FieldCheckSeverityDecision on violation
max_discount_pctDeterministicAuthorityrequire_approval
commitment_authority_usdDeterministicAuthorityrequire_approval
required_disclaimersDeterministicSoftrewrite
forbidden_commitmentsSemanticHardblock
blocked_topicsSemanticHardblock
approved_claimsSemanticSoftrewrite

The logic behind the split: numbers and required strings are checked exactly, in milliseconds, immune to phrasing. Judgment calls (is this sentence a delivery guarantee?) get one model pass with the policy in context. Severity then drives the decision ladder. Hard violations block outright. Authority violations are legitimate business moves the agent lacks authority for, so they queue for a human. Soft violations trigger a compliant rewrite, which is itself re-checked before it is offered. The ladder and its rationale are covered in the guardrails guide.

Common mistakes

  1. The policy lives in people's heads. The discount cap is whatever the sales lead would say if asked. Unwritten policy cannot be enforced, and the first time it gets written down is usually inside an incident postmortem.
  2. The policy is prose in a prompt. "Do not offer large discounts" is a wish. Prompts shape behavior; they do not enforce limits, and a determined customer routes around them. The failure pattern and the fix are the subject of how to stop unauthorized discounts.
  3. No severity tiers. If every violation blocks, the agent becomes useless and someone turns the layer off within a month. If every violation merely logs, you have monitoring, not policy. Three tiers exist so the response is proportionate to the risk.
  4. The policy never changes. Treat the approval queue as telemetry. If reviewers approve the same over-cap discount every week, the cap is wrong: raise it and version the change. A policy nobody updates is a policy nobody believes.

Write the six fields, wire them into the send path, and watch the first week of decisions. The live demo runs a noncompliant draft against a sample policy much like the one above and shows every rung of the ladder in about two minutes.

Frequently asked questions

How long should an AI agent policy be?

About a page of JSON. Six fields cover most commercial deployments: two numbers for money, lists for forbidden commitments, approved claims, and blocked topics, and a list of required disclaimers. If your policy does not fit on a page, you are probably writing prose descriptions of judgment calls instead of checkable rules.

Should the policy also go in the system prompt?

Yes. The prompt version lowers the violation rate, which keeps the approval queue short. But the prompt is what you ask the agent to do; the policy object is what happens when it does something else. One shapes behavior, the other enforces limits.

How do I pick the initial numbers?

Give the agent the authority you would give a new human hire in the same seat during their first week: a modest discount cap and a small commitment authority. Then let the approval queue tell you where reality disagrees, and version each change.

What is the difference between forbidden_commitments and blocked_topics?

forbidden_commitments covers categories of binding promise: delivery date guarantees, indemnification, refund promises. blocked_topics covers subjects the agent should not discuss at all, like competitor pricing or legal advice. Both are semantic checks that block on violation; the first protects against obligations, the second against conversations.

See the authorization layer live

Paste a message, set a policy, get allow / rewrite / require approval / block in seconds.

Try the demo