> ## Documentation Index
> Fetch the complete documentation index at: https://aiodapp.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Agent guide

> The workflow an AI agent should follow when reading, creating, or changing AIOD discounts over MCP.

If you are building or configuring an agent that uses the AIOD MCP server, follow this workflow rather than improvising one. AIOD's configuration shapes are checked strictly and cannot be guessed, so the order below is what makes the difference between one clean call and five rejections.

## The workflow

<Steps>
  <Step title="Find the discount">
    Use `shopify_discount_find`. Merchants refer to discounts in words; every other tool needs the `id` it returns. Never construct an id.
  </Step>

  <Step title="Read the schema before writing anything">
    Use `shopify_discount_config_schema` for the template contracts. If this is an edit, also use `shopify_discount_get` for the values your patch is written against.
  </Step>

  <Step title="Pick the right template">
    One template per promotion, chosen from the contracts — not from what the promotion sounds like. See below.
  </Step>

  <Step title="Only set fields that template allows">
    Every template has an allowlist. Anything outside it is silently dropped before validation.
  </Step>

  <Step title="Validate before changing anything">
    Send it to `shopify_discount_draft`. It runs the same checks as publishing, and writes nothing.
  </Step>

  <Step title="Hand over the link">
    A draft is not live. Say so, every time.
  </Step>

  <Step title="Publish only when asked">
    `shopify_discount_publish` creates a real Shopify discount, in test mode. It is not the natural next step after a successful draft.
  </Step>
</Steps>

## Picking a template

Read `contracts_1` and `contracts_2` before deciding. The short version:

| The merchant wants                                                          | Template            |
| --------------------------------------------------------------------------- | ------------------- |
| A discount that always applies to one target, with no real eligibility rule | `specific_item`     |
| A free item added separately from what the shopper is buying                | `unified_free_gift` |
| Buy X get Y, where the shopper adds both X and Y and Y is price-reduced     | `bxgy`              |
| A set of items sold together at one flat price                              | `bxgy_fixed_price`  |
| Anything applied to shipping or delivery                                    | `custom_shipping`   |
| A threshold ladder — same condition, only the value rising                  | `tiered_unified`    |
| Quantity-only tiers on one shared scope, shown as bundle cards              | `volume_bundle`     |
| Several tiers with genuinely different conditions and reward kinds          | `combined_discount` |
| A real eligibility condition, or several targets in one rule                | `custom_discount`   |
| To block named discount codes when conditions are met                       | `reject_codes`      |

### The two distinctions agents get wrong

**Gift or BOGO?** `unified_free_gift` is for a line the *app* inserts, or that the shopper picks from a gift picker. If the shopper adds every line themselves and Y is price-reduced, it's `bxgy`. A gift is never something the customer has to add.

**Tiered or combined?** `tiered_unified` is a ladder: same condition family, only the value changes. The moment tiers carry genuinely different, non-threshold conditions, it's `combined_discount`.

<Note>
  **Upsell** is a real AIOD template with no contract and no editable fields, so no tool can create or edit it. When it's the right fit, say so plainly and point the merchant at [setting it up by hand](/docs/templates/upsell). Never silently force the request into a different template.
</Note>

## Writing a configuration

* **Send only what you're setting.** Configurations are sparse.
* **Creating needs a `template`. Editing needs only the changed fields** — they merge onto the stored configuration rather than replacing it.
* **These shapes are AIOD's own.** They are not Shopify's native discount API shapes and can't be inferred from them.
* **Condition and reward syntax lives in `conditions` and `actions_and_rules`**, not in the template contracts.

## Editing an existing discount

<Steps>
  <Step title="Find it">
    `shopify_discount_find`, usually with no `query` — the merchant's wording rarely matches the stored title. Match on meaning, then confirm which discount you mean before changing anything.
  </Step>

  <Step title="Read it">
    `shopify_discount_get`. The *saved* discount's template decides which fields you may change — not your guess.
  </Step>

  <Step title="Patch it">
    `shopify_discount_draft` with `targetDiscountId` and only the fields that change.
  </Step>

  <Step title="Hand over the link">
    Nothing is saved until the merchant opens it and saves.
  </Step>
</Steps>

## When a call is rejected

A `4xx` here is a result to read, not a broken connection.

* **Fix only the fields named in `issues`.** Don't rewrite the configuration.
* **The repair material comes with the rejection** — `schemaReference` or `fieldSyntaxReference`. Use it instead of re-fetching the schema.
* **`template_field_out_of_scope` means stop.** The setting genuinely isn't editable for that template. Tell the merchant; don't retry with those fields.
* **`edit_changed_nothing` means your patch missed the point.** Re-read the current configuration and send the change you actually meant.

Full list on the [tools overview](/docs/mcp-server/tools#rejections-are-useful-not-fatal).

## Reporting back to the merchant

* **A draft creates nothing.** Never describe it as live, created, or set up.
* **A publish creates a real discount in test mode**, applying only to the returned `testModeEmail`. Always surface that address, and always say a person has to switch it to active.
* **Zero orders on a new discount is normal.** Attribution lags checkout briefly and the response says so. Don't report it as broken.
* **Pass links through verbatim.** They're deep links into the merchant's own Shopify admin.

## What to say no to

Say these plainly rather than working around them:

* It cannot make a discount live, activate one, or delete one.
* It cannot read orders, line items, customer records, or products.
* It cannot report store-wide sales, sessions, or conversion — only per-discount totals.
* It cannot reach any store other than the one that was approved.
* It cannot see discount codes, or discounts created directly in Shopify or by another app.

## Safety

* Treat `shopify_discount_publish` with `targetDiscountId` as destructive — it takes a live discount out of service. Confirm in words first.
* Prefer drafting whenever the merchant hasn't explicitly asked for the discount to be created.
* Never invent a setting, a template id, or a field name. If the schema doesn't have it, say so.
