Phase 1: Platform mental model

This phase introduces you to Viam machine management and gives you the mental map you need before the rest of the workshop: what happens when you make an API call, why config changes appear instantly on the robot, and how Python code on your laptop talks to hardware across the room. You will configure your first resource as you go.

Three questions to consider

By the end of this phase you should be able to answer the following questions. Keep them in mind as you read, and check yourself against them again at the end.

  1. What are the three layers of a Viam machine, and which one does your Python code actually talk to?
  2. What is the difference between a component and a service?
  3. Why does adding the arm component to the machine trigger a module download?

You will not write any code in this phase, but you will configure your first resource, the arm, so the concepts below have something real to point at. Open your own machine in the Viam app and follow along.

The three layers

Viam cloud app
  └─ machine configuration  (the source of truth)
           │
           │  viam-server pulls config
           ▼
The robot's computer
  ├─ viam-agent    supervises viam-server (installs, updates, restarts)
  └─ viam-server   runs components and services, exposes the control API
           ▲
           │  control API calls
           │
Your Python script (on your laptop)

A Viam machine is made of three layers that each do one job:

  • The Viam cloud app is the source of truth for configuration. When you add a component, change an attribute, or wire up a service, you are editing a JSON document stored in the cloud. The app never controls your robot directly; it describes what should run.
  • viam-agent is a service that runs on the computer controlling the arm. viam-agent manages viam-server: it installs, updates, and keeps viam-server running, restarts the server if it crashes, and provides the initial bootstrap credentials viam-server needs to reach the cloud. Think of viam-agent as the process supervisor, not as the source of your resource config, and not as something you interact with directly during this workshop.
  • viam-server pulls the machine resource configuration from the cloud app, starts every component and service that configuration describes, and exposes the components and services over an API. This is the layer that handles the modules that drive the arm, reads the camera, and runs the vision pipeline.

Open your machine’s overview page in the Viam app now and find the status indicator that shows the machine is live. That indicator reflects viam-agent keeping viam-server running and connected to the cloud app, the handoff between all three layers happening continuously in the background.

How your SDK connects

When a Python script imports the Viam SDK and connects to your machine, the connection goes to viam-server, not to the cloud app. The cloud app helps your script locate the machine and authenticate, but once the connection is established, every control API call goes directly to viam-server on the robot: moving the arm, reading the camera, calling the vision service. You will write exactly this kind of script later in the workshop.

This matters because it explains why your script keeps working even if your laptop briefly loses its connection to the internet at large but keeps a path to the robot: the cloud app is not in the request path for control, only for discovery and configuration delivery.

Open the CONNECT tab on your machine’s page in the Viam app and look at the code sample it generates. It contains your machine’s address and an API key + ID pair, the main things any script needs to authenticate and reach viam-server.

Configuration is the source of truth

Whatever you set in the app’s CONFIGURE tab is what the machine runs. When you save an edit, the app updates the config document, and viam-server picks up the new config and applies it, typically within seconds, without a restart for most changes.

This is why the workshop asks you to make changes in the app rather than by editing a file on the robot directly. The app’s CONFIGURE tab is the only place you need to look to know what a machine will do.

Open the CONFIGURE tab now and find the JSON view toggle near the top of the panel. Switching to JSON shows you the exact document that viam-server receives. Your machine has no resources configured yet, so the document is nearly empty; it fills in as you add resources.

The CONFIGURE tab with the JSON view toggle highlighted, showing a near-empty config document for the pick-and-place-main machine.

Resources: configure your first one

Everything a Viam machine does, hardware and software alike, is modeled as a resource. Each resource has a name you choose (like arm-1), an API that describes what kind of thing it is (an arm, a camera, a vision service), and a model that identifies the specific implementation. The fastest way to understand a resource is to configure one, so add the arm now.

On the CONFIGURE tab, click the + icon and select Blocks. Search for xArm6, select the ufactory/xArm6 result, and name the component arm-1.

The add-component dialog with xArm6 searched and the ufactory/xArm6 result selected.

Set the following attributes:

{
  "host": "192.168.x.x",
  "speed_degs_per_sec": 30
}

