All articles

Engineering

Task Compilation: Turning a Warehouse Ops Request into an Executable Task Graph

Stateful Robotics Engineering Team
Abstract node graph diagram with coloured nodes connected by flow arrows on a dark background

Consider the instruction: "move batch A47 from bay 3 to dock 7." A human warehouse supervisor reads this and immediately understands a chain of implied steps: someone needs to go to bay 3, confirm batch A47 is there, pick it, transport it through the appropriate corridors, present it at dock 7. If batch A47 is split across two bays, the human infers that both sub-batches need to be consolidated first. If the direct path is blocked, a detour is chosen.

None of that inference is captured in the original instruction. The text describes an outcome, not a sequence of robot-executable operations. A fleet orchestration system that takes this instruction and tries to dispatch it directly to robots has no basis for generating a valid execution plan. The instruction needs to be compiled into a task graph before any robot can act on it.

This is what the compilation step does: it takes a high-level ops request, consults the current warehouse state and fleet capabilities, and produces a directed acyclic graph (DAG) of executable tasks with their dependency edges, preconditions, and robot-type assignments. The rest of this post walks through how that compilation process works and what decisions it makes along the way.

The input: what an ops request contains

An ops request submitted to the Stateful Robotics API carries several fields: the source location (bay, zone, or specific bay address), the destination location (dock, staging area, or coordinates), an item identifier or batch reference, and optionally a priority level and a deadline. In structured deployments, the WMS fires ops requests automatically when its outbound queue triggers; in less automated environments, they are submitted manually through the API or a thin UI wrapper.

What the ops request does not contain is robot assignments, route specifications, intermediate steps, or anything about current floor state. Those are determined by the compiler at compilation time, using live data from the warehouse state store: current robot positions and availability, lane occupancy, bay item locations, and dock status.

The separation matters. Ops requests that are generated by the WMS represent business intent at the time the WMS fires them. The physical execution context, which corridors are clear, which robots are available, changes continuously. Compiling at execution time (rather than pre-planning hours ahead) means the task graph is grounded in current reality, not a prediction of what the floor will look like when the request is eventually processed.

Decomposition: from intent to task types

The first stage of compilation is decomposing the ops request into its constituent task types. A move operation from bay to dock typically decomposes into some combination of the following primitive task types:

  • Pick: navigate to source location, acquire item or pallet
  • Transport: navigate a route between two waypoints while carrying payload
  • Deposit: arrive at destination location, release payload
  • Pre-position: move to a staging location in preparation for a subsequent pick or transport
  • Consolidate: combine sub-batches from multiple source locations before transport (only generated when the source item is split across locations)

The decomposition logic consults the item location data from the warehouse state store. If batch A47 is at a single location in bay 3, the decomposition produces: Pick(bay-3, batch-A47), Transport(bay-3-exit, dock-7-approach), Deposit(dock-7, batch-A47). If batch A47 is split across bay 3 and bay 11, the decomposition adds a consolidation step and potentially a staging waypoint, producing a longer chain.

Each task type has a capability requirement. Pick tasks require a robot capable of item acquisition at the source height profile. Transport tasks require payload capacity matching the item weight and dimensions. Deposit tasks at dock positions may require specific approach angles that not all robot configurations support. These requirements are encoded in the task type definitions and consulted during robot assignment.

Dependency edges: encoding execution order

Once the task nodes are generated, the compiler adds the dependency edges that define legal execution order. A Deposit task cannot start until the Transport task that precedes it completes. A Transport task cannot start until the Pick task delivers the payload to the robot. A Consolidate task cannot start until all sub-batch Pick tasks have completed.

