The word "stateful" in our name is a deliberate technical claim. Most robot dispatch systems are, at their core, stateless: they issue a command, wait for a completion acknowledgment, and forget what they sent. The robot's own firmware tracks its current task. The dispatch system tracks whether the robot is busy or free. That is roughly the extent of the shared state model.
This is adequate for single-robot, simple-task deployments. For fleet-scale pick-and-pack with mid-run replanning, it is not. The gap between what a stateless system knows and what a replanning system needs to know is substantial. This post describes exactly what state the orchestration layer needs to maintain, why each component is necessary, and how it is used in the pick-and-pack context specifically.
Pick-and-pack as a state management challenge
Pick-and-pack operations are more state-intensive than simple point-to-point transport tasks because they involve multi-step workflows, partial completion, and item-level tracking. A robot doesn't just move from A to B; it picks specific items from specific locations, may visit multiple pick locations in sequence, and deposits a consolidated payload at a packing station. The sequence matters, the item identity matters, and partial completion has different implications than zero completion.
Consider a scenario: a pick wave of 240 items across 80 distinct SKUs is in progress with 14 robots active. Robot AMR-09 has picked 3 of its 5 assigned items when a lane blocks. The question for the orchestration layer is not just "can AMR-09 reach its next pick location via an alternative route?" It is: what items has AMR-09 already picked (completed state), what items are still pending (assigned but not yet executed), what dependencies existed between those picks (did picking item 4 depend on picking item 3 first, or were they independent), and does the replan for AMR-09's remaining picks affect any other robot that was expecting to hand off to or from AMR-09 at a staging point?
None of these questions can be answered from a stateless "robot is busy / robot is free" model. They require the orchestration layer to maintain structured state across four dimensions: task history, task dependency graph, robot position estimates, and item-level completion tracking.
Task history: what was done and when
Task history is the record of completed task nodes in the running task graph, with their completion timestamps and execution outcomes. This sounds like a logging concern, but it has direct operational implications for replanning.
When a disruption occurs, the replan engine needs to know which tasks are completed and therefore not subject to replanning. Completed tasks have already produced their output: items have been picked, payloads have been deposited. Replanning cannot and should not attempt to reissue completed tasks. The replan scope is bounded to tasks in "in progress" or "not started" states, and the correct identification of that boundary requires knowing which tasks are completed.
Task history also drives dependency propagation. When task T-104 completes, the system checks whether any tasks have T-104 as a prerequisite. If T-108 is waiting on T-104, that completion event triggers T-108's transition from "waiting" to "ready for assignment." Without maintaining task history as live state (not just a log), this propagation cannot happen automatically, and the system must rely on polling or human dispatch to trigger downstream tasks.
Staleness and the pick-and-pack problem
Pick-and-pack operations generate task completion events at high frequency during busy windows. A 14-robot fleet might generate 80 to 120 task completion events per hour. Each event must be processed by the state management layer to update the task graph and propagate dependency changes. The state management architecture must handle this event rate without falling behind, because stale state data leads to incorrect replan decisions: a replan that treats a completed task as "in progress" may attempt to reissue it to a different robot, causing duplicate execution.
In practice this means the task state store needs to be an in-memory structure with event-driven updates, not a database that is polled periodically. The polling model introduces a latency window during which state is stale. In a high-event-rate environment like an active pick wave, that window can span multiple task completions, compounding the staleness.
The dependency graph at runtime
The task dependency graph is the most structurally complex component of the fleet state. It was produced by the compilation step and encodes the logical ordering constraints of the ops request: which tasks must complete before others can start, which tasks can run concurrently, and which tasks have preconditions tied to the completion of specific predecessor tasks.
At runtime, this graph is not static. It changes as tasks complete (completed nodes are marked, their outgoing edges become satisfied), as tasks are replanned (route fields are updated, timing estimates change), and as preconditions change state (a previously blocked precondition clears, enabling a task that was waiting). The live task graph is the authoritative source of truth for the current execution state of the ops request.
Maintaining the live graph correctly requires careful handling of concurrent updates. In a fleet running multiple ops requests simultaneously, many task completion events arrive roughly in parallel. The state management layer must serialize updates to the graph in a way that preserves consistency: two simultaneous completions of tasks that are predecessors to the same downstream task should each mark their respective nodes as complete and, after both updates, trigger the downstream task's availability exactly once, not twice.
Robot position estimates
The third state dimension is robot positions, maintained as continuous estimates rather than discrete point-in-time updates. AMRs typically report their position at intervals or on crossing a waypoint; between reports, the orchestration layer estimates current position based on the robot's known speed profile, its planned route, and elapsed time since the last confirmed position report.
Position estimates are used during replanning to determine whether a reroute is feasible and what the optimal reroute looks like. A robot that is currently at waypoint 3 of 7 on its route needs a reroute from waypoint 3, not from its starting position. The reroute calculation must know the robot's current location. If the orchestration layer only holds the last confirmed position (which might be several seconds old and several meters behind the robot's actual position), the reroute calculation produces a route that starts from the wrong point.
Position estimation also feeds corridor reservation. The orchestration layer maintains a projected path for each active robot based on its current position estimate and planned route. This projection is what allows the routing solver to detect potential conflicts between in-flight robots: if two position projections intersect at the same corridor segment within a close time window, the routing solver flags a conflict and resolves it before the robots physically encounter each other.
Item-level completion state in pick-and-pack
In pick-and-pack operations specifically, the orchestration layer also needs to maintain item-level completion state: which specific SKUs and item counts have been picked, from which locations, by which robots, as part of which ops request. This is a level of granularity that goes beyond task-level tracking.
The reason item-level state matters is partial pick handling. If a robot fails to pick an item at its assigned location (item not found, location empty, robot fault), the orchestration layer needs to know which specific item is missing to determine the correct recovery action. Did the same item appear in multiple pick locations in the original plan? Can a different robot pick it from an alternative location? Does the missing item block downstream tasks that expected it to be included in the payload?
Without item-level state, the orchestration layer sees only "Task T-112 failed" and has no basis for determining whether the failure is recoverable (item available at another location), blocking (item not available anywhere), or ignorable (item was not on the critical path for the ops request's completion). All three outcomes call for different system responses, and distinguishing between them requires knowing which specific item was involved.
State persistence and recovery
An in-memory state store is fast but ephemeral. If the orchestration process restarts during an active pick wave, the in-memory task graph is lost and all active tasks become unresolved. Recovery requires reconstructing the task graph from a combination of the original compilation output and the completion events that were processed before the restart.
We handle this with a write-ahead log: every state change to the task graph is written to a persistent log before being applied to the in-memory structure. On restart, the orchestration layer replays the log from the last checkpoint to reconstruct the in-memory graph state. The recovery time depends on the number of events since the last checkpoint, but for typical shift-level operation with checkpoints every few minutes, recovery is measured in seconds rather than minutes.
This approach is a deliberate tradeoff. Checkpointing every state change to persistent storage would eliminate recovery latency but would add write overhead to every event, slowing the state management layer's throughput. Checkpointing on a schedule (every 2 minutes in our default configuration) bounds the recovery log replay to at most 2 minutes of events, which is acceptable for the warehouse context where multi-minute outages are already disruptive events regardless of recovery speed.
What this architecture does not cover
Fleet state management, as described here, is the orchestration layer's view of execution state. It does not replace or replicate the robot's own internal state. Each AMR has its own navigation stack, sensor fusion layer, and local task execution state. The orchestration layer does not attempt to mirror that internal state. What it maintains is the coordinated representation of the fleet's work, not the execution details of any individual robot.
This means there is a boundary between what the orchestration layer knows and what the individual robot knows. The robot's local state is authoritative for its own position, obstacle detection, and immediate path execution. The orchestration layer's state is authoritative for task assignment, dependency tracking, and fleet-level routing decisions. Both layers need to be correct within their respective boundaries for the overall system to function reliably. Maintaining the orchestration layer's state with the fidelity described in this post is a necessary condition for that, not a sufficient one.