Advanced cartonization guide¶
This guide walks 3rd-party WMS integrators through enabling advanced (dynamic, sequence-synchronized) cartonization — where a packaging machine produces the right container for each SKU in real-time lockstep with the pick sequence. It covers the framing, the master-data you supply, the coupling modes (strict 1:1 vs buffered), worked scenarios end-to-end including the apple/bacon/orange motivating example, cancellation behavior, failure flows, and the contract surface.
This is distinct from basic (static) cartonization — where your WMS pre-decides which Order lines go in which cartons at dispatch time. Basic cartonization is Pattern C in the label printing guide and uses the cartonization[] field on ShipperReleasedPayload. Advanced cartonization needs a different contract surface and is only relevant if your operation has a packaging machine that produces containers just-in-time.
TL;DR¶
Advanced cartonization is a three-way concern split. You (the planner) own per-SKU packaging requirement master data. Karajan (FG.AI’s optimizer-compiler, optional) owns sequence-decision optimization. WES owns sequenced production execution — driving the cartonization machine, coordinating with pickers, handling jams.
You enable it by exposing one lookup endpoint.
GET /wes/v1/master-data/packaging-requirement?tenant_id=...&site_id=...&sku_id=...&qty=...returns the container spec for a (SKU, qty) tuple. That’s the only new mandatory endpoint.Container spec is opaque to WES. You return whatever JSON your cartonization-machine vendor adapter understands. WES never parses it.
One operational parameter controls everything:
buffer_depth.0= strict 1:1 sync (perishables, cold-chain).1..K= produce K containers ahead (steady-state ops). Tenant configures per Scheme instance.Cancellation that arrives mid-PRODUCING orphans the container. The cancellation ack carries the orphan info; you can void carrier tracking on the cartonizer-issued label (if any). The container itself becomes a disposal decision at WES’s RecoveryStation.
Karajan is optional. Without Karajan, WES uses FIFO baseline ordering; with Karajan, an optimal sequence is computed. Either way the integration shape is the same.
You don’t need to know about machines. Vendor adapters (Quadient, CMC, Sealed Air, Loveshaw, Packsize, custom PLC) handle the wire protocol. Your integration is purely with the planner-facing contract.
The framing¶
Three concerns; three owners.
Concern |
Owner |
Why |
|---|---|---|
Per-SKU packaging master data (“apple needs paper bag”) |
You — the planner |
Same lifecycle as SKU dimensions / weight / hazmat-class. Rarely changes; multi-channel reuse. Lives in your WMS master-data system. |
Sequence decision (“pick orange first, then apple, then bacon”) |
Karajan (optional) — FG.AI’s optimizer-compiler |
Sequence is an optimization problem — minimize cartonizer idle, minimize material waste, minimize cross-zone walk. Karajan owns this class of workload. With no Karajan, WES uses FIFO baseline. |
Sequenced production execution |
WES execution plane |
Real-time floor coordination is WES’s core competency. Drives the cartonizer; tracks the queue; handles jams; pauses on cancellation. |
This separation means a tenant can adopt advanced cartonization without forcing them to also adopt Karajan: the WES baseline FIFO path is always available. Karajan-computed optimal sequencing is the premium path.
When advanced cartonization applies¶
Skip this feature if your operation:
Uses generic interchangeable containers (totes, generic cartons) — basic cartonization Pattern C handles this
Has only a single container type per SKU regardless of qty (rare; usually qty drives box size)
Doesn’t have a packaging machine — operators wrap by hand at PackStation
Adopt it if your operation:
Has a cartonization machine that produces containers on demand (Quadient X, CMC CartonWrap, Sealed Air Korrvu, Loveshaw, Packsize EM-7, etc.) OR has a multi-station produce-and-apply setup
Has SKU-specific packaging requirements (cold-pack vs ambient, fragile vs flat, branded vs generic, sustainable right-size vs box-of-shame)
Cares about cartonizer↔picker throughput coordination — material waste, idle time, or operator queueing matters
Is operating in fresh/grocery, pharma, sustainable-packaging, gift-wrap, or other VAS-heavy verticals
If you’re not sure: WES architects can help you scope. Talk to your FG.AI contact before implementing.
Step 1 — Define your packaging-requirement master data¶
Per-SKU container-spec selection rules live in WMS master data. Each row says: for this SKU, when the observed pick quantity falls in this range, use this container spec.
Example rows (your WMS internal model):
SKU |
qty_min |
qty_max |
container_spec |
priority |
|---|---|---|---|---|
|
1 |
3 |
|
100 |
|
4 |
10 |
|
100 |
|
11 |
999999 |
|
100 |
|
1 |
12 |
|
100 |
|
1 |
999999 |
|
100 |
|
1 |
999999 |
|
500 |
The container_spec field is whatever JSON your cartonization-machine vendor adapter understands. WES never parses it. The format is between you and your adapter team.
The priority column resolves the multi-rule case: a temporary holiday packaging rule (priority 500) overrides the default (priority 100) while it’s active. Higher number wins.
Master-data lookup endpoint (mandatory)¶
Expose this endpoint at your planner:
GET /wes/v1/master-data/packaging-requirement
?tenant_id=frn:wms:intl/tenant:acme
&site_id=frn:wms:intl/tenant:acme:site/tokyo
&sku_id=SKU-APPLE
&qty=5
Response:
sku_id: "SKU-APPLE"
qty_bucket_min: 4
qty_bucket_max: 10
container_spec:
type: paper-bag
size: medium
color: kraft
priority: 100
WES calls this at PackagingSequenceArtifact.advance() time — when the next sequence position is being prepared for production. WES caches results locally in its Static Data table; consecutive calls for the same (tenant, site, sku, qty) hit the cache.
Cache freshness: WES refreshes on TTL (default 1 hour) until a master-data.packaging-requirement-changed.v1 event surface lands in a future wes-contract version (currently v1.5 candidate). For now, plan for ~1-hour propagation delay on rule changes. For urgent changes (recall, packaging error), coordinate manually with the executor team to flush the cache.
Endpoint latency target: <100ms at p99. WES calls this on the hot path of every sequence advance. Slow lookups are the most common reason for cartonizer underflow stalls.
404 handling: if you have no rule for a (SKU, qty), return HTTP 404. WES will pause the sequence position with PRODUCTION_FAILED state and emit a supervisor escalation. Don’t fail by returning a default spec — defaults mask master-data gaps.
Step 2 — Tenant operational config¶
The tenant’s WES admin configures one or more SequencedCartonizationScheme instances at Site onboarding. Each instance has:
Setting |
Values |
Decision criteria |
|---|---|---|
|
|
|
|
|
|
|
List of cartonizer FRNs |
Which physical machines this Scheme instance binds to. Multi-cartonizer (different container types) is supported. |
You don’t set these — the tenant does. But you should communicate to your tenants which mode fits their operation. As a general guide:
Grocery fresh / cold-chain / pharma controlled-substances →
buffer_depth=0,cartonization_spec_timing=lazySteady-state ecom mixed-fragility →
buffer_depth=3,cartonization_spec_timing=eagerHigh-throughput peak season →
buffer_depth=5,cartonization_spec_timing=eager
A single Site can run multiple Scheme instances in parallel (e.g., one for fresh, one for ambient) — config is per-instance, not per-Site.
Worked example 1 — The apple/bacon/orange scenario (strict 1:1)¶
This is the user-provided motivating example. Pick sequence: [orange, apple, bacon]. Cartonizer must produce in matching sequence: [bamboo-blanket, paper-bag, plastic-box].
Setup¶
One picker; one cartonization machine (the cartonizer can produce all three container types — say a Quadient X with paper-bag + plastic-box + bamboo modules)
buffer_depth = 0(strict 1:1) — these are fresh products; perishability concerns mean no advance productioncartonization_spec_timing = lazy— confirm qty before deciding spec (defensive against short-pick on fresh)
Sequence¶
t=0 Picker walks to orange bin
WES → planner: GET /master-data/packaging-requirement?sku=ORANGE&qty=1
Planner → WES: container_spec={"type":"bamboo-blanket","size":"small"}
PackagingSequenceArtifact: position 1 transitions ENQUEUED → PRODUCING
Cartonizer adapter pushes spec to machine PLC
Machine starts producing bamboo blanket
t=15s Picker arrives at orange bin; scans; picks 1 orange
WES: pick observed; voice "deliver to cartonizer output"
Cartonizer has bamboo blanket ready (PRODUCING → READY_AT_OUTPUT)
Picker walks to cartonizer; places orange in bamboo blanket
WES → cartonizer: notifyConsumed(1)
PackagingSequenceArtifact position 1: READY_AT_OUTPUT → PICKED_INTO
t=30s Position 2 becomes eligible (buffer_depth=0 + position 1 PICKED_INTO)
Picker walks to apple bin
WES → planner: GET /master-data/packaging-requirement?sku=APPLE&qty=2
Planner → WES: container_spec={"type":"paper-bag","size":"small"}
Cartonizer starts producing paper bag
t=45s Picker arrives at apple bin; scans; picks 2 apples
Paper bag READY_AT_OUTPUT
Picker delivers 2 apples to paper bag
Position 2: PICKED_INTO
t=60s Position 3 eligible
Picker walks to bacon bin
WES → planner: GET /master-data/packaging-requirement?sku=BACON&qty=3
Planner → WES: container_spec={"type":"plastic-box","subtype":"cold-vac"}
Cartonizer starts producing plastic box (cold-vac variant)
t=80s Picker arrives at bacon bin; scans; picks 3 bacon packs
Plastic box READY_AT_OUTPUT (with cold-vac seal applied)
Picker delivers 3 bacon packs to plastic box
Position 3: PICKED_INTO
t=85s All positions DELIVERED → Scheme instance goal achieved
Note: there’s a 15-second walk window between positions where the cartonizer is idle. That’s the cost of strict 1:1. For perishables it’s acceptable; for high-throughput ambient ops you’d use buffered mode (worked example 2).
What you (the planner) see¶
Three calls to
GET /master-data/packaging-requirement— one per positionThree
LABEL_PRINT_REQUESTEDobservations if labels are being applied (see Pattern with-label below)Several
PICKER_COMMITTED_TO_SEQUENCEobservations (one per pick)Final shift-summary confirmation when the Scheme instance completes
You don’t see the cartonizer state — that’s WES-internal. You see the touchpoints where the contract requires action.
Worked example 2 — Buffered ecom (mixed-fragility)¶
Picker is handling a steady stream of small ecom Orders. SKUs vary: some need padded mailers, some need small corrugated, some need cold-insulated. buffer_depth=3 means the cartonizer produces up to 3 containers ahead.
Sequence¶
t=0 PackagingSequenceArtifact has positions 1..N ENQUEUED
Cartonizer starts producing position 1 (padded mailer)
Immediately: cartonizer starts position 2 (small corrugated)
Immediately: cartonizer starts position 3 (padded mailer)
Buffer is full at 3 in-flight productions
t=5s Position 1 READY_AT_OUTPUT
Picker is en route from position 0 pick zone; not yet here
Buffer count: 3 (still 3 in-flight, position 1 ready means
position 4 NOT yet eligible — needs position 1 to PICKED_INTO)
t=12s Picker arrives, places picked SKU in position 1 container
Position 1 → PICKED_INTO
Now buffer count: 2 in-flight; position 4 becomes eligible
Cartonizer starts producing position 4
Position 2 also READY_AT_OUTPUT (was already produced)
Position 4 = padded mailer
t=14s Picker walks to next pick zone
Position 2 ready and waiting; will be consumed when picker arrives
Position 4 mid-production
...
The buffer absorbs the picker’s walk time between zones. Cartonizer rarely idles; picker rarely waits. Throughput maximized.
What you (the planner) see¶
Master-data lookups concentrated at sequence start (3 lookups for the initial 3 positions); thereafter one lookup per advance as buffer slot frees
Higher overall throughput than strict 1:1 (visible in shift-summary)
Same observation events; sequence positions are just produced earlier relative to pick events
Worked example 3 — Multi-cartonizer (different container types)¶
Apple → paper bag (Cartonizer A, Quadient). Bacon → plastic box (Cartonizer B, cold-pack-station with PLC). Orange → bamboo blanket (Cartonizer C, custom artisan station).
Three physical machines, each with its own SubsystemArtifact instance and adapter. Each declares its capabilities:
Cartonizer A (Quadient X):
declared_capabilities:
- container-type-paper-bag-small
- container-type-paper-bag-medium
- container-type-corrugated-small
- cartonizer-buffer-min-5
- cartonizer-with-label
Cartonizer B (Cold-pack station):
declared_capabilities:
- container-type-cold-insulated
- container-type-plastic-box
- cartonizer-strict-sync
- cartonizer-buffer-min-1
Cartonizer C (Bamboo artisan station):
declared_capabilities:
- container-type-bamboo-blanket
- cartonizer-strict-sync
WES’s PackagingSequenceArtifact.advance() looks up the next position’s spec and matches against capabilities to route to the right machine. The sequence position is global — position 1 goes to Cartonizer C, position 2 goes to Cartonizer A, position 3 goes to Cartonizer B. Picker walks to whichever machine’s output produced their next container.
What you (the planner) see¶
Same contract surface. WES handles the routing internally. Your master-data lookup is identical; you don’t need to know which machine produces what (that’s per-tenant configuration).
The one operational consideration: when configuring this Site, the tenant needs each cartonizer’s capabilities declared correctly. If SKU-APPLE maps to a paper-bag spec but no cartonizer declares container-type-paper-bag-small, the sequence position will fail with PRODUCTION_FAILED and supervisor escalation. Coordinate with the WES ops team to verify capability declarations match your master data.
Worked example 4 — Multi-picker (scan-at-induction)¶
Five operators are picking simultaneously from different aisles, all delivering to a single cartonization line. Physical arrival order is unpredictable — depends on walk distance, pick complexity, etc.
Resolution: scan-at-induction. Before walking to pick, each operator scans the SKU barcode at an induction-point scanner. The scan commits them to a sequence position based on scan-arrival order. The cartonizer enqueues productions in scan-arrival order.
Sequence¶
t=0 Operator 1 scans SKU-APPLE at induction
WES emits PICKER_COMMITTED_TO_SEQUENCE event:
{ picker_id: op-1, sequence_position: 1, sku_id: SKU-APPLE }
Position 1 ENQUEUED with picker_id=op-1
WES looks up packaging-requirement for SKU-APPLE
Cartonizer starts producing paper bag
t=2s Operator 2 scans SKU-ORANGE at induction
WES emits PICKER_COMMITTED_TO_SEQUENCE:
{ picker_id: op-2, sequence_position: 2, sku_id: SKU-ORANGE }
Position 2 ENQUEUED, capabilities-matched to bamboo cartonizer
Bamboo cartonizer starts producing
t=4s Operator 3 scans SKU-BACON at induction
Position 3 ENQUEUED, cold-pack cartonizer starts producing
t=20s Operator 1 returns from aisle with apple
Cartonizer output for position 1 (paper bag) is ready
Operator 1's voice prompt: "deliver to cartonizer A output"
Operator 1 places apple in paper bag → position 1 PICKED_INTO
...
What you (the planner) see¶
PICKER_COMMITTED_TO_SEQUENCEobservations as scans occurOne master-data lookup per scan (the moment the position enters the sequence)
Multiple cartonizers running in parallel, each producing for their committed position
The PICKER_COMMITTED_TO_SEQUENCE event is purely informational for the planner — you don’t need to ack it or take action. It’s useful for live floor monitoring (which picker is committed to what), debugging sequence stalls, and post-shift productivity analysis.
Worked example 5 — Cartonizer-with-label (label printed at production)¶
Some cartonization machines (Quadient X, CMC CartonWrap, Sealed Air Korrvu) integrate label printing into the production line. The label is printed and applied as part of producing the container — there’s no separate label-application step downstream.
This is a fourth print_mode for labels: at-cartonization (see label printing guide). The flow:
Setup¶
Cartonizer declares
cartonizer-with-labelcapabilityShipperReleasedPayload includes
label_bindings: [{print_mode: at-cartonization, bound_to_type: container, ...}]
Sequence¶
t=0 PackagingSequenceArtifact position 1 about to advance
WES looks up packaging-requirement → container_spec for paper bag
Before enqueueing to cartonizer, WES needs the label.
WES → planner: POST /wes/v1/labels/issue with context:
{ order_id, container_id (to-be-produced), fulfilled_contents }
Planner → WES: { label_id, external_label_uri,
print_payload_uri }
WES → cartonizer: enqueueContainerSpec(spec, position=1,
label_print_request_uuid=...)
Cartonizer adapter pushes spec + label print payload to machine
Machine produces container WITH LABEL ALREADY APPLIED
t=10s Picker arrives; cartonizer output has paper bag with label affixed
Picker delivers SKU into labeled paper bag
Position 1 PICKED_INTO
What’s different from post-pick label issuance?¶
In Pattern D (post-pick at PackStation), /labels/issue is called at custody time — AFTER the operator has picked into the container. Container contents are known with certainty when the label is allocated.
In cartonizer-with-label, /labels/issue is called BEFORE the pick — at sequence-advance time. Container contents are expected (based on planner-dispatched qty), not yet observed. Short-pick risk: if planner expected 5 apples but operator picks 4, the cartonizer already produced a paper bag with label for “5 apples”; the label is now slightly wrong but the carrier tracking number is still valid.
This is acceptable in most carrier integrations — tracking number is the load-bearing identifier; the package contents declaration is updated at confirmation time. If your carrier requires exact-qty labels (rare), use print_mode=post-pick instead and have label apply downstream of cartonization.
What you (the planner) see¶
LABEL_PRINT_REQUESTEDevent at sequence-advance time (earlier than Pattern D)/labels/issuecalls following each event within millisecondsStandard
IssuedLabelresponse with carrier tracking allocated
Cancellation × sequence interaction¶
When you cancel an Order that has work in flight in a SequencedCartonizationScheme, the executor’s transactional cancellation invariant atomically:
Transitions Order state IN_PROGRESS → CANCELLING
Spawns CompensationTask(s) per ADR-0013
Voids all LabelBindings for the cancelled Order
Transitions any active PackagingSequenceArtifact positions referencing the cancelled Order:
ENQUEUED→CANCELLED(clean cancel; no orphan; cartonizer hasn’t started)PRODUCING→CANCELLEDwith orphan-container outcome (produced container is or will be wasted)READY_AT_OUTPUT→CANCELLEDwith orphan-container outcome (container sits at output, no picker will come for it)PICKED_INTOand beyond → handled by Pattern D in-cart compensation (see label printing guide — the operator at PackStation diverts the cancelled item)
Spawns
orphan-container-dispositionCompensationTasks for any orphaned positions
The cancellation ack envelope from dispatch.cancelled.v1 includes:
cancel_outcome: ACCEPTED
compensation_initiated_for:
- task_id: ...
order_id: ...
compensation_task_id: ...
compensation_type: orphan-container-disposition # if orphaned
voided_label_bindings:
- label_id: ...
voided_reason: ORDER_CANCELLED
bound_to_type: container # cartonizer-issued
# ... carrier tracking info ...
You (the planner) consume voided_label_bindings[] to void carrier tracking. The orphan-container disposition itself is operator-resolved at the executor’s RecoveryStation — disposal, store-for-reuse, or repurpose-for-substitute. The planner doesn’t need to drive that; it’s WES-side workflow.
TOO_LATE interaction: if cancellation arrives after the cartonized container has been delivered (PICKED_INTO and downstream), the cancellation outcome will be TOO_LATE for that binding. Pattern D PackStation in-cart compensation handles it from there. See cancellation guide for the full custody semantics.
Failure flows¶
Jam at the cartonizer¶
Adapter detects a machine fault (jam, paper-out, mechanical issue). PackagingSequenceArtifact.pause() halts sequence advance. Two recovery paths:
Hot resume (jam clears within seconds):
Adapter detects ONLINE; PackagingSequenceArtifact.resume()
If
buffer_depth > 0and there were ready containers, picker continues consuming buffered productions; cartonizer catches upNo planner action needed
Drain + restart (jam doesn’t clear; operator clears manually):
Operator clears jam; cartonizer adapter re-initializes
PackagingSequenceArtifact.reseed(from_position=N) restarts sequence at the failed position
Already-produced buffered containers retain bindings (no re-issuance)
Picker may need to pause briefly during reseed; supervisor decides
Planner observes a gap in production events; no specific action required other than monitoring shift KPIs
Short-pick at position N¶
Picker can’t find the expected qty (e.g., expected 5 apples, bin has 3). Picker reports SHORT_PICK exception (existing flow per Realtime).
If cartonizer-with-label was used and the label was issued for the originally-expected qty, the produced container is technically over-sized but the tracking number is still valid. Operator may deliver short-pick contents anyway (acceptable for most carriers — the package contents declaration updates at confirmation).
If the discrepancy is large enough that the container is unsuitable (e.g., 1 apple in a paper-bag-large), supervisor may decide to substitute or rebuild. In that case the produced container becomes orphan; orphan-container-disposition CompensationTask spawned per ADR-0023 §9.
SKU substitution at position N¶
Planner notifies WES of substitution before pick. Two sub-cases:
Pre-PRODUCING: position state is ENQUEUED; WES cancels the enqueue (
cancelInQueue(N)), re-enqueues with the substitute SKU’s spec. Clean substitution, no material waste.Mid-PRODUCING or post-PRODUCING: produced container is wrong for the substitute SKU. Container becomes orphan; orphan-container-disposition CompensationTask spawned. Substitute SKU enqueued at new sequence position downstream.
To minimize wasted production, substitute as early as possible — ideally at order amendment time, before WES advances to that position. If you frequently substitute, consider increasing buffer_depth=0 to give yourself more substitution headroom (counter-intuitive but: a smaller buffer means less material wasted on substituted-out productions).
Qty mismatch (eager spec timing)¶
Under cartonization_spec_timing=eager, WES decided the spec using planner-expected qty. If observed qty differs:
Observed < expected: container is over-sized; operator delivers anyway in most cases; acceptable
Observed > expected: container may be undersized; pick fails into container; supervisor intervention
If over-/under-sizing is operationally problematic, switch to cartonization_spec_timing=lazy (forces buffer_depth=0). Slower throughput but always-correct spec.
Master-data lookup failure¶
If your /master-data/packaging-requirement endpoint returns 5xx or times out:
WES retries with exponential backoff (3 attempts, ~30s total)
If retries exhaust, the sequence position transitions to PRODUCTION_FAILED with supervisor escalation
Supervisor may manually configure a fallback spec, or pause the sequence until the planner endpoint recovers
Subsequent positions continue if they can be looked up; the failed position stays paused
Defensive pattern: implement aggressive local caching on the WES side (already done — Static Data table). Plan your endpoint for ~99.9% availability; brief outages are absorbed by cache.
If your endpoint returns 404 (no rule for SKU+qty), WES does NOT retry — it treats 404 as definitive. The sequence position transitions to PRODUCTION_FAILED. To prevent this, ensure every active SKU has at least one open-ended catch-all rule (qty_min=1, qty_max=999999) even if it’s just a sensible default.
Common pitfalls¶
1. Container spec format not agreed with the cartonization adapter team¶
The container_spec field is opaque to WES. WES passes it through to the cartonization adapter. If your master-data team’s spec format doesn’t match what the adapter expects, the adapter rejects the spec at push time.
Fix: before going live, exchange a sample spec document with the adapter vendor (e.g., Quadient’s adapter team). Agree on schema. Test end-to-end with a stub spec; verify the machine produces what you expect. This is the single most common cause of advanced cartonization launch failures.
2. Master-data lookup endpoint too slow¶
WES calls /master-data/packaging-requirement on the hot path of every sequence advance. p99 latency >500ms causes cartonizer underflow stalls — pickers wait at the output for containers that haven’t been produced because spec lookup is slow.
Fix: target p99 <100ms. Pre-load all active SKUs into a hot in-memory cache in your master-data service. Don’t query a relational database on every call.
3. Capability declarations missing on cartonizer machines¶
Multi-cartonizer routing depends on each machine declaring its supported container-type-* capabilities. If SKU-APPLE maps to paper-bag-small but no cartonizer declares that capability, the sequence stalls.
Fix: when onboarding a new cartonization machine, audit its declared capabilities. Cross-reference with your master-data spec catalog. Coordinate with the WES ops team to verify.
4. Eager vs lazy timing chosen wrong for the operation¶
eager favors throughput but risks wrong-sized containers on qty discrepancies. lazy is always correct but forces strict 1:1 sync (forfeits buffering benefits).
Defaults that work for most ops:
Ecom + ambient + reliable inventory →
eager+buffer_depth=3Fresh + cold-chain + frequent short-pick →
lazy+buffer_depth=0Pharma / controlled substances →
lazy+buffer_depth=0always
Don’t pick lazy + buffer_depth=3 — they’re incompatible (lazy implies buffer=0).
5. PackagingRequirement rule gaps¶
If a SKU exists in your WMS but has no PackagingRequirement rule, every advance() for that SKU fails with 404. The Order can’t proceed.
Fix: at SKU master-data creation, require a packaging rule before the SKU goes active. Have a default catch-all rule template (e.g., “generic small corrugated, qty 1-999999”) that applies if no specific rule exists. Better: have your SKU lifecycle gate active-status on packaging rule existence.
6. Forgetting to handle PICKER_COMMITTED_TO_SEQUENCE events in multi-picker ops¶
If your monitoring/analytics consumes confirmation.realtime.v1 events for floor visibility, you should handle PICKER_COMMITTED_TO_SEQUENCE. Otherwise multi-picker ops appear to have “ghost” sequence positions from the analytics perspective — productions occurring with no explanation.
Fix: add PICKER_COMMITTED_TO_SEQUENCE to your observation consumer’s event_type whitelist. Use the picker_id + sequence_position fields to attribute downstream events.
7. Orphan container disposition workflow not communicated to operators¶
When containers get orphaned (cancellation mid-PRODUCING, SKU substitution, etc.), they end up at the RecoveryStation with a orphan-container-disposition CompensationTask. Operators need a UI workflow to decide: discard / store-for-reuse / repurpose.
Fix: this is WES-side, not your concern directly, but coordinate with the WES ops team during onboarding. Make sure the RecoveryStation operator UI surfaces the disposition options clearly. Track orphan rate as a KPI; high orphan rates indicate operational tuning needed (lower buffer_depth, better substitution timing, etc.).
Endpoint reference¶
GET /wes/v1/master-data/packaging-requirement¶
Direction: Executor → Planner Purpose: Resolve (SKU, qty) → container_spec at sequence advance time Required: Yes if your tenant uses advanced cartonization Latency target: p99 <100ms
Query parameters:
tenant_id (frn, required)
site_id (frn, required)
sku_id (string, required)
qty (number, required; observed or expected per timing mode)
Response (200):
sku_id: string
qty_bucket_min: integer # inclusive lower bound
qty_bucket_max: integer # inclusive upper bound
container_spec: # opaque JSON; vendor adapter parses
...
priority: integer # higher = applied first
Response (404): no rule matches; WES treats as definitive (no retry); sequence position fails.
POST /wes/v1/labels/issue (existing — but called at-cartonization time)¶
When print_mode=at-cartonization is used, the executor calls this endpoint at sequence-advance time (BEFORE the pick) rather than at PackStation custody. Same request/response shape; just earlier timing. See label printing guide for the full endpoint spec.
Event reference¶
confirmation.realtime.v1 with event_type=PICKER_COMMITTED_TO_SEQUENCE¶
Direction: Executor → Planner Purpose: Multi-picker scan-at-induction observation; identifies which picker committed to which sequence position Action required: None (informational); useful for floor monitoring + post-shift analytics
Envelope (additions to standard RealtimeObservation):
event_type: PICKER_COMMITTED_TO_SEQUENCE
context:
picker_id: frn # which operator scanned
sequence_position: int # global position assigned
sku_id: string # SKU about to be picked
scan_location: frn # induction-point FRN
occurred_at: timestamp
Other observation events relevant to cartonization¶
Existing observation events (per label printing guide and Realtime) that fire during cartonization flows:
LABEL_PRINT_REQUESTED— fires at sequence-advance time whenprint_mode=at-cartonization; precedes/labels/issuecall within msCONTAINER_ARRIVED— fires when a produced container reaches the output queue (READY_AT_OUTPUT state transition)SLOT_ATTACHED/SLOT_DETACHED— if AMR-based delivery between cartonizer and pack, slot lifecycle still fires
All carry standard (event_uuid, correlation_id, agent_id, site_id) envelope. Use them for live floor visibility; consumption is optional.
Karajan integration notes¶
Karajan is FG.AI’s optional optimizer-compiler service. With Karajan:
Tenant’s pick-sequence ordering is computed by Karajan’s release plan
The ordering optimizes for cartonizer throughput (minimize idle), material efficiency (minimize wrong-size production), and walker time (minimize cross-zone)
Karajan runs in the cloud; WES execution plane consumes its release plans
Without Karajan:
WES uses FIFO baseline ordering — pick in the order Orders arrive in OrderPool
Always works; never blocks; per ADR-0012 the always-on guarantee
Sub-optimal sequencing (more material waste, more picker idle) but operationally functional
You as the planner don’t need to know whether the tenant has Karajan installed. Your integration is identical either way. If your customer is sensitive to cartonization efficiency (high SKU diversity, expensive packaging materials, throughput-critical), recommend they install Karajan.
FAQ¶
Q: Do I need to implement the lookup endpoint if my tenant uses basic cartonization?
No. Basic cartonization (Pattern C in label printing guide) uses cartonization[] on ShipperReleasedPayload and doesn’t call any new endpoint. Advanced cartonization is a separate integration path.
Q: Can a tenant use both basic and advanced cartonization?
Yes — for different Orders. The decision is per-Order: include cartonization[] in the dispatch payload to use basic (Pattern C); omit it AND have a SequencedCartonizationScheme configured to use advanced. WES picks the path based on dispatch + Scheme configuration.
Q: What if my cartonization machine doesn’t have an existing adapter? You’ll need an adapter implementation. Common vendors (Quadient, CMC, Sealed Air, Loveshaw, Packsize) have or are getting FG.AI adapters; custom PLC machines need a custom adapter. Coordinate with FG.AI partner-engineering. This is a one-time per-vendor cost.
Q: How do I test advanced cartonization without a physical machine?
Use a stub cartonization adapter (wes-adapters-cartonization-stub) that pretends to produce containers with configurable latency. The stub adapter lets you exercise the full master-data lookup → enqueue → READY → consumed cycle without hardware. Coordinate with FG.AI dev-ops for stub setup.
Q: Can I drive the cartonizer’s spec format from a UI in my WMS?
Yes. The container_spec is opaque — you can build whatever UI lets your warehouse engineers define specs. Common pattern: a master-data UI with vendor-specific spec templates per cartonization machine model.
Q: What happens if a cartonizer is offline? The cartonizer’s SubsystemArtifact transitions to OFFLINE state. PackagingSequenceArtifact instances bound to it pause. If multi-cartonizer with another machine declaring the same capability, sequence routes around (degraded throughput). If single-cartonizer or no fallback, sequence pauses entirely.
Q: Can I update PackagingRequirement rules without restarting WES? Yes — WES refreshes the cache on TTL (default 1 hour). For urgent updates, coordinate with WES ops team to flush. Future wes-contract versions will add a master-data-change event so rule updates propagate immediately; until then, plan for TTL latency on changes.
Q: How does this interact with Pattern G (sortation-line late-bind) from the label guide? Pattern G + advanced cartonization in the same operation is not supported in v1 — sortation routes items to labels at downstream divert; advanced cartonization produces containers at upstream induction. Picking one mode per Site is the v1 constraint.
Q: What’s the maximum sequence position count? There’s no hard limit. PackagingSequenceArtifact instances are scoped per Scheme execution (typically per-cart-batch or per-shift-station). A shift’s worth of sequence positions (thousands) is operationally normal. Extreme cases (tens of thousands per instance) may need ops review for memory + DB pressure.
Q: Are sequence positions persistent across executor restart? Yes. PackagingSequenceArtifact state lives in the executor’s Runtime Data; per Jason intention persistence (ADR-0001) + CArtAgO artifact persistence the state survives JVM restart. Sequenced ops resume from the last consistent position on recovery.
For deeper context, see WES ADR-0023 for the architectural decisions, Label printing guide for the at-cartonization label mode, and Cancellation guide for cancellation × orphan disposition interaction.