Designing a Hierarchical Planner for E-commerce Logistics Automation

Written by

in

# Designing a Hierarchical Planner for E-commerce Logistics Automation

![Order information chatbot with verification resolving a customer logistics inquiry](https://www.onlinecloud.dev/assets/chatbot-order-info-5GR50Zbf.jpg)

> A Principal Engineer’s field notes on turning order fulfillment into a swarm of bounded, parallel, backtrackable agents.

Every e-commerce team that has tried to “automate shipping” eventually hits the same wall: fulfillment looks like a single operation from the outside and behaves like a distributed system underneath. The wall is not a model limitation. It is an architecture problem. This post is the design I reach for when a logistics workflow is too wide, too exception-prone, and too irreversible for one agent, one prompt, or one linear chain — a hierarchical planner that decomposes each shipment request into parallel worker tasks, wired to ShipStation, inventory, and carrier systems through Model Context Protocol (MCP), with agentic backtracking as its immune system.

## 1. The Complexity of Order Fulfillment Swarms

Ask any operator what happens when an order drops and the honest answer is a graph, not a line. A four-line-item order fans out into per-SKU inventory checks across multiple warehouses, packaging and carrier-feasibility rules (hazmat, lithium, dimensional weight), service-level promises, split-shipment decisions, label purchasing, pickup scheduling, tracking registration, and customer notification. Every edge of that graph has a failure mode: a SKU goes out of stock mid-reservation, a carrier delays a scan, an address fails validation, a box gets voided after the label was bought.

Three properties make fulfillment fundamentally a *swarm* problem rather than a single-agent problem:

– **Parallelism is structural, not optional.** Line items destined for different fulfillment nodes are independent. Serializing them because one agent holds the whole transcript costs hours per order and makes latency scale with line count.
– **Context economy is unforgiving.** A single agent running an entire fulfillment flow re-reads its own history at every stage and eventually exceeds the context window or the cost ceiling. Each worker should see only the context its step needs.
– **Blast radius is real.** Fulfillment ends in irreversible, externally visible side effects — money collected, labels purchased, packages released to carriers. A hallucinated tool call in a monolithic agent *is* the production incident. In a swarm, a worker’s failure is contained before it reaches a system of record.

The engineering question is not *whether* to decompose. It is how to decompose without drowning the orchestration layer in coordination overhead — which is exactly what a planner-worker topology solves.

## 2. Planner-Worker Architecture: Decomposing a Shipment Request into Parallel Worker Tasks

The pattern is borrowed from well-run engineering orgs: a lead decomposes the objective, delegates to specialists, and reconciles the results. For logistics, the *planner agent* receives a shipment request and produces a **task graph — not a script**. The graph is a DAG in which every node is a narrow, typed unit of work with explicit dependencies, and independent branches are marked fan-out.

For a typical order, the planner emits something like this:

– `reserve_inventory(sku, qty)` — one worker per SKU per candidate fulfillment node, all dispatched in parallel. This is the widest fan-out in the system and the most failure-prone, which is deliberate: we want inventory to fail *early and cheaply*, before any money or label is committed.
– `plan_shipment_split(lines, node_availability)` — a deterministic allocator (with a rules layer, not free-form reasoning) decides which lines ship from which node and whether the order splits.
– `rate_shop(packages, nodes, carriers)` — workers query carriers in parallel for service/price/Eta candidates.
– `purchase_labels(packages, carrier_selection)` — idempotent, gated behind a human or policy checkpoint, because it is an irreversible spend.
– `schedule_pickup` and `register_tracking` — post-release side effects that fire only after label purchase succeeds.
– `notify_customer(plan_result)` — terminal, and only ever runs against the reconciled output of the graph, never against a mid-flight guess.

Two contracts keep this from degenerating into chaos. First, every worker has **typed inputs and outputs**: the reservation worker returns a structured `ReservationResult` with availability, ETA, and substitute candidates — not prose. Second, every task inherits a **plan ID** from the planner, so fan-out, join, and backtrack events are traceable to the parent request. State lives in a durable store, not in the planner’s context, so a worker can run for seconds while the planner waits cheaply.

The planner’s real job is **fan-in**. It does not execute shipping logic; it watches the graph, joins results at dependency boundaries, and — the part that matters most — it is the only agent allowed to *revise the plan* when a worker fails. That separation is what makes Section 5 possible.

## 3. Logistics Tooling: Bridging ShipStation, Inventory DBs, and Carrier APIs via MCP

A planner can decompose all it wants; the swarm still needs a steering layer into the systems that actually move boxes. In practice that means three integration surfaces: **ShipStation** for order management and shipping operations, **inventory databases** (Postgres, Oracle, or a WMS) for availability truth, and **carrier APIs** (UPS, FedEx, USPS, regional carriers) for rates, labels, and tracking. The Model Context Protocol is the contract that makes those surfaces typed, auditable, and model-agnostic.

We expose each system as a set of *verb-shaped* MCP tools with strict JSON Schemas and structured error semantics:

– **ShipStation surface:** `create_order`, `get_order`, `hold_shipment`, `purchase_label` (idempotency-keyed), `void_label`, `get_carrier_services`.
– **Inventory surface:** `check_stock(sku, node)`, `reserve_stock`, `release_reservation`, `get_restock_eta`, `get_substitutes`.
– **Carrier surface:** `rate_shop(package, origin, destination)`, `schedule_pickup`, `track_package`, `get_delivery_estimates`.

Three design rules keep this layer production-safe. **Idempotency everywhere a side effect can repeat**: `purchase_label` and `reserve_stock` carry idempotency keys, so agentic retries and backtrack compensation can never double-spend or double-hold. **Row-level access at the connector**: a worker agent queries inventory through a bridge constrained to the SKUs and nodes its task authorized — the model cannot widen the lookup by phrasing, because the schema has no knob that widens it. **Everything logged**: every MCP invocation from every worker is an auditable event with timestamps and the parent plan ID, so a misrouted shipment at 2 a.m. is replayable as a sequence of typed calls, not a mystery transcript.

The payoff of doing this through MCP rather than one-off function calls is that the *schema is the asset*. The same server surfaces run under Claude, GPT-4-class models, or open-weights deployments in the merchant’s VPC — and when the next model generation ships, you swap the model, not the plumbing. The planner reasons; the MCP layer executes; humans audit.

## 4. Decision Framework: Hierarchical vs. Sequential Reasoning in Logistics Swarms

The honest question every logistics team asks once they see the task graph is: do I actually need a hierarchy, or is a sequential chain enough? The answer depends on where the workflow’s *width* and *exception density* live.

A **sequential workflow** — `verify → reserve → box → label → release → notify` — is the correct spine for a single-SKU, single-node, happy-path shipment. It is deterministic, reviewable in a diagram, and cheap: no coordination hop, no planner context, one typed handoff per stage. Its failure mode is that it has no branching vocabulary. The moment one line item goes out of stock, a second node enters the picture, or a carrier misses a scan, the “one true path” either serializes every alternative or compounds errors — a confident wrong input from stage two becomes stage three’s starting assumption.

A **hierarchical swarm** earns its extra hop precisely where logistics is hardest: heterogeneous stages with independent failure modes that must run in parallel, and failures that require *replanning rather than retrying*. When the reservation worker for SKU A fails at node 1 while SKU B’s worker has already succeeded, a sequential chain must unwind and restart. A hierarchical planner simply prunes the failed subtree, dispatches alternative tasks, and lets the completed work stand. Hierarchy also buys context isolation — the inventory worker never sees customer payment history — and a natural place for the strongest, priciest model: decomposition and adjudication, where a bad decision poisons everything downstream.

Our rule of thumb, applied per branch rather than per system: **serialize what is truly dependent and deterministic; fan out what is independent or likely to fail.** A fixed pipeline of dependent steps gets sequential stages with reflection checkpoints between them. Wide, conditional, exception-prone work — inventory across nodes, rate shopping, exception handling — gets hierarchical fan-out. Most production fulfillment systems end up as a hybrid: a sequential spine with a hierarchical planner owning the wide and risky branches. Let the process diagram pick the topology; do not let framework marketing pick it.

## 5. Error Handling: Managing ‘Out of Stock’ and Carrier Delays with Agentic Backtrack

Logistics is exception-dense, so the error path is not an edge case — it is the design center. We handle exceptions on a ladder: deterministic rules first, **agentic backtrack** where the recovery decision itself requires reasoning.

Agentic backtrack means this: when a worker returns a *structured failure* (not prose, a machine-readable error code with context), the planner prunes the failed subtree of the task graph and generates a **revised plan** from the current state — never a full restart, and never an unexamined retry. Completed, unaffected work stays committed. Compensation tasks are first-class nodes in the new plan.

Consider **out of stock**. The `reserve_inventory` worker for SKU A returns `OUT_OF_STOCK` with `restock_eta` and substitute candidates. The planner does not just retry. It evaluates the recovery tree: reserve at the secondary node (which may introduce a split shipment), substitute if policy and customer consent allow, backorder the line with a communicated ETA, or cancel the line and issue a refund. Each branch has a cost and a policy gate, and the planner picks by policy — escalating to a human checkpoint only when the branch is irreversible or exceeds a spend threshold. Meanwhile, SKU B’s reservation stands, and the healthy branches proceed: the order may ship partially rather than wait for the whole graph. If a later failure voids a planned box, a `release_reservation` or `void_label` compensation runs with the same idempotency discipline as the original action.

Carrier delays exercise the same machinery on the outbound side. A `track_package` worker observes a missed scan or a delay event; the planner treats it as a trigger to backtrack on the *notification* subtree: recompute ETA from fresh carrier data, decide whether the delay breaches the SLA, push a proactive update to the customer before they open a ticket, and — if the breach is material — route a credit-or-escalation decision to a human or a policy rule. The difference between this and a naive retry loop is that the plan *changes*: the system stops promising the old ETA and starts managing the new one.

Three guardrails keep backtrack from becoming a cost runaway: a **bounded revision budget** (a plan may backtrack at most N times before a human owns it), **structured errors with machine-readable codes** so the planner branches on semantics rather than parsing text, and **full replayability** — every prune, compensation, and revision is an audited event under the parent plan ID.

## 6. Case Study: Deflecting 50% of Logistics-Related Tickets with Automated Agent Swarms

The reference deployment is the **Order Information Chatbot with Verification** OnlineCloud shipped for a multi-channel merchant — the agent swarm this post describes, pointed at the most expensive intent in e-commerce support: *”Where is my order?”* Order-status, delay, and exception conversations were the merchant’s largest and least satisfying queue, and each one forced an agent to context-switch between the order management system and carrier portals.

The swarm changed both directions of the ticket flow. **Outbound**, fulfillment monitoring agents watched ShipStation, inventory, and carrier feeds through the MCP surfaces above; when the planner’s backtrack machinery caught an out-of-stock line or a carrier delay, proactive notifications reached the customer with a corrected ETA *before* they felt the need to ask. **Inbound**, a conversational agent resolved the questions that still arrived — verified by email/OTP so account data never leaks, then answering from live tool results: current status, latest tracking scan, ETA, and a return link when the item qualifies.

The results, measured on the merchant’s own dashboards:

– **Roughly 50% of logistics-related tickets deflected** by the automated swarm — and order-status tickets specifically were cut by more than half within the first week, before flows were even tuned.
– **Median resolution inside the chat landed well under two minutes**, against six to eight minutes of average human handle time for the same intent.
– **CSAT stayed flat to positive.** Customers trusted answers that were faster and pulled from their real order — not synthesized from a training corpus.
– **Exception tickets shrank on their own.** Proactive delay and backorder messaging pre-empted a meaningful share of inbound asks, which is why the deflection number is larger than the chatbot’s conversation volume alone.

The lesson generalizes: in logistics automation, deflection is not only about answering faster **inbound** — it is about acting earlier **outbound**. A planner that backtracks on a carrier delay and tells the customer before they ask converts what would have been a support ticket into a background event. That is the difference between a chatbot bolted onto a queue and an agent swarm that owns the fulfillment loop end to end.

—

### Ready to wire agents into your logistics stack?

OnlineCloud is a US-based engineering studio specializing in agentic AI and Model Context Protocol — MCP-native swarms that plug into ShipStation, your inventory databases, and carrier APIs with typed tools, audit trails, and human checkpoints where they matter. Senior engineers only, no offshore handoffs, evaluated and observable systems shipped to production in 6–10 weeks, not quarters. [Contact the OnlineCloud team](https://www.onlinecloud.dev/) or email **contact@onlinecloud.dev** for a free initial consultation — we respond within 24 hours.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *