← Zuora Coding AgentCONTENT HISTORYWHAT CHANGED · RULE-BASED ANALYSIS
Update to Zuora Coding Agent
Snapshot Sep 30, 2026 · 23:14 UTC · version 1.5.4
Collection source: not recorded for this historical snapshot.
First saved snapshot
No earlier snapshot is available to establish a change.
Compare saved observations
Download comparison JSONFull technical diff · 0 changed fields
Full snapshot data
{
"name": "zuora-dynamic-pricing-design",
"description": "Design a Commerce Catalog setup with dynamic pricing — gather requirements, inspect tenant state, and propose the catalog structure before execution",
"included_files": [],
"skill_md_contents": "---\nname: zuora-dynamic-pricing-design\ndescription: Design a Commerce Catalog setup with dynamic pricing — gather requirements, inspect tenant state, and propose the catalog structure before execution\nargument-hint: [product/pricing description or business requirement]\nallowed-tools: [Read, Glob, Grep, Bash, Agent, mcp__zuora-mcp__manage_commerce_context_attributes, mcp__zuora-mcp__manage_commerce_charges, mcp__zuora-mcp__query_objects, mcp__zuora-mcp__manage_custom_fields, mcp__zuora-mcp__ask_zuora]\n---\n\nYou are designing a Commerce Catalog setup with dynamic pricing. Your job is to gather requirements, inspect the tenant's current state, and propose a complete catalog structure — NOT to create anything yet.\n\n## Preflight: Check DynamicPricing is enabled\n\nBefore proceeding, call `manage_commerce_charges` with `{\"help\": true, \"operation\": \"create_charge\"}`. If the tool is not available (not listed / not found), stop and tell the user:\n\n> The DynamicPricing feature is not enabled on this tenant. Enable it at **Settings > Billing > Manage Features > Commerce**, then retry.\n\nNote: The Commerce Catalog and Classic Catalog are mutually exclusive.\n\n## Input\n\nThe user's request: $ARGUMENTS\n\n## Tool routing\n\nUse `manage_commerce_context_attributes` with `list_attributes` to inspect existing schemas. Use `query_objects` to check existing products, plans, and custom fields. Use `manage_commerce_charges` with `help: true` for charge model guidance. Use `manage_custom_fields` to inspect and create custom field definitions. Use `mcp__zuora-mcp__ask_zuora` only as a fallback for unresolved product-behavior questions (e.g., \"can dynamic pricing coexist with discount charges?\") after checking the charge help and references first.\n\n## Workflow\n\n### Step 1: Clarify requirements\n\nDetermine the scope:\n- **Full catalog setup** — new product + plan + charge with dynamic pricing\n- **Add dynamic pricing to existing charge** — new attributes and rate cards on an existing charge\n- **Update rate card** — modify prices, add attribute values, add rows\n\nFor new setups, gather:\n- Product name, description, category (`base` or `add-on`)\n- Plan name, billing currencies\n- Charge model: `flat_fee`, `per_unit`, `tiered`, `volume`, `tiered_overage`, `overage`, `discount_percentage`, `discount_fixed_amount`\n- Charge type: `recurring`, `one_time`, `usage`\n- What business dimensions drive pricing (e.g., region, customer segment, commitment type, quantity band)\n- Expected pricing for each dimension combination\n- Default pricing (fallback when no rate card matches)\n- Billing cycle preferences\n- Unit of measure (for per_unit, tiered, volume, usage charges)\n- **Effective dating** — does any price need to change on a future date, or does the price history need to be preserved? (e.g., \"US price is $10 today, rises to $12 on 2026-04-01\"). If yes, capture the effective start date for each price point. See the effective dating section below.\n\n**Product grouping principle:** If the user describes what looks like multiple products that share the same base name but differ by pricing (e.g., \"On-Demand\" vs \"Reserved\" vs \"Spot\"), consolidate them into ONE product with ONE charge that has MULTIPLE rate cards differentiated by attributes. Don't create separate products for pricing variations.\n\n**Attribute mapping level:** Some attributes can validly map to multiple objects (e.g., \"Region\" could live on Account, RatePlan, or a usage record). When the mapping level is ambiguous, confirm with the user. Choose based on at what granularity the value changes:\n- **Account** — fixed per customer, shared across all subscriptions (e.g., customer region, segment)\n- **Subscription** — can differ between subscriptions for the same customer (e.g., commitment type: one sub is \"reserved\", another \"on-demand\")\n- **RatePlan** — set per rate plan instance within a subscription (e.g., service tier chosen for that specific plan)\n- **Usage** — varies per event/record (e.g., resource type, cloud region of the API call). Only available on usage charges.\n\nA single charge can combine attributes at different levels (e.g., `CustomerTier` on Account + `ResourceType` on Usage).\n\n**Effective dating (time-varying pricing):**\n\nDynamic pricing rate cards support effective dating so a price can change on a future date while the prior price is preserved as history. This is driven by a **reserved attribute named `EffectiveDate`** — it is NOT a business dimension, does NOT map to any object field, and does NOT need a custom field created.\n\nHow it works in the catalog:\n- `EffectiveDate` is a reserved attribute of type `Datetime`. On each rate card row it takes the `>=` operator only (it marks the row's start / \"effective from\" instant). Any other operator is rejected.\n- The value is an ISO-8601 datetime **with a zone offset**, e.g. `2026-04-01T00:00:00Z` or `2026-04-01T00:00:00-08:00`. A bare local date with no offset is rejected.\n- If a rate card row omits `EffectiveDate`, it defaults to \"effective from now\" (`>= current time`).\n- For the **same business-attribute combination**, adding a new row with a later `EffectiveDate` does NOT overwrite the old price. The system automatically closes the previous row to a bounded window ending 1 second before the new start, and the new row becomes the open-ended current price. This builds a price timeline:\n - Old row: US → $10, effective `[original start, 2026-03-31T23:59:59]`\n - New row: US → $12, effective `>= 2026-04-01T00:00:00Z`\n- Rows are grouped for timeline purposes by their business attributes only (`EffectiveDate` is excluded from the grouping key). So each unique dimension combination carries its own independent price history.\n\nWhen to surface effective dating in the design:\n- The user wants a scheduled/future price change (\"raise EU price to €9 starting next quarter\").\n- The user wants to backfill or preserve historical prices rather than replace them.\n- Two rows in the same request that share the same business attributes AND the same effective date are a duplicate and will be rejected — flag this if the requirements imply it.\n\nIf pricing never changes over time, no `EffectiveDate` attribute needs to be shown to the user — the system still records an implicit \"effective from now\" internally.\n\n### Step 2: Inspect tenant state\n\n#### 2a: Check existing context schemas and attributes\n\nCall `manage_commerce_context_attributes` with `list_attributes` to see what's already configured. Available context schemas include: Business Structure, Catalog, Channel, Custom, Customer Context, Location.\n\n#### 2b: Check mapped fields\n\nAttributes can map to **standard fields** or **custom fields** (`__c` suffix) on multiple Zuora objects. Use `query_objects` with `help: \"fields\"` and the target `objectType` to discover available fields.\n\n- `account` — standard or custom fields\n- `subscription` — standard or custom fields\n- `rate_plan` — standard or custom fields\n- `usage` — usage record fields\n\nStandard fields already exist — no creation needed. Only custom fields (`__c` suffix) require creation.\n\n**Ambiguous mappings:** When an attribute could reasonably live on multiple objects, ask the user which level to map it at. Explain the granularity:\n- **Account** — one value per customer, applies to all subscriptions\n- **Subscription** — can vary across subscriptions for the same customer\n- **RatePlan** — set per rate plan instance within a subscription\n- **Usage** — varies per usage record; only available on usage charges\n\nA single charge can combine attributes at different levels.\n\nIf custom fields are needed, use `manage_custom_fields` with `list_custom_fields` to check what exists. Note missing custom fields as prerequisites:\n- Object type (Account, Subscription, RatePlan, etc.)\n- Field name (must end with `__c`)\n- Field type (`string` or `integer`)\n- Label and description\n\n#### 2c: Check existing catalog entities\n\nUse `query_objects` to inspect:\n- Existing products: `objectType: \"Product\"`\n- Existing rate plans: `objectType: \"ProductRatePlan\"`\n- Existing charges: `objectType: \"ProductRatePlanCharge\"`\n\nThis helps determine whether to create new entities or attach dynamic pricing to existing ones.\n\n### Step 3: Charge model guidance\n\nCall `manage_commerce_charges` with `help: true` to get detailed field requirements, constraints, and examples for the chosen charge model.\n\nKey model decisions:\n- **flat_fee** — fixed amount per period (simplest)\n- **per_unit** — price × quantity (per seat, per license)\n- **tiered** — progressive tiers (first N at price A, next M at price B)\n- **volume** — all units priced at the tier reached by total quantity\n- **tiered_overage** — included units + tiered overage pricing\n- **overage** — simple per-unit overage rate\n- **discount_percentage** / **discount_fixed_amount** — discounts applied to other charges\n\n### Step 4: Propose the design\n\nPresent a structured proposal:\n\n```\n## Dynamic Pricing Design\n\n### Prerequisites\n- [ ] Custom fields to create:\n | Object | Field Name | Type | Description | Example Values |\n |--------|-----------|------|-------------|----------------|\n | Account | Region__c | String | Customer region | US, EU, APAC |\n\n- [ ] Context attributes to create: [list new attributes needed]\n\n### Context Attributes\n| Attribute | Schema | Type | Mapped Object.Field | Valid Values |\n|-----------|--------|------|---------------------|--------------|\n| Region | location | STRING | Account.Region__c | US, EU, APAC |\n| CommitmentType | custom | STRING | Subscription.CommitmentType__c | on-demand, reserved |\n\n### Product\n- Name: ...\n- Category: base | add-on\n- Dates: startDate → endDate\n\n### Plan\n- Name: ...\n- Currencies: [USD, ...]\n\n### Charge\n- Name: ...\n- Model: per_unit\n- Type: recurring\n- Bill cycle: default_from_customer / monthly / in_advance\n- Trigger: contract_effective\n- End date condition: subscription_end\n- Unit of measure: (if applicable)\n- Default pricing: $X.XX (applies when no rate card matches)\n\n### Rate Card\nInclude an `Effective From` column only when pricing is time-varying. Omit it (or show \"now\") when all prices are effective immediately.\n\n| Region | CommitmentType | Price (USD) | Effective From |\n|--------|---------------|-------------|----------------|\n| US | on-demand | $10.00 | now |\n| US | reserved | $7.00 | now |\n| EU | on-demand | $8.00 | now |\n| EU | reserved | $5.50 | now |\n\n### Pricing Timeline (only if effective dating is used)\nShow scheduled price changes as separate rows for the same attribute combination. The system preserves the earlier price as bounded history automatically — you only supply the new \"effective from\" date.\n\n| Region | CommitmentType | Price (USD) | Effective From |\n|--------|---------------|-------------|----------------|\n| US | on-demand | $10.00 | now (implicit) |\n| US | on-demand | $12.00 | 2026-04-01T00:00:00Z |\n\nResulting effective windows after the system merges:\n- US / on-demand → $10.00 for `[now, 2026-03-31T23:59:59]`\n- US / on-demand → $12.00 for `>= 2026-04-01T00:00:00Z`\n\n### Rate Card Operators\n- Region: == (exact match)\n- CommitmentType: == (exact match)\n- EffectiveDate: >= (reserved attribute; only `>=` is valid — marks the effective-from instant)\n\n### Constraints\n- [any edge cases, limitations, or decisions to confirm]\n```\n\n### Step 5: Confirm with user\n\nUse `AskUserQuestion` to present the design summary and ask for explicit approval before any build work begins. The question must offer at least these options:\n\n- **Approve — proceed to build** (confirm the design is correct and ready to execute)\n- **Revise** (user wants to change something; loop back to update the design)\n- **Cancel** (stop without building)\n\n**If the user approves:** tell the user to run `/zuora-dynamic-pricing-build` with the approved design as input to execute it.\n\n**If the user does not approve:** do NOT proceed. Ask what needs to change and re-present an updated design for approval.\n\nDo not call any write/mutating MCP tools (product, plan, charge, custom field creation) in this skill — those belong in the build skill.\n\n## Key constraints to surface in design\n\n- `productRatePlanId` cannot be changed after charge creation\n- Tiered pricing: ranges must not overlap; last tier omits `upTo` (unbounded) — EXCEPT `tiered_overage` where ALL tiers require `upTo`\n- Rate card operators: `==`, `>`, `>=`, `<`, `<=`, `between`, `between-inclusive`, `matches` (regex). NOT supported: `!=`\n- For `between`/`between-inclusive`, value is an array: `[lower, upper]`\n- Attribute types: `String`, `Integer`, `Double` (NOT Decimal), `Boolean`, `Date`, `Datetime`\n- Usage charges must NOT include `billCycle.timing`; recurring/one_time SHOULD include it (`in_advance` or `in_arrears`)\n- First matching rate card wins; if no rate card matches, default pricing applies\n- Mapped fields must exist before attribute creation (standard fields already exist; custom fields must be created first)\n- Consolidate pricing variations into rate cards on a single charge — don't create separate products for each price point\n- **Effective dating**: `EffectiveDate` is a reserved attribute (type `Datetime`) — do not map it to an object field or create a custom field for it\n- `EffectiveDate` accepts only the `>=` operator (marks the effective-from instant); any other operator is rejected\n- `EffectiveDate` values must be ISO-8601 with a zone offset (e.g., `2026-04-01T00:00:00Z`); a bare local datetime is rejected\n- Omitting `EffectiveDate` on a row means \"effective from now\"; a future date schedules the change while preserving the prior price as bounded history — you do not supply the end date, the system computes it\n- Two rate card rows with the same business attributes AND the same effective date are a duplicate and will be rejected\n- For dynamic pricing updates, re-submitting a row whose price equals the price already in effect at its effective date is a no-op and is dropped (does not grow the rate card)\n"
}SHA-256: 701a088034e20ff0bdde5edfab8e1ae9bdb5ad2e6ac17af320caff2505baa8b3