These are hard dependencies: violation would produce a physically invalid state (a robot trying to deposit a payload it hasn't picked up yet). The graph also supports soft dependencies, which are ordering preferences rather than hard constraints: for instance, preferring that a pre-positioning task completes before the corridor it will use becomes congested by other traffic. Soft dependencies can be relaxed by the replanning engine when hard constraints make relaxation necessary.

The result of this stage is a DAG where the edges are typed as hard or soft, and where parallel execution paths are explicit. Tasks that have no dependency relationship between them are candidates for concurrent assignment: they can be dispatched to different robots simultaneously without coordination risk between those specific tasks. The subsequent robot assignment step takes this parallelism into account.

Precondition checking: reality-grounding the graph

Before robot assignment, the compiler runs precondition checks against the current warehouse state. Each task node carries a precondition set: conditions that must be true for the task to be eligible for dispatch. Common preconditions include: source location is accessible (lane to bay is not blocked), destination location has available space, payload capacity of the assigned robot is sufficient for the item weight.

Failed preconditions at compilation time produce a specific output: the task node is created in state "precondition-blocked" rather than "ready." The ops request is not rejected. Instead, the orchestration engine monitors the conditions that caused the block, and automatically transitions the task to "ready" when those conditions clear. If bay 3 access lane is temporarily occupied by another robot, the Pick task for batch A47 waits in "precondition-blocked" until the lane clears, at which point it enters the assignment queue without requiring a new compilation run.

This distinction matters for throughput. An ops request that hits a precondition block is not discarded; it holds its position in the fleet's work queue and self-heals when the blocking condition resolves. A system that rejects the request and requires resubmission loses the queuing position and requires manual resubmission overhead.

Robot assignment: matching capabilities to tasks

Robot assignment is the final stage of compilation. The compiler queries the fleet state for available robots, filtered by capability requirements from each task's type definition. It then runs an assignment algorithm that attempts to minimise total completion time for the ops request while respecting the warehouse graph constraints and existing robot reservations.

The assignment algorithm is not attempting to solve a global optimum across all current ops requests simultaneously. That would be computationally expensive and would produce brittle plans that need full recomputation whenever anything changes. Instead, it greedily assigns the best available robot to each unassigned task node in the graph, working in topological order (tasks earlier in the dependency chain first), with backtracking when a greedy assignment produces a corridor conflict.

Corridor conflict detection during assignment works by simulating the planned routes of all robots currently assigned to tasks, including those from other concurrent ops requests. When a new route overlaps with an existing reservation in time and space, the assignment either offsets the new task's start time (if the conflict clears before the new robot would reach it) or selects an alternative route.

The output is a fully assigned task graph: each task node has a robot ID, a planned route, an estimated start time, and an estimated completion time. This assigned graph is the runtime state that the orchestration engine executes against and that the replan engine queries when a disruption occurs.

What compilation cannot resolve

There are cases where compilation cannot produce a valid fully assigned graph. The most common is fleet exhaustion: all available robots with the required capability are committed to other tasks and none are free within a reasonable time window. In this case, the ops request is queued with status "awaiting-assignment" and the compiler retries assignment as robots complete their current tasks and free up.

A more challenging case is layout infeasibility: the source and destination cannot be connected by any available route given current lane occupancy. This is a transient condition in most warehouses (occupancy changes as other robots complete their tasks), but it means the ops request must wait for a lane to clear before any assignment is possible. The system reports this status explicitly rather than attempting to dispatch on a route that does not currently exist.

We are not claiming that compilation solves all scheduling problems. The value of the compilation step is that it makes these constraints explicit and handles them programmatically, rather than leaving them as implicit knowledge that a human dispatcher carries in their head. The system knows what it cannot do and says so, clearly, rather than producing a confused partial assignment.

Compilation as the foundation for replanning

It is worth connecting the compilation process back to the replanning capability that motivates the whole architecture. Replanning mid-run is only computationally tractable if the system already has a well-structured task graph with explicit dependencies and route assignments. Without that structure, a block event forces a full re-evaluation of all active work, which is slow and error-prone.

Because the compilation step produces a typed DAG with hard dependency edges and route reservations, the replan engine can query it with precision: which task nodes have a path dependency on the blocked lane, what is their current execution state, and what alternative routes are available given current fleet positions. This targeted query is fast because the graph structure makes it fast. The compile-time investment in structuring the work pays off at every replan event that occurs during execution.

This is the core of what we mean when we say Stateful Robotics is a stateful orchestration system. The state is the task graph, populated at compile time and maintained continuously during execution. Replanning is not a special operation that requires reconstructing context from scratch; it is a query against the live state that the system already holds.

Stay current with the orchestration layer

New articles on AMR fleet coordination, task compilation, and replanning from the Stateful Robotics engineering team. No sales emails.

Request Early Access