Remote Fleet Management with AWS IoT RoboRunner in 20 Minutes

Set up centralized robot fleet management using AWS IoT RoboRunner to monitor, command, and coordinate autonomous robots across multiple sites.

Problem: Managing Robots Across Multiple Sites Is a Mess

You have autonomous robots operating across warehouses, factories, or hospitals — and no unified way to monitor their state, send commands, or coordinate them with each other. Each vendor has its own silo.

You'll learn:

  • How to set up AWS IoT RoboRunner for multi-vendor fleet coordination
  • How to register sites, workers, and worker fleets via the AWS CLI and SDK
  • How to send tasks and listen to telemetry in real time

Time: 20 min | Level: Intermediate


Why This Happens

Most robotic systems ship with proprietary fleet management software. When you scale to multiple vendors or sites, you end up with incompatible APIs, no cross-fleet visibility, and brittle custom integrations.

AWS IoT RoboRunner solves this by acting as a coordination layer — it doesn't replace your robots' native software but gives you a unified API to track state, assign tasks, and aggregate telemetry.

Common symptoms without a fleet manager:

  • Robot status only visible inside vendor dashboards
  • No single source of truth for task assignment across fleets
  • Manual re-routing when a robot in Fleet A blocks Fleet B

Solution

Step 1: Create a Site and Worker Fleet

A site maps to a physical location. A worker fleet groups robots that share a management system (e.g., all AMRs from one vendor).

# Create your site
aws iotroborunner create-site \
  --name "warehouse-seattle" \
  --country-code "US" \
  --description "Seattle fulfillment center"

Expected: JSON response with a arn field — save this as SITE_ARN.

# Create a worker fleet within the site
aws iotroborunner create-worker-fleet \
  --name "amr-fleet-1" \
  --site "$SITE_ARN"

Save the returned ARN as FLEET_ARN.

If it fails:

  • AccessDeniedException: Attach AmazonIoTRoboRunnerFullAccess to your IAM role
  • ResourceNotFoundException on site: Double-check your SITE_ARN — region must match

Step 2: Register Individual Robots as Workers

Each robot gets registered as a worker. You pass an additionalFixedProperties JSON blob for static metadata (robot model, max payload, etc.) and additionalTransientProperties for live state.

import { IoTRoboRunnerClient, CreateWorkerCommand } from "@aws-sdk/client-iot-roborunner";

const client = new IoTRoboRunnerClient({ region: "us-east-1" });

async function registerRobot(robotId: string, fleetArn: string) {
  const command = new CreateWorkerCommand({
    name: `robot-${robotId}`,
    fleet: fleetArn,
    // Static properties don't change at runtime
    additionalFixedProperties: JSON.stringify({
      model: "AMR-5000",
      maxPayloadKg: 50,
      chargeVoltage: 48,
    }),
    // Transient properties are updated via UpdateWorker during operation
    additionalTransientProperties: JSON.stringify({
      batteryPct: 100,
      status: "IDLE",
      currentZone: "receiving-dock",
    }),
  });

  const response = await client.send(command);
  console.log("Worker ARN:", response.arn);
  return response.arn;
}

Why additionalTransientProperties: RoboRunner doesn't model every possible robot attribute — these JSON blobs let you store domain-specific state without fighting the schema.


Step 3: Push Live Telemetry Updates

As your robot moves, push state updates so the fleet manager always has current position and status.

import { UpdateWorkerCommand } from "@aws-sdk/client-iot-roborunner";

async function updateRobotState(
  workerArn: string,
  battery: number,
  zone: string,
  positionX: number,
  positionY: number
) {
  const command = new UpdateWorkerCommand({
    id: workerArn,
    // Orientation and position use RoboRunner's VendorProperties schema
    vendorProperties: {
      vendorWorkerId: "amr-5000-001",
      vendorAdditionalTransientProperties: JSON.stringify({
        batteryPct: battery,
        status: battery < 15 ? "RETURNING_TO_CHARGE" : "ACTIVE",
        currentZone: zone,
      }),
    },
    position: {
      cartesianCoordinates: { x: positionX, y: positionY, z: 0 },
    },
    orientation: {
      degrees: 90, // Heading in degrees
    },
  });

  await client.send(command);
}

Call this on a cadence from your robot's onboard software — every 2–5 seconds is typical for AMRs. Avoid sub-second polling; it's noisy and costs more.


Step 4: Create and Assign Tasks

Tasks are the unit of work you assign to a worker. RoboRunner tracks task state but doesn't execute them — your robot's native software does that via the taskBlob payload.

import { CreateTaskCommand, AssignWorkerCommand } from "@aws-sdk/client-iot-roborunner";

async function dispatchPickTask(workerArn: string, destinationArn: string) {
  // Create the task
  const createCmd = new CreateTaskCommand({
    name: `pick-task-${Date.now()}`,
    taskBlob: JSON.stringify({
      action: "PICK",
      sourceShelf: "A-14",
      targetStation: "packing-3",
      sku: "WIDGET-001",
      quantity: 5,
    }),
    // Destination maps to a physical location in your site
    destinations: [destinationArn],
  });

  const task = await client.send(createCmd);

  // Assign the task to a specific worker
  const assignCmd = new AssignWorkerCommand({
    id: task.id!,
    worker: workerArn,
  });

  await client.send(assignCmd);
  console.log(`Task ${task.id} assigned to worker`);
}

Why separate create and assign: This lets you queue tasks before a robot is available, then assign when one becomes free — useful for building a basic dispatcher without a third-party system.


Verification

Poll a worker's current state to confirm telemetry is flowing:

aws iotroborunner get-worker --id "$WORKER_ARN"

You should see: vendorProperties with your latest telemetry JSON, plus position and orientation fields populated with coordinates.

To list all workers in a fleet:

aws iotroborunner list-workers --fleet "$FLEET_ARN"

You should see: All registered robots with their last-known state.


What You Learned

  • RoboRunner is a coordination layer, not a replacement for vendor fleet software — your robots still run their own navigation stack
  • additionalTransientProperties is where your real-time state lives; update it on every telemetry push
  • Tasks decouple what to do from which robot does it — design your dispatcher to assign tasks based on worker state, not hard-coded robot IDs
  • Limitation: RoboRunner doesn't handle path planning or inter-robot collision avoidance — you still need your AMR vendor's software or a third-party coordinator (OSRF Fleet Adapter, InOrbit) for that
  • When NOT to use this: Single-vendor, single-site deployments where the vendor's dashboard already covers your needs — RoboRunner adds infrastructure overhead only worth it at multi-site or multi-vendor scale

Tested on AWS IoT RoboRunner (us-east-1), AWS SDK for JavaScript v3, Node.js 22.x