Quote and create from natural language

Updated May 21, 20263 min read

A user describes an order in plain English. The agent resolves the tenant + merchant, gets carrier rate quotes, creates a draft shipment with the chosen rate, and confirms.

This is the canonical "I want to ship this thing" flow — the path from user intent to a booked shipment in the fewest tool calls.

When to use

  • Internal ops copilot: ad-hoc shipments without going through the Dashboard.
  • Order-management agent: when an order arrives via email or chat and needs a manual shipment created.
  • Customer-facing storefront agent (with tight guardrails) — quote a delivery option without going to a checkout page.

Tool sequence

get_accessible_tenants         (which tenant?)
       │
       ▼
get_merchants                  (which merchant within the tenant?)
       │
       ▼
get_shipping_rates             (what are the carrier options + costs?)
       │
       ▼
   user picks a rate
       │
       ▼
create_shipment(draft=true)    (save the chosen rate as a draft)
       │
       ▼
confirm_shipment               (book the carrier)

Example agent prompt

"Ship 2 boxes from our Dubai warehouse to Sara at 25 Maple Street, Riyadh, postcode 11564. COD AED 350. What are my options?"

The agent narrates rate options, the user picks one, and the agent books it.

Walkthrough

Step 1 — resolve tenant and merchant

get_accessible_tenants()
get_merchants(tenantId="…")

If the user's prompt mentioned a brand or merchant name, match it against get_merchants. If the tenant is ambiguous, the agent should ask before proceeding — never guess.

Step 2 — get rate quotes

get_shipping_rates(
  tenantId="…",
  shipment={
    "merchant": "…",
    "pickup": { "location_id": "DXB-WH-01" },
    "dropoff": {
      "address1": "25 Maple Street",
      "city": "Riyadh",
      "country": "SA",
      "postcode": "11564",
      "contact_name": "Sara",
      "contact_phone": "…"
    },
    "parcels": [
      { "quantity": 2, "weight": 1.5 }
    ],
    "payment": {
      "currency": "AED",
      "payment_on_delivery": 350
    }
  }
)

Returns eligible carrier-account options with their estimated cost and service-level info. The agent narrates the options ("DHL — AED 28, 2-day; Aramex — AED 22, 3-day; …") and waits for the user to pick.

Step 3 — create as a draft

Once the user picks (or the agent picks based on a rule like "cheapest" or "fastest"), create as a draft. Unlike get_shipping_rates, create_shipment takes the shipment fields flat at the top level — not wrapped in a shipment object:

create_shipment(
  tenantId="…",
  draft=true,
  merchant="…",
  references={ "partner_shipment_reference": "…" },
  payment={ "currency": "AED", "payment_on_delivery": 350 },
  pickup={ "location_id": "DXB-WH-01" },
  dropoff={
    "address1": "25 Maple Street",
    "city": "Riyadh",
    "country": "SA",
    "postcode": "11564",
    "contact_name": "Sara",
    "contact_phone": "…"
  },
  items=[ … ],
  parcels=[ { "quantity": 2, "weight": 1.5 } ],
  carrier_account={ "id": "<chosen account>", "name": "<chosen service>" }
)

Required fields per the input schema are tenantId, references, payment, pickup, dropoff, and items. draft=true lets the agent edit before locking in.

Step 4 — confirm

confirm_shipment(
  tenantId="…",
  shipment_id="<id from step 3>"
)

The carrier is booked. The response includes the tracking number and the label URL.

Confirm before action

This pattern spends real money — every confirmed shipment incurs carrier fees. In any agent that books on behalf of a non-trusted user, require an explicit confirmation step between rates and create_shipment, and between create_shipment and confirm_shipment.

Variations

  • Skip the draft — pass draft=false (or omit the param) on create_shipment and skip confirm_shipment entirely. Simpler, but you lose the draft-edit window.
  • Multi-merchant batch — for an OMS that creates shipments across many merchants, loop steps 3 and 4 per merchant. Resolve the tenant once, the merchants once, then iterate.
  • Quote-only mode — stop after step 2. The agent just narrates rate options for a human to act on. Useful when MCP is exposed to customer-facing agents that shouldn't book directly.

Pitfalls

  • Address validation. If the dropoff address is malformed, get_shipping_rates returns errors per carrier, not a global reject. The agent should narrate the error and ask the user to fix the address before retrying.
  • COD currency mismatch. payment.currency and payment.payment_on_delivery must be coherent — the agent shouldn't infer currency from the country.
  • Custom attributes. If the merchant routes via custom-attribute rules (get_custom_attributes), the agent must collect those values before creating, or risk a routing fallback.