host is the only required attribute; it can be found on the arm’s control box. Setting speed_degs_per_sec to 30 keeps the arm moving slowly enough to stay safe while you work near it.

The xArm controller box; the IP address to use for the host attribute is printed on a label.

Save the config, then open the LOGS tab and watch what happens: a log line for a module download, then one for the module starting, then arm-1 coming online, usually well under a minute. You just set the module system in motion; the Builtin resources and modules section below explains what you saw.

The LOGS tab showing the viam:ufactory module downloading and starting.

Back on the CONFIGURE tab, look at the arm-1 card. Next to the name, it shows the model as ufactory/xArm6, the family and model name, with from ufactory marking the module it came from. That is the short form. The model’s full name is a triplet, namespace:family:name, which you can see written out as viam:ufactory:xArm6 if you switch to the JSON view. The triplet tells viam-server exactly which code to run for this resource: who published it (namespace, here viam), the family of models it belongs to (family, here ufactory), and the specific model name (name, here xArm6).

The arm-1 resource card showing its ufactory/xArm6 model and from ufactory module label.

You will configure the gripper and camera the same way in the next phase. Each is a resource too, with its own name, API, and model, even though one drives a gripper and the other reads a depth camera.

Components and services

Resources split into two kinds:

  • Components represent physical hardware. arm-1 is a component, and so are the gripper-1 and cam-1 you add in Phase 2: each one wraps a piece of hardware and exposes a standard API for it (an arm API with move commands, a camera API that returns images, and so on).
  • Services represent software tasks or capabilities. A motion service plans collision-free paths for an arm. Later, you configure a shape-detector vision service that gets images from cam-1 and finds blocks by shape, and a 3D segmenter vision service that takes those detections and turns them into point cloud objects with 3D positions used for planning arm motions. Neither service is a physical thing; each one composes other resources into a new capability.

The difference shows up in what each API does: a component’s API maps onto its hardware, so an arm moves to a pose and a camera returns an image, while a service’s API exposes a capability, so the motion service plans a path and a vision service returns detections. Keep that split in mind: for the rest of the workshop, “component” means a piece of hardware you can point at or visualize, and “service” means a behavior built on top of one or more of those components.

Builtin resources and modules

Some resources are builtin: viam-server (also called the RDK, the robot development kit) ships with support for common APIs and a handful of default models out of the box. Most of the interesting functionality on a real machine, though, comes from modules: packages that viam-server downloads and runs to add support for a specific model.

The ufactory/xArm6 arm you just added comes from a module. That is what the LOGS activity was when you saved it: viam-server recognized it does not have ufactory/xArm6 model built in, so it downloaded the module that provides it from the Viam registry and started it. Every other module-provided resource you add follows the same pattern.

You can read this straight off the triplet seen in the JSON view of the machine configuration. arm-1’s namespace is viam, a third-party namespace, which is why it arrived as a module. A namespace of rdk would mean the model ships inside viam-server itself and needs no download; any other namespace, like viam or erh, means the model comes from a module.

The resource dependency graph

Resources rarely stand alone. Many need another resource configured and running before they can start, and viam-server works out that order for you. The graph below shows the dependencies you build up across this workshop:

arm-1 (arm)
  ├─→ gripper-1 (gripper)
  └─→ home / approach / grasp / travel / place  (pose switches)

cam-1 (camera)
  └─→ shape-detector (vision)
        └─→ vision-segment (vision)

motion  (builtin service, no configuration)

"A → B" means B depends on A: A must be online before B starts.

Resources can depend on each other. A dependency means one resource needs another to be configured and running before it can start, because it relies on that resource to do its job. A gripper attaches to an arm, so gripper-1’s config points at arm-1. A vision service reads from a camera, so it depends on cam-1. viam-server reads these dependencies returned by resources when validating their configuration and builds a dependency graph, then starts resources in an order that respects it: a resource cannot start until everything it depends on has started.

Open the LOGS tab and look at the startup sequence the next time the machine restarts. The order resources come online in the log follows the dependency graph, not the order they appear in the config file.