From 94726d67f6f6c68eab7e88ec622ac1a560646caf Mon Sep 17 00:00:00 2001 From: Annie Tallund Date: Thu, 12 Mar 2026 16:57:33 -0700 Subject: [PATCH 1/7] New LP with AI agents using Strands and Device Connect --- .../device-connect-strands/_index.md | 54 +++++ .../device-connect-strands/_next-steps.md | 8 + .../device-connect-strands/background.md | 74 +++++++ .../device-connect-strands/run-example.md | 169 +++++++++++++++ .../run-infra-example.md | 193 ++++++++++++++++++ .../device-connect-strands/setup.md | 85 ++++++++ 6 files changed, 583 insertions(+) create mode 100644 content/learning-paths/embedded-and-microcontrollers/device-connect-strands/_index.md create mode 100644 content/learning-paths/embedded-and-microcontrollers/device-connect-strands/_next-steps.md create mode 100644 content/learning-paths/embedded-and-microcontrollers/device-connect-strands/background.md create mode 100644 content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-example.md create mode 100644 content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-infra-example.md create mode 100644 content/learning-paths/embedded-and-microcontrollers/device-connect-strands/setup.md diff --git a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/_index.md b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/_index.md new file mode 100644 index 0000000000..b24a4b7653 --- /dev/null +++ b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/_index.md @@ -0,0 +1,54 @@ +--- +title: Connect AI agents to edge devices using Device Connect and Strands + + +draft: true +cascade: + draft: true + +minutes_to_complete: 30 + +who_is_this_for: This Learning Path is for software developers who want to connect AI agents to physical or simulated edge devices using Device Connect — Arm's platform for structured device access — and Strands, the open-source agent SDK from AWS. + +learning_objectives: + - Understand how Device Connect and Strands work together to give AI agents structured access to Arm-based edge devices. + - Set up a Python environment with the Device Connect SDK and agent tools installed from source. + - Start a simulated robot that registers itself on the local network and is discovered automatically by an agent. + - Discover and invoke the robot using the Device Connect agent tools and the robot_mesh Strands tool. + +prerequisites: + - An Arm Linux or macOS machine with Python 3.12 installed. + - Git installed. + - Basic familiarity with Python virtual environments and command-line tools. + - (Optional) A Raspberry Pi for testing a full infrastructure setup + +author: Annie Tallund + + + +### Tags +skilllevels: Introductory +subjects: ML +armips: + - Cortex-A + - Neoverse +operatingsystems: + - Linux + - macOS +tools_software_languages: + - Python + - Docker + - strands-agents + +further_reading: + - resource: + title: Strands Agents SDK documentation + link: https://strandsagents.com/ + type: website + +### FIXED, DO NOT MODIFY +# ================================================================================ +weight: 1 # _index.md always has weight of 1 to order correctly +layout: "learningpathall" # All files under learning paths have this same wrapper +learning_path_main_page: "yes" # This should be surfaced when looking for related content. Only set for _index.md of learning path content. +--- diff --git a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/_next-steps.md b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/_next-steps.md new file mode 100644 index 0000000000..c3db0de5a2 --- /dev/null +++ b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/_next-steps.md @@ -0,0 +1,8 @@ +--- +# ================================================================================ +# FIXED, DO NOT MODIFY THIS FILE +# ================================================================================ +weight: 21 # Set to always be larger than the content in this path to be at the end of the navigation. +title: "Next Steps" # Always the same, html page title. +layout: "learningpathall" # All files under learning paths have this same wrapper for Hugo processing. +--- diff --git a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/background.md b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/background.md new file mode 100644 index 0000000000..998d47ee30 --- /dev/null +++ b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/background.md @@ -0,0 +1,74 @@ +--- +title: Background and architecture +weight: 2 + +# FIXED, DO NOT MODIFY +layout: learningpathall +--- + +## Why connect AI agents to edge devices? + +Arm processors are at the heart of a remarkable range of systems — from Cortex-M microcontrollers in industrial sensors to Neoverse servers running in the cloud. That breadth of hardware is one of Arm's greatest strengths, but it raises a practical question for AI developers: how do you give an agent structured, safe access to devices that are physically distributed and built on different software stacks? + +Device Connect is Arm's answer to that question. It is a platform layer that handles device registration, discovery, and remote procedure calls across a network of devices, with no bespoke networking code required. Strands is an open-source agent SDK from AWS that takes a model-driven approach to building AI agents — an LLM calls Python tools in a structured reasoning loop, and the SDK handles the rest. When you combine them, an agent can ask "which devices are online and what can they do?" and then invoke a function on a specific device, turning natural language intent into physical action. + +This Learning Path puts both tools through their paces. It starts with a single machine, for example a laptop, where a simulated robot and an agent discover each other automatically, then extends to a two-machine setup where a Raspberry Pi joins the same device mesh over the network. + +TODO: compatible devices? Mac and what else? + +## The two layers + +**Device layer** + +A device is any process that registers itself on the mesh and exposes callable functions. In this Learning Path you will create a simulated robot arm from the `strands-robots` SDK. The moment this object is created, it registers on the local1 network under a unique device ID (for example, `so100_sim-abc23`) and begins publishing a presence heartbeat. No explicit registration call is required. Device Connect uses Zenoh as its underlying messaging transport, which handles low-level connectivity and routing automatically. + +**Agent layer** + +Two interfaces sit at this layer. The `device-connect-agent-tools` package exposes `discover_devices()` and `invoke_device()` as plain Python functions you can call directly from a script or REPL, with no LLM involved. The `robot_mesh` tool from `redacted` wraps the same capabilities as a Strands agent tool, which means an LLM can also call them during a reasoning loop. Both share the same underlying Device Connect transport, so anything you can do with one you can do with the other. + +TODO: replace redacted + +The diagram below shows how these layers communicate at runtime: + +``` +┌──────────────────────────────────────┐ +│ Agent layer │ +│ discover_devices · invoke_device │ +│ robot_mesh Strands tool │ +└──────────────┬───────────────────────┘ + │ Device Connect + │ (device-to-device discovery & RPC) +┌──────────────▼───────────────────────┐ +│ Device layer │ +│ Robot('so100') — so100_sim-abc123 │ +│ heartbeat · execute · getStatus │ +└──────────────────────────────────────┘ +``` + +## How device discovery works + +When a `Robot()` instance starts, Device Connect automatically announces the device on the local network. Any process running `discover_devices()` or `robot_mesh(action='peers')` on the same network will hear the announcement and add the device to its live table of available hardware. + +## What the simulated robot provides + +When you run `Robot('so100')`, the SDK downloads the MuJoCo physics model for the SO-100 arm (this happens once on first run) and starts a local simulation. The robot exposes three functions that any agent can call via RPC: + +- `execute` — start a task with a given instruction and policy provider +- `getStatus` — query the current task state +- `stop` — halt the current task + +For this Learning Path, the `policy_provider='mock'` argument is used, which means `execute` accepts the call and returns `{'status': 'accepted'}` without actually running a motion policy. This keeps the focus on the connectivity and invocation patterns rather than robotics. + +Once you have the flow working end to end, replacing `'mock'` with a real policy is a one-line change. + +## What you'll accomplish in this Learning Path + +By working through the remaining sections you will: + +- Clone two repositories and install the Device Connect SDK, agent tools, and Strands robot runtime from source into a single virtual environment. +- Start a simulated robot that registers itself on the local device mesh. +- Discover and invoke the robot using `device-connect-agent-tools` directly. +- Discover and command the robot through the `robot_mesh` Strands tool, including an emergency stop. +- Optionally extend the setup to a Raspberry Pi connected over the network, discovering and commanding it from your laptop through the Device Connect infrastructure. + +The next section covers the environment setup. diff --git a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-example.md b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-example.md new file mode 100644 index 0000000000..5b02d4cea0 --- /dev/null +++ b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-example.md @@ -0,0 +1,169 @@ +--- +title: Run the example end to end +weight: 4 + +# FIXED, DO NOT MODIFY +layout: learningpathall +--- + +## Overview + +This section runs entirely on your local machine using Device Connect's device-to-device discovery. You will need two terminal windows open at the same time: one to keep the simulated robot running, and one to invoke it from the agent side. Both terminals need the virtual environment activated. + +| Terminal | Purpose | +|----------|---------| +| 1 | Simulated robot — keep running throughout | +| 2 | Agent tool invocations | + +Make sure you are in the workspace directory you created during setup and that your virtual environment is activated: + +```bash +cd ~/strands-device-connect +source .venv/bin/activate +``` + +## Start the simulated robot + +In terminal 1, run the following command to create and start the simulated SO-100 robot arm: + +```python +python <<'PY' +import logging +logging.basicConfig(level=logging.INFO) +from strands_robots import Robot +Robot('so100') +PY +``` + +When the `Robot('so100')` object is created, the SDK downloads the MuJoCo physics model for the SO-100 arm (this download happens only on the first run and takes a minute or two), then starts the simulation and registers the robot on the Device Connect device mesh. The robot publishes a presence heartbeat every 0.5 seconds under a unique device ID, for example `so100_sim-abc123`. + +You should see INFO-level log output similar to: + +```output +INFO:strands_robots.mesh:Zenoh session started +INFO:strands_robots.mesh:Peer ID: so100_sim-abc123 +INFO:strands_robots.mesh:Heartbeat thread started +``` + +Leave this process running. The simulated robot is only discoverable as long as this process is alive. + +## Discover and invoke the robot using the agent tools + +The `device-connect-agent-tools` package gives you direct programmatic access to the mesh, without involving an LLM. This is useful for testing, scripting, or validating the stack before wiring it up to an agent. Open terminal 2, activate the virtual environment, then run: + +```python +python <<'PY' +from device_connect_agent_tools import connect, discover_devices, invoke_device + +connect() + +devices = discover_devices(device_type='') +print(f'Found {len(devices)} robot(s):') +for d in devices: + print(f' {d["device_id"]}') + +if devices: + result = invoke_device( + devices[0]['device_id'], + 'execute', + {'instruction': 'pick up the cube', 'policy_provider': 'mock'}, + ) + print(f'Result: {result}') +PY +``` + +`discover_devices(device_type='')` returns all devices on the mesh regardless of type. If you pass `device_type='strands_robot'` you can filter to only `Robot()` instances. `invoke_device` sends an RPC to the named device; here `policy_provider='mock'` tells the robot to accept the task without executing real motion, which is appropriate for this connectivity test. + +The output is similar to: + +```output +Found 1 robot(s): + so100_sim-abc123 +Result: {'success': True, 'result': {'status': 'accepted'}} +``` + +## Control the robot using the robot_mesh Strands tool + +The `robot_mesh` tool wraps the same discovery and invocation primitives as a Strands agent tool. You can call it directly from a Python script or attach it to an LLM agent; the API is identical either way. + +### List peers + +Start by confirming which robots are currently visible on the mesh: + +```python +python <<'PY' +from strands_robots.tools.robot_mesh import robot_mesh +print(robot_mesh(action='peers')) +PY +``` + +The output is similar to: + +```output +Found 2 robot(s): + so100_sim-abc123 — idle + so100_sim-def456 — idle +``` + +The peer ID (for example `so100_sim-abc123`) is assigned at startup and changes each run. Note the actual ID shown in your terminal - you will need it in the next step. + +### Execute an instruction + +Send a task to one of the discovered robots. Replace `so100_sim-abc123` with the peer ID shown in your `peers` output: + +```python +python <<'PY' +from strands_robots.tools.robot_mesh import robot_mesh +print(robot_mesh( + action='tell', + target='so100_sim-abc123', + instruction='pick up the cube', + policy_provider='mock', +)) +PY +``` + +You will see the following output: + +```output +Result: {'success': True, 'result': {'status': 'success', 'content': [{'text': "🚀 Policy started on 'so100' (async)"}]}} +``` + +{{% notice Robot output in terminal 1 %}} +The robot also logs event updates as it processes the task. If you switch back to terminal 1, it logs the execution of the task, similar to: + +```output +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*** EVENT so100_sim-abc123::stateUpdate [111aaabb] + payload: sim_time=4.34, step_count=2070, running_policies={'so100': {'steps': 814, 'instruction': 'pick up the cube'}} +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +``` +{{% /notice %}} + + +### Emergency stop + +The emergency stop broadcasts a halt command to every device on the mesh simultaneously. This is useful when you want to stop all robots without knowing their individual peer IDs: + +```python +python <<'PY' +from strands_robots.tools.robot_mesh import robot_mesh +print(robot_mesh(action='emergency_stop')) +PY +``` + +The output is similar to: + +```output +E-STOP: 1/1 devices stopped +``` + +## What you've accomplished and what's next + +In this section you: + +- Started a simulated SO-100 robot that registered itself on the Device Connect device mesh. +- Used `device-connect-agent-tools` to discover the robot and invoke an RPC call against it. +- Used the `robot_mesh` Strands tool to list peers, send an instruction, and trigger an emergency stop. + +This showcases the ease of setting up a mesh on a local network. In the next section, you can optionally set up a Raspberry Pi or any other device, opening up a new category of possibilites with agent integration. \ No newline at end of file diff --git a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-infra-example.md b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-infra-example.md new file mode 100644 index 0000000000..dc9a586929 --- /dev/null +++ b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-infra-example.md @@ -0,0 +1,193 @@ +--- +title: Run with full Device Connect infrastructure +weight: 5 + +# FIXED, DO NOT MODIFY +layout: learningpathall +--- + +## Why add infrastructure? + +The previous section ran entirely on one machine, with Device Connect handling device-to-device discovery automatically. That approach is fast and requires zero configuration, but it has natural limits: both the robot and the agent must be on the same LAN, device state is ephemeral, and there is no registry you can query by device type. + +This section goes one step further. You will run the Zenoh router, an etcd state store, and a registry service on your machine using Docker, then connect a Raspberry Pi on the same network as the remote device. The agent running on your machine will discover the robot running on the Pi through the infrastructure, as if both were part of the same managed fleet. The Pi never needs to run Docker — it just needs Python and the packages from setup. + +## What you need + +- The machine from the previous section, with the virtual environment set up and Docker installed. This will be referred to as the host. +- A Raspberry Pi (or any similar device) connected to the same network as your host machine. +- An SSH connection or keyboard and monitor attached to the Pi. + +Confirm Docker and Docker Compose v2 are available on the host before continuing: + +```bash +docker --version +docker compose version +``` + +## Machine and terminal layout + +This section involves two machines. Keep track of which commands run where: + +| Machine | Terminal | Purpose | +|---------|----------|---------| +| Host | 1 | Docker Compose infrastructure | +| Host | 2 | Agent tool invocations | +| Raspberry Pi | — | Robot process | + +## Step 1 — Start the infrastructure on your host machine + +In host terminal 1, bring up the Device Connect infrastructure stack. The Compose file is inside the `device-connect` repository you cloned during setup: + +```bash +cd ~/strands-device-connect/device-connect/packages/device-connect-server +docker compose -f infra/docker-compose-dev.yml up -d +``` + +Confirm the services are healthy: + +```bash +docker compose -f infra/docker-compose-dev.yml ps +``` + +The output is similar to: + +```output +NAME STATUS PORTS +zenoh-router running 0.0.0.0:7447->7447/tcp +etcd running 0.0.0.0:2379->2379/tcp +device-registry running 0.0.0.0:8080->8080/tcp +``` + +All three services must show `running` before you continue. The router on port 7447 is the single rendezvous point for all device traffic. Every device on any machine points at this address to join the mesh. + +## Step 2 — Find your host's IP address + +The Raspberry Pi needs to connect to the Device Connect router on your host by IP address. Find it now: + +```bash +# macOS +ipconfig getifaddr en0 + +# Linux +hostname -I | awk '{print $1}' +``` + +Note the address returned — for the rest of this section it is referred to as `HOST_IP`. For example, if the command returns `192.168.1.42`, replace every occurrence of `HOST_IP` below with that address. + +## Step 3 — Prepare the Raspberry Pi + +On the Raspberry Pi, follow the same repository and environment setup from the setup section of this Learning Path: install Python 3.12, clone both repositories, create the virtual environment, and install the packages with the same editable install commands. + +Once the environment is ready, export the three variables that tell the SDK to route traffic through the Device Connect router on your host rather than using local network discovery: + +```bash +export MESSAGING_BACKEND=zenoh +export ZENOH_CONNECT=tcp/HOST_IP:7447 +export DEVICE_CONNECT_ALLOW_INSECURE=true +``` + +Replace `HOST_IP` with the address you noted in Step 2. `DEVICE_CONNECT_ALLOW_INSECURE=true` disables mTLS for this local development setup — do not use this flag in production. + +## Step 4 — Start the robot on the Raspberry Pi + +On the Raspberry Pi, with the environment active and the variables set, start the simulated SO-100 robot: + +```python +python <<'PY' +import logging +logging.basicConfig(level=logging.INFO) +from strands_robots import Robot +Robot('so100') +PY +``` + +Because `ZENOH_CONNECT` points at your host, the SDK routes traffic through the Device Connect router instead of using local network discovery. The robot registers with the persistent registry and you should see output similar to: + +```output +INFO:strands_robots.mesh:Zenoh session started +INFO:strands_robots.mesh:Peer ID: so100_sim-abc123 +device_connect_sdk.device.so100_sim-abc123 - INFO - Using ZENOH messaging backend +device_connect_sdk.device.so100_sim-abc123 - INFO - Connected to ZENOH broker: ['tcp/192.168.1.42:7447'] +device_connect_sdk.device.so100_sim-abc123 - INFO - Device registered: registration_id=ecfff6a7-... +``` + +Note the peer ID (for example `so100_sim-abc123`). You will need it in the `tell` command below. Leave this process running on the Pi. + +## Discover and invoke using the robot_mesh Strands tool + +In host terminal 2 (with the environment variables set), use `robot_mesh` to confirm the Pi's robot is visible as a peer: + +```python +python <<'PY' +from strands_robots.tools.robot_mesh import robot_mesh +print(robot_mesh(action='peers')) +PY +``` + +The output is similar to: + +```output +Discovered 1 device(s): + [robot] so100_sim-abc123 — idle + Functions: execute, getFeatures, getState, getStatus, stop +``` + +Send an instruction to the robot. Replace `so100_sim-abc123` with the peer ID shown in your output: + +```python +python <<'PY' +from strands_robots.tools.robot_mesh import robot_mesh +print(robot_mesh( + action='tell', + target='so100_sim-abc123', + instruction='pick up the cube', + policy_provider='mock', +)) +PY +``` + +The output is similar to: + +```output +-> so100_sim-abc123: pick up the cube + {"status": "accepted"} +``` + +Trigger an emergency stop across every device registered with the infrastructure: + +```python +python <<'PY' +from strands_robots.tools.robot_mesh import robot_mesh +print(robot_mesh(action='emergency_stop')) +PY +``` + +The output is similar to: + +```output +E-STOP: 1/1 devices stopped +``` + +The stop broadcast reaches every device in the registry — whether it is running on your host, the Pi on your desk, or a machine in a remote lab. + +## Shut down cleanly + +Stop the robot process on the Pi with `Ctrl+C`, then bring down the infrastructure on your host: + +```bash +cd ~/strands-device-connect/device-connect/packages/device-connect-server +docker compose -f infra/docker-compose-dev.yml down +``` + +This removes the containers and clears the in-container etcd state. Your virtual environment and cloned repositories remain intact on both machines. + +## What you've accomplished and what's next + +In this section you: + +- Started a persistent Device Connect infrastructure stack on your host — a router, etcd, and a device registry. +- Connected a Raspberry Pi as a remote device by pointing its SDK at the router's TCP address. +- Discovered the Pi's robot from your host by querying the persistent registry and sent commands to it across the network. + +This is a deliberately simple two-device setup, but it demonstrates the foundation for something much larger. Once devices register through a shared infrastructure, agents can discover and command any of them without caring where they run — a fleet of robot arms, a network of sensors, or a mix of physical and simulated devices all become equally reachable. Adding more devices is just a matter of pointing them at the same router. That is the core of what Device Connect makes possible: a mesh of heterogeneous devices that agents can reason about and act on, at any scale. diff --git a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/setup.md b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/setup.md new file mode 100644 index 0000000000..4a35f1dea7 --- /dev/null +++ b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/setup.md @@ -0,0 +1,85 @@ +--- +title: Set up the developer environment +weight: 3 + +# FIXED, DO NOT MODIFY +layout: learningpathall +--- + +## Verify the required tools + +Before cloning any repositories, confirm that Python 3.12 and Git are available: + +```bash +python3.12 --version +git --version +``` + +These instructions are tested on Python 3.12. Earlier versions of Python 3 may work but are not validated against the `redacted-branch` branch used in this Learning Path. + +## Clone the repositories + +You need two repositories. The `device-connect` contains the SDK and agent tools as local packages. The `redacted` repository contains the robot runtime and the `robot_mesh` Strands tool. + +```bash +mkdir -p ~/strands-device-connect +cd ~/strands-device-connect + +git clone https://github.com/redacted +git clone https://github.com/arm/device-connect.git +``` + +After cloning, your workspace should look like this: + +```output +~/strands-device-connect/ +├── device-connect/ +└── redacted/ +``` + +## Check out the integration branch + +The Device Connect integration code for `redacted` lives on the `redacted-branch` branch. This branch adds the `RobotDeviceDriver` adapter and the updated `robot_mesh` tool that routes calls through the Device Connect SDK rather than the raw Zenoh mesh. + +TODO: remove feature branch? replace redacted and redacted-branch + +```bash +cd redacted +git checkout redacted-branch +cd .. +``` + +## Create a Python virtual environment + +Create a single virtual environment at the workspace root, then activate it: + +```bash +python3.12 -m venv .venv +source .venv/bin/activate +``` + +Now install the packages: + +```bash +pip install --upgrade pip setuptools wheel hatchling hatch-vcs +pip install -e device-connect/packages/device-connect-sdk +pip install -e "device-connect/packages/device-connect-agent-tools[strands]" +pip install -e "redacted[sim]" +``` + +TODO: simplify commands? + +## How discovery works — no configuration needed + +The `strands-robots` SDK uses Device Connect's built-in device-to-device discovery: every `Robot()` instance announces itself on the local network at startup, and any process running `discover_devices()` or `robot_mesh(action='peers')` on the same network segment will find it automatically. + +This means discovery works as long as the device process and the agent process are on the same LAN or on the same machine. Discovery is typically available on home and office networks. If you are behind a firewall or VPN that blocks local network traffic, devices will not discover each other — that scenario requires the infrastructure-backed setup with a Zenoh router, which is covered later in this Learning Path. + +## What you've set up and what's next + +At this point you have: + +- Two repositories cloned with `redacted` on the `feat/device-connect-integration` branch. +- A single Python 3.12 virtual environment with the Device Connect SDK, agent tools, and robot simulation runtime all installed. + +The next section walks you through starting a simulated robot and invoking it from both the agent tools and the `robot_mesh` Strands tool. \ No newline at end of file From a1a7428543c7832ab3c1ab7d65eeb2670e3ca041 Mon Sep 17 00:00:00 2001 From: Annie Tallund Date: Fri, 13 Mar 2026 09:37:51 -0700 Subject: [PATCH 2/7] Swap order of options --- .../device-connect-strands/run-example.md | 70 +++++++++---------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-example.md b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-example.md index 5b02d4cea0..596036d570 100644 --- a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-example.md +++ b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-example.md @@ -47,41 +47,6 @@ INFO:strands_robots.mesh:Heartbeat thread started Leave this process running. The simulated robot is only discoverable as long as this process is alive. -## Discover and invoke the robot using the agent tools - -The `device-connect-agent-tools` package gives you direct programmatic access to the mesh, without involving an LLM. This is useful for testing, scripting, or validating the stack before wiring it up to an agent. Open terminal 2, activate the virtual environment, then run: - -```python -python <<'PY' -from device_connect_agent_tools import connect, discover_devices, invoke_device - -connect() - -devices = discover_devices(device_type='') -print(f'Found {len(devices)} robot(s):') -for d in devices: - print(f' {d["device_id"]}') - -if devices: - result = invoke_device( - devices[0]['device_id'], - 'execute', - {'instruction': 'pick up the cube', 'policy_provider': 'mock'}, - ) - print(f'Result: {result}') -PY -``` - -`discover_devices(device_type='')` returns all devices on the mesh regardless of type. If you pass `device_type='strands_robot'` you can filter to only `Robot()` instances. `invoke_device` sends an RPC to the named device; here `policy_provider='mock'` tells the robot to accept the task without executing real motion, which is appropriate for this connectivity test. - -The output is similar to: - -```output -Found 1 robot(s): - so100_sim-abc123 -Result: {'success': True, 'result': {'status': 'accepted'}} -``` - ## Control the robot using the robot_mesh Strands tool The `robot_mesh` tool wraps the same discovery and invocation primitives as a Strands agent tool. You can call it directly from a Python script or attach it to an LLM agent; the API is identical either way. @@ -158,6 +123,41 @@ The output is similar to: E-STOP: 1/1 devices stopped ``` +## Optional: Discover and invoke the robot using the agent tools + +The `device-connect-agent-tools` package gives you direct programmatic access to the mesh, without involving an LLM. This is useful for testing, scripting, or validating the stack before wiring it up to an agent. Open terminal 2, activate the virtual environment, then run: + +```python +python <<'PY' +from device_connect_agent_tools import connect, discover_devices, invoke_device + +connect() + +devices = discover_devices(device_type='') +print(f'Found {len(devices)} robot(s):') +for d in devices: + print(f' {d["device_id"]}') + +if devices: + result = invoke_device( + devices[0]['device_id'], + 'execute', + {'instruction': 'pick up the cube', 'policy_provider': 'mock'}, + ) + print(f'Result: {result}') +PY +``` + +`discover_devices(device_type='')` returns all devices on the mesh regardless of type. If you pass `device_type='strands_robot'` you can filter to only `Robot()` instances. `invoke_device` sends an RPC to the named device; here `policy_provider='mock'` tells the robot to accept the task without executing real motion, which is appropriate for this connectivity test. + +The output is similar to: + +```output +Found 1 robot(s): + so100_sim-abc123 +Result: {'success': True, 'result': {'status': 'accepted'}} +``` + ## What you've accomplished and what's next In this section you: From fbf287c24fe32fd68a28ea9273cd758cc1cc6935 Mon Sep 17 00:00:00 2001 From: Annie Tallund Date: Fri, 13 Mar 2026 10:29:16 -0700 Subject: [PATCH 3/7] Add target approach to local example --- .../device-connect-strands/background.md | 7 +++-- .../device-connect-strands/run-example.md | 31 +++++++++++++++---- .../run-infra-example.md | 12 ++----- 3 files changed, 32 insertions(+), 18 deletions(-) diff --git a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/background.md b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/background.md index 998d47ee30..241033fcf6 100644 --- a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/background.md +++ b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/background.md @@ -20,7 +20,7 @@ TODO: compatible devices? Mac and what else? **Device layer** -A device is any process that registers itself on the mesh and exposes callable functions. In this Learning Path you will create a simulated robot arm from the `strands-robots` SDK. The moment this object is created, it registers on the local1 network under a unique device ID (for example, `so100_sim-abc23`) and begins publishing a presence heartbeat. No explicit registration call is required. Device Connect uses Zenoh as its underlying messaging transport, which handles low-level connectivity and routing automatically. +A device is any process that registers itself on the mesh and exposes callable functions. In this Learning Path you will create a simulated robot arm, namely the simulated robotic arm SO-100 from Hugging Face, from the `strands-robots` SDK. The moment this object is created, it registers on the local network under a unique device ID (for example, `so100_sim-abc23`) and begins publishing a presence heartbeat. No explicit registration call is required. Device Connect uses Zenoh as its underlying messaging transport, which handles low-level connectivity and routing automatically. **Agent layer** @@ -40,14 +40,15 @@ The diagram below shows how these layers communicate at runtime: │ (device-to-device discovery & RPC) ┌──────────────▼───────────────────────┐ │ Device layer │ -│ Robot('so100') — so100_sim-abc123 │ +│ Simulated SO-100 arm | +| — so100_sim-abc123 │ │ heartbeat · execute · getStatus │ └──────────────────────────────────────┘ ``` ## How device discovery works -When a `Robot()` instance starts, Device Connect automatically announces the device on the local network. Any process running `discover_devices()` or `robot_mesh(action='peers')` on the same network will hear the announcement and add the device to its live table of available hardware. +When the `SO-100 arm` instance starts, Device Connect automatically announces the device on the local network. Any process running `discover_devices()` or `robot_mesh(action='peers')` on the same network will hear the announcement and add the device to its live table of available hardware. ## What the simulated robot provides diff --git a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-example.md b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-example.md index 596036d570..365454cc7e 100644 --- a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-example.md +++ b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-example.md @@ -8,12 +8,26 @@ layout: learningpathall ## Overview -This section runs entirely on your local machine using Device Connect's device-to-device discovery. You will need two terminal windows open at the same time: one to keep the simulated robot running, and one to invoke it from the agent side. Both terminals need the virtual environment activated. +This section runs Device Connect's device-to-device discovery. There are two ways to walk through this setup. Optionally, you can connect an external device. -| Terminal | Purpose | -|----------|---------| -| 1 | Simulated robot — keep running throughout | -| 2 | Agent tool invocations | +### Option 1: Run on a single machine + +For a proof-of-conect, follow the steps using two terminal windows on your machine with the virtual environment set up. + +### Option 2: Run with real hardware + +If you have access to an external device, you can use it with this setup as well. You will need: + +- Your machine with the virtual environment set up. This machine will be referred to as the host. +- A Raspberry Pi (or any similar device) connected to the same network as your host machine. This machine is your target. +- An SSH connection or keyboard and monitor attached to the target. + +You will need two terminal windows open at the same time: one to keep the simulated robot running, and one to invoke it from the agent side. Both terminals need the virtual environment activated. + +| Machine | Terminal | Purpose | +|---------|----------|---------| +| Host or Target | 1 | Simulated robot — keep running throughout | +| Host | 2 | Agent tool invocations | Make sure you are in the workspace directory you created during setup and that your virtual environment is activated: @@ -148,7 +162,12 @@ if devices: PY ``` +{{% notice About the snippet %}} +When an agent calls `execute(instruction="pick up the cup", policy_provider="groot")`, Device Connect handles the RPC delivery, and the policy handles the actual arm movement. + `discover_devices(device_type='')` returns all devices on the mesh regardless of type. If you pass `device_type='strands_robot'` you can filter to only `Robot()` instances. `invoke_device` sends an RPC to the named device; here `policy_provider='mock'` tells the robot to accept the task without executing real motion, which is appropriate for this connectivity test. +{{% /notice %}} + The output is similar to: @@ -166,4 +185,4 @@ In this section you: - Used `device-connect-agent-tools` to discover the robot and invoke an RPC call against it. - Used the `robot_mesh` Strands tool to list peers, send an instruction, and trigger an emergency stop. -This showcases the ease of setting up a mesh on a local network. In the next section, you can optionally set up a Raspberry Pi or any other device, opening up a new category of possibilites with agent integration. \ No newline at end of file +This showcases the ease of setting up a mesh on a local network. In the next section, you can extend the configuration to a Docker-based approach, opening up a new category of possibilites with agent integration. \ No newline at end of file diff --git a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-infra-example.md b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-infra-example.md index dc9a586929..b99e892b1a 100644 --- a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-infra-example.md +++ b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-infra-example.md @@ -1,5 +1,5 @@ --- -title: Run with full Device Connect infrastructure +title: (Optional) Run with full Device Connect infrastructure weight: 5 # FIXED, DO NOT MODIFY @@ -8,16 +8,10 @@ layout: learningpathall ## Why add infrastructure? -The previous section ran entirely on one machine, with Device Connect handling device-to-device discovery automatically. That approach is fast and requires zero configuration, but it has natural limits: both the robot and the agent must be on the same LAN, device state is ephemeral, and there is no registry you can query by device type. +The previous section ran entirely on a local network, with Device Connect handling device-to-device discovery automatically. That approach is fast and requires zero configuration, but it has natural limits: both the robot and the agent must be on the same LAN, device state is ephemeral, and there is no registry you can query by device type. This section goes one step further. You will run the Zenoh router, an etcd state store, and a registry service on your machine using Docker, then connect a Raspberry Pi on the same network as the remote device. The agent running on your machine will discover the robot running on the Pi through the infrastructure, as if both were part of the same managed fleet. The Pi never needs to run Docker — it just needs Python and the packages from setup. -## What you need - -- The machine from the previous section, with the virtual environment set up and Docker installed. This will be referred to as the host. -- A Raspberry Pi (or any similar device) connected to the same network as your host machine. -- An SSH connection or keyboard and monitor attached to the Pi. - Confirm Docker and Docker Compose v2 are available on the host before continuing: ```bash @@ -33,7 +27,7 @@ This section involves two machines. Keep track of which commands run where: |---------|----------|---------| | Host | 1 | Docker Compose infrastructure | | Host | 2 | Agent tool invocations | -| Raspberry Pi | — | Robot process | +| Target | — | Robot process | ## Step 1 — Start the infrastructure on your host machine From 04c96b6faa74a3fbdb7d497577905f05844e6607 Mon Sep 17 00:00:00 2001 From: Annie Tallund Date: Mon, 16 Mar 2026 09:29:29 -0700 Subject: [PATCH 4/7] Update with single repo approach --- .../device-connect-strands/_index.md | 4 ++- .../device-connect-strands/background.md | 2 ++ .../device-connect-strands/run-example.md | 36 +++++++++++-------- .../run-infra-example.md | 18 ++++++++-- .../device-connect-strands/setup.md | 30 +++++----------- 5 files changed, 50 insertions(+), 40 deletions(-) diff --git a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/_index.md b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/_index.md index b24a4b7653..c6d2476a04 100644 --- a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/_index.md +++ b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/_index.md @@ -22,7 +22,9 @@ prerequisites: - Basic familiarity with Python virtual environments and command-line tools. - (Optional) A Raspberry Pi for testing a full infrastructure setup -author: Annie Tallund +author: + - Annie Tallund + - Kavya Sri Chennoju diff --git a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/background.md b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/background.md index 241033fcf6..75e9730d54 100644 --- a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/background.md +++ b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/background.md @@ -73,3 +73,5 @@ By working through the remaining sections you will: - Optionally extend the setup to a Raspberry Pi connected over the network, discovering and commanding it from your laptop through the Device Connect infrastructure. The next section covers the environment setup. + +TODO: add links to the Strands Robots docs, mesh.md, pypi?, \ No newline at end of file diff --git a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-example.md b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-example.md index 365454cc7e..4c0e374020 100644 --- a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-example.md +++ b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-example.md @@ -29,10 +29,10 @@ You will need two terminal windows open at the same time: one to keep the simula | Host or Target | 1 | Simulated robot — keep running throughout | | Host | 2 | Agent tool invocations | -Make sure you are in the workspace directory you created during setup and that your virtual environment is activated: +Make sure you are in the repository directory and that your virtual environment is activated: ```bash -cd ~/strands-device-connect +cd ~/strands-device-connect/redacted source .venv/bin/activate ``` @@ -45,18 +45,21 @@ python <<'PY' import logging logging.basicConfig(level=logging.INFO) from strands_robots import Robot -Robot('so100') +r = Robot('so100') +r.run() PY ``` -When the `Robot('so100')` object is created, the SDK downloads the MuJoCo physics model for the SO-100 arm (this download happens only on the first run and takes a minute or two), then starts the simulation and registers the robot on the Device Connect device mesh. The robot publishes a presence heartbeat every 0.5 seconds under a unique device ID, for example `so100_sim-abc123`. +When the `Robot('so100')` object is created, the SDK downloads the MuJoCo physics model for the SO-100 arm (this download happens only on the first run and takes a minute or two), then starts the simulation and registers the robot on the Device Connect device mesh. The robot publishes a presence heartbeat every 0.5 seconds under a unique device ID, for example `so100-abc123`. You should see INFO-level log output similar to: ```output -INFO:strands_robots.mesh:Zenoh session started -INFO:strands_robots.mesh:Peer ID: so100_sim-abc123 -INFO:strands_robots.mesh:Heartbeat thread started +device_connect_sdk.device.so100-a3f1b2 - INFO - Using ZENOH messaging backend +device_connect_sdk.device.so100-a3f1b2 - INFO - Connected to ZENOH broker: [] +device_connect_sdk.device.so100-a3f1b2 - INFO - Driver connected: strands_sim +device_connect_sdk.device.so100-a3f1b2 - INFO - Subscribed to commands on device-connect.default.so100-abc123.cmd +🤖 so100-abc123 is online. Ctrl+C to stop. ``` Leave this process running. The simulated robot is only discoverable as long as this process is alive. @@ -79,9 +82,9 @@ PY The output is similar to: ```output -Found 2 robot(s): - so100_sim-abc123 — idle - so100_sim-def456 — idle +Discovered 1 device(s): + [robot] so100-lab-1 — idle + Functions: execute, getFeatures, getStatus, reset, step, stop ``` The peer ID (for example `so100_sim-abc123`) is assigned at startup and changes each run. Note the actual ID shown in your terminal - you will need it in the next step. @@ -105,7 +108,8 @@ PY You will see the following output: ```output -Result: {'success': True, 'result': {'status': 'success', 'content': [{'text': "🚀 Policy started on 'so100' (async)"}]}} +-> so100-lab-1: pick up the cube + {"status": "success", "content": [...]} ``` {{% notice Robot output in terminal 1 %}} @@ -158,7 +162,10 @@ if devices: 'execute', {'instruction': 'pick up the cube', 'policy_provider': 'mock'}, ) - print(f'Result: {result}') + print(f'Execute result: {result}') + + status = invoke_device(devices[0]['device_id'], 'getStatus') + print(f'Status: {status}') PY ``` @@ -173,8 +180,9 @@ The output is similar to: ```output Found 1 robot(s): - so100_sim-abc123 -Result: {'success': True, 'result': {'status': 'accepted'}} + so100-lab-1 — idle +Execute result: {'success': True, 'result': {'status': 'success', 'content': [...]}} +Status: {'success': True, 'result': {...}} # full sim state dict ``` ## What you've accomplished and what's next diff --git a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-infra-example.md b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-infra-example.md index b99e892b1a..a9d54e7d85 100644 --- a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-infra-example.md +++ b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-infra-example.md @@ -10,7 +10,9 @@ layout: learningpathall The previous section ran entirely on a local network, with Device Connect handling device-to-device discovery automatically. That approach is fast and requires zero configuration, but it has natural limits: both the robot and the agent must be on the same LAN, device state is ephemeral, and there is no registry you can query by device type. -This section goes one step further. You will run the Zenoh router, an etcd state store, and a registry service on your machine using Docker, then connect a Raspberry Pi on the same network as the remote device. The agent running on your machine will discover the robot running on the Pi through the infrastructure, as if both were part of the same managed fleet. The Pi never needs to run Docker — it just needs Python and the packages from setup. +This section goes one step further. You will run the Zenoh router, an etcd state store, and a registry service on your machine using Docker, then connect a Raspberry Pi on the same network as the remote device. You can use a different device as long as you can access it, but the Raspberry Pi will be used as an example. This device is also referred to as the target. + +The agent running on your machine will discover the robot running on the Pi through the infrastructure, as if both were part of the same managed fleet. The Pi never needs to run Docker — it just needs Python and the packages from setup. Confirm Docker and Docker Compose v2 are available on the host before continuing: @@ -19,6 +21,14 @@ docker --version docker compose version ``` +## Clone and bring up the Docker image + +```bash +cd ~/strands-device-connect +git clone --depth 1 https://github.com/arm/device-connect.git + +``` + ## Machine and terminal layout This section involves two machines. Keep track of which commands run where: @@ -36,6 +46,7 @@ In host terminal 1, bring up the Device Connect infrastructure stack. The Compos ```bash cd ~/strands-device-connect/device-connect/packages/device-connect-server docker compose -f infra/docker-compose-dev.yml up -d +cd ../../.. ``` Confirm the services are healthy: @@ -71,7 +82,7 @@ Note the address returned — for the rest of this section it is referred to as ## Step 3 — Prepare the Raspberry Pi -On the Raspberry Pi, follow the same repository and environment setup from the setup section of this Learning Path: install Python 3.12, clone both repositories, create the virtual environment, and install the packages with the same editable install commands. +On the Raspberry Pi, follow the same repository and environment setup from the setup section of this Learning Path: install Python 3.12, clone the `redacted` repository, create the virtual environment, and install the packages with the same editable install commands. Once the environment is ready, export the three variables that tell the SDK to route traffic through the Device Connect router on your host rather than using local network discovery: @@ -92,7 +103,8 @@ python <<'PY' import logging logging.basicConfig(level=logging.INFO) from strands_robots import Robot -Robot('so100') +r = Robot('so100') +r.run() PY ``` diff --git a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/setup.md b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/setup.md index 4a35f1dea7..22fee6405a 100644 --- a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/setup.md +++ b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/setup.md @@ -17,24 +17,14 @@ git --version These instructions are tested on Python 3.12. Earlier versions of Python 3 may work but are not validated against the `redacted-branch` branch used in this Learning Path. -## Clone the repositories +## Clone the repository -You need two repositories. The `device-connect` contains the SDK and agent tools as local packages. The `redacted` repository contains the robot runtime and the `robot_mesh` Strands tool. +The code run in this Learning Path sits in the `redacted` repository. It contains the robot runtime and the `robot_mesh` Strands tool. ```bash -mkdir -p ~/strands-device-connect -cd ~/strands-device-connect - +mkdir ~/strands-device-connect +cd strands-device-connect git clone https://github.com/redacted -git clone https://github.com/arm/device-connect.git -``` - -After cloning, your workspace should look like this: - -```output -~/strands-device-connect/ -├── device-connect/ -└── redacted/ ``` ## Check out the integration branch @@ -44,7 +34,7 @@ The Device Connect integration code for `redacted` lives on the `redacted-branch TODO: remove feature branch? replace redacted and redacted-branch ```bash -cd redacted +cd ~/strands-device-connect/redacted git checkout redacted-branch cd .. ``` @@ -58,17 +48,13 @@ python3.12 -m venv .venv source .venv/bin/activate ``` -Now install the packages: +Now install the packages and make sure they are available on your `PYTHONPATH` environment variable: ```bash -pip install --upgrade pip setuptools wheel hatchling hatch-vcs -pip install -e device-connect/packages/device-connect-sdk -pip install -e "device-connect/packages/device-connect-agent-tools[strands]" -pip install -e "redacted[sim]" +pip install -e ".[sim]" +export PYTHONPATH="$PWD:$PYTHONPATH" ``` -TODO: simplify commands? - ## How discovery works — no configuration needed The `strands-robots` SDK uses Device Connect's built-in device-to-device discovery: every `Robot()` instance announces itself on the local network at startup, and any process running `discover_devices()` or `robot_mesh(action='peers')` on the same network segment will find it automatically. From a0653d16611a8ca1a2345301b1a0df4b970010af Mon Sep 17 00:00:00 2001 From: Annie Tallund Date: Mon, 16 Mar 2026 13:00:23 -0700 Subject: [PATCH 5/7] Update repo name --- .../device-connect-strands/background.md | 6 +++--- .../device-connect-strands/run-example.md | 2 +- .../device-connect-strands/run-infra-example.md | 2 +- .../device-connect-strands/setup.md | 16 ++++++++-------- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/background.md b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/background.md index 75e9730d54..8bd6a465a1 100644 --- a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/background.md +++ b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/background.md @@ -24,9 +24,9 @@ A device is any process that registers itself on the mesh and exposes callable f **Agent layer** -Two interfaces sit at this layer. The `device-connect-agent-tools` package exposes `discover_devices()` and `invoke_device()` as plain Python functions you can call directly from a script or REPL, with no LLM involved. The `robot_mesh` tool from `redacted` wraps the same capabilities as a Strands agent tool, which means an LLM can also call them during a reasoning loop. Both share the same underlying Device Connect transport, so anything you can do with one you can do with the other. +Two interfaces sit at this layer. The `device-connect-agent-tools` package exposes `discover_devices()` and `invoke_device()` as plain Python functions you can call directly from a script or REPL, with no LLM involved. The `robot_mesh` tool from `robots` wraps the same capabilities as a Strands agent tool, which means an LLM can also call them during a reasoning loop. Both share the same underlying Device Connect transport, so anything you can do with one you can do with the other. -TODO: replace redacted +TODO: replace robots The diagram below shows how these layers communicate at runtime: @@ -66,7 +66,7 @@ Once you have the flow working end to end, replacing `'mock'` with a real policy By working through the remaining sections you will: -- Clone two repositories and install the Device Connect SDK, agent tools, and Strands robot runtime from source into a single virtual environment. +- Clone the sample repository and install the Device Connect SDK, agent tools, and Strands robot runtime from source into a single virtual environment. - Start a simulated robot that registers itself on the local device mesh. - Discover and invoke the robot using `device-connect-agent-tools` directly. - Discover and command the robot through the `robot_mesh` Strands tool, including an emergency stop. diff --git a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-example.md b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-example.md index 4c0e374020..9d0d1965e6 100644 --- a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-example.md +++ b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-example.md @@ -32,7 +32,7 @@ You will need two terminal windows open at the same time: one to keep the simula Make sure you are in the repository directory and that your virtual environment is activated: ```bash -cd ~/strands-device-connect/redacted +cd ~/strands-device-connect/robots source .venv/bin/activate ``` diff --git a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-infra-example.md b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-infra-example.md index a9d54e7d85..15a776cf8c 100644 --- a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-infra-example.md +++ b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-infra-example.md @@ -82,7 +82,7 @@ Note the address returned — for the rest of this section it is referred to as ## Step 3 — Prepare the Raspberry Pi -On the Raspberry Pi, follow the same repository and environment setup from the setup section of this Learning Path: install Python 3.12, clone the `redacted` repository, create the virtual environment, and install the packages with the same editable install commands. +On the Raspberry Pi, follow the same repository and environment setup from the setup section of this Learning Path: install Python 3.12, clone the `robots` repository, create the virtual environment, and install the packages with the same editable install commands. Once the environment is ready, export the three variables that tell the SDK to route traffic through the Device Connect router on your host rather than using local network discovery: diff --git a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/setup.md b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/setup.md index 22fee6405a..149a059036 100644 --- a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/setup.md +++ b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/setup.md @@ -15,27 +15,27 @@ python3.12 --version git --version ``` -These instructions are tested on Python 3.12. Earlier versions of Python 3 may work but are not validated against the `redacted-branch` branch used in this Learning Path. +These instructions are tested on Python 3.12. Earlier versions of Python 3 may work but are not validated against the `feat/device-connect-integration-draft` branch used in this Learning Path. ## Clone the repository -The code run in this Learning Path sits in the `redacted` repository. It contains the robot runtime and the `robot_mesh` Strands tool. +The code run in this Learning Path sits in the `robots` repository. It contains the robot runtime and the `robot_mesh` Strands tool. ```bash mkdir ~/strands-device-connect cd strands-device-connect -git clone https://github.com/redacted +git clone https://github.com/atsyplikhin/robots.git ``` ## Check out the integration branch -The Device Connect integration code for `redacted` lives on the `redacted-branch` branch. This branch adds the `RobotDeviceDriver` adapter and the updated `robot_mesh` tool that routes calls through the Device Connect SDK rather than the raw Zenoh mesh. +The Device Connect integration code for `robots` lives on the `feat/device-connect-integration-draft` branch. This branch adds the `RobotDeviceDriver` adapter and the updated `robot_mesh` tool that routes calls through the Device Connect SDK rather than the raw Zenoh mesh. -TODO: remove feature branch? replace redacted and redacted-branch +TODO: remove feature branch? replace robots and feat/device-connect-integration-draft ```bash -cd ~/strands-device-connect/redacted -git checkout redacted-branch +cd ~/strands-device-connect/robots +git checkout feat/device-connect-integration-draft cd .. ``` @@ -65,7 +65,7 @@ This means discovery works as long as the device process and the agent process a At this point you have: -- Two repositories cloned with `redacted` on the `feat/device-connect-integration` branch. +- `robots` cloned with the `feat/device-connect-integration` branch. - A single Python 3.12 virtual environment with the Device Connect SDK, agent tools, and robot simulation runtime all installed. The next section walks you through starting a simulated robot and invoking it from both the agent tools and the `robot_mesh` Strands tool. \ No newline at end of file From eb69a7a4a93ef75a8bb843651748d62ced670b01 Mon Sep 17 00:00:00 2001 From: Annie Tallund Date: Mon, 16 Mar 2026 13:24:03 -0700 Subject: [PATCH 6/7] Final touches --- .../device-connect-strands/_index.md | 12 ++++++++-- .../device-connect-strands/background.md | 8 ++----- .../device-connect-strands/run-example.md | 22 +++++++++---------- .../run-infra-example.md | 18 +++++++-------- .../device-connect-strands/setup.md | 2 -- 5 files changed, 32 insertions(+), 30 deletions(-) diff --git a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/_index.md b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/_index.md index c6d2476a04..279bfaa32b 100644 --- a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/_index.md +++ b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/_index.md @@ -17,10 +17,10 @@ learning_objectives: - Discover and invoke the robot using the Device Connect agent tools and the robot_mesh Strands tool. prerequisites: - - An Arm Linux or macOS machine with Python 3.12 installed. + - An development machine with Python 3.12 installed. - Git installed. - Basic familiarity with Python virtual environments and command-line tools. - - (Optional) A Raspberry Pi for testing a full infrastructure setup + - (Optional) A Raspberry Pi for testing a full device-to-device (D2D) setup. author: - Annie Tallund @@ -47,6 +47,14 @@ further_reading: title: Strands Agents SDK documentation link: https://strandsagents.com/ type: website + - resource: + title: Strands robots repository + link: https://github.com/strands-labs/robots/tree/dev + type: website + - resource: + title: Device Connect integration guide + link: https://github.com/atsyplikhin/robots/blob/feat/device-connect-integration-draft/strands_robots/device_connect/GUIDE.md + type: website ### FIXED, DO NOT MODIFY # ================================================================================ diff --git a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/background.md b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/background.md index 8bd6a465a1..3434c5bbc7 100644 --- a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/background.md +++ b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/background.md @@ -14,8 +14,6 @@ Device Connect is Arm's answer to that question. It is a platform layer that han This Learning Path puts both tools through their paces. It starts with a single machine, for example a laptop, where a simulated robot and an agent discover each other automatically, then extends to a two-machine setup where a Raspberry Pi joins the same device mesh over the network. -TODO: compatible devices? Mac and what else? - ## The two layers **Device layer** @@ -26,8 +24,6 @@ A device is any process that registers itself on the mesh and exposes callable f Two interfaces sit at this layer. The `device-connect-agent-tools` package exposes `discover_devices()` and `invoke_device()` as plain Python functions you can call directly from a script or REPL, with no LLM involved. The `robot_mesh` tool from `robots` wraps the same capabilities as a Strands agent tool, which means an LLM can also call them during a reasoning loop. Both share the same underlying Device Connect transport, so anything you can do with one you can do with the other. -TODO: replace robots - The diagram below shows how these layers communicate at runtime: ``` @@ -41,7 +37,7 @@ The diagram below shows how these layers communicate at runtime: ┌──────────────▼───────────────────────┐ │ Device layer │ │ Simulated SO-100 arm | -| — so100_sim-abc123 │ +| — so100-abc123 │ │ heartbeat · execute · getStatus │ └──────────────────────────────────────┘ ``` @@ -74,4 +70,4 @@ By working through the remaining sections you will: The next section covers the environment setup. -TODO: add links to the Strands Robots docs, mesh.md, pypi?, \ No newline at end of file +TODO: replace robots and feat/device-connect-integration-draft. Update furhter reading links. Clarify device support. \ No newline at end of file diff --git a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-example.md b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-example.md index 9d0d1965e6..9f5a83015b 100644 --- a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-example.md +++ b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-example.md @@ -55,10 +55,10 @@ When the `Robot('so100')` object is created, the SDK downloads the MuJoCo physic You should see INFO-level log output similar to: ```output -device_connect_sdk.device.so100-a3f1b2 - INFO - Using ZENOH messaging backend -device_connect_sdk.device.so100-a3f1b2 - INFO - Connected to ZENOH broker: [] -device_connect_sdk.device.so100-a3f1b2 - INFO - Driver connected: strands_sim -device_connect_sdk.device.so100-a3f1b2 - INFO - Subscribed to commands on device-connect.default.so100-abc123.cmd +device_connect_sdk.device.so100-abc123 - INFO - Using ZENOH messaging backend +device_connect_sdk.device.so100-abc123 - INFO - Connected to ZENOH broker: [] +device_connect_sdk.device.so100-abc123 - INFO - Driver connected: strands_sim +device_connect_sdk.device.so100-abc123 - INFO - Subscribed to commands on device-connect.default.so100-abc123.cmd 🤖 so100-abc123 is online. Ctrl+C to stop. ``` @@ -83,22 +83,22 @@ The output is similar to: ```output Discovered 1 device(s): - [robot] so100-lab-1 — idle + [robot] so100-abc123 — idle Functions: execute, getFeatures, getStatus, reset, step, stop ``` -The peer ID (for example `so100_sim-abc123`) is assigned at startup and changes each run. Note the actual ID shown in your terminal - you will need it in the next step. +The peer ID (for example `so100-abc123`) is assigned at startup and changes each run. Note the actual ID shown in your terminal - you will need it in the next step. ### Execute an instruction -Send a task to one of the discovered robots. Replace `so100_sim-abc123` with the peer ID shown in your `peers` output: +Send a task to one of the discovered robots. Replace `so100-abc123` with the peer ID shown in your `peers` output: ```python python <<'PY' from strands_robots.tools.robot_mesh import robot_mesh print(robot_mesh( action='tell', - target='so100_sim-abc123', + target='so100-abc123', instruction='pick up the cube', policy_provider='mock', )) @@ -108,7 +108,7 @@ PY You will see the following output: ```output --> so100-lab-1: pick up the cube +-> so100-abc123: pick up the cube {"status": "success", "content": [...]} ``` @@ -117,7 +117,7 @@ The robot also logs event updates as it processes the task. If you switch back t ```output ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -*** EVENT so100_sim-abc123::stateUpdate [111aaabb] +*** EVENT so100-abc123::stateUpdate [111aaabb] payload: sim_time=4.34, step_count=2070, running_policies={'so100': {'steps': 814, 'instruction': 'pick up the cube'}} ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``` @@ -180,7 +180,7 @@ The output is similar to: ```output Found 1 robot(s): - so100-lab-1 — idle + so100-abc123 — idle Execute result: {'success': True, 'result': {'status': 'success', 'content': [...]}} Status: {'success': True, 'result': {...}} # full sim state dict ``` diff --git a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-infra-example.md b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-infra-example.md index 15a776cf8c..56c9569975 100644 --- a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-infra-example.md +++ b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/run-infra-example.md @@ -112,13 +112,13 @@ Because `ZENOH_CONNECT` points at your host, the SDK routes traffic through the ```output INFO:strands_robots.mesh:Zenoh session started -INFO:strands_robots.mesh:Peer ID: so100_sim-abc123 -device_connect_sdk.device.so100_sim-abc123 - INFO - Using ZENOH messaging backend -device_connect_sdk.device.so100_sim-abc123 - INFO - Connected to ZENOH broker: ['tcp/192.168.1.42:7447'] -device_connect_sdk.device.so100_sim-abc123 - INFO - Device registered: registration_id=ecfff6a7-... +INFO:strands_robots.mesh:Peer ID: so100-abc123 +device_connect_sdk.device.so100-abc123 - INFO - Using ZENOH messaging backend +device_connect_sdk.device.so100-abc123 - INFO - Connected to ZENOH broker: ['tcp/192.168.1.42:7447'] +device_connect_sdk.device.so100-abc123 - INFO - Device registered: registration_id=ecfff6a7-... ``` -Note the peer ID (for example `so100_sim-abc123`). You will need it in the `tell` command below. Leave this process running on the Pi. +Note the peer ID (for example `so100-abc123`). You will need it in the `tell` command below. Leave this process running on the Pi. ## Discover and invoke using the robot_mesh Strands tool @@ -135,18 +135,18 @@ The output is similar to: ```output Discovered 1 device(s): - [robot] so100_sim-abc123 — idle + [robot] so100-abc123 — idle Functions: execute, getFeatures, getState, getStatus, stop ``` -Send an instruction to the robot. Replace `so100_sim-abc123` with the peer ID shown in your output: +Send an instruction to the robot. Replace `so100-abc123` with the peer ID shown in your output: ```python python <<'PY' from strands_robots.tools.robot_mesh import robot_mesh print(robot_mesh( action='tell', - target='so100_sim-abc123', + target='so100-abc123', instruction='pick up the cube', policy_provider='mock', )) @@ -156,7 +156,7 @@ PY The output is similar to: ```output --> so100_sim-abc123: pick up the cube +-> so100-abc123: pick up the cube {"status": "accepted"} ``` diff --git a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/setup.md b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/setup.md index 149a059036..df5d9fff36 100644 --- a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/setup.md +++ b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/setup.md @@ -31,8 +31,6 @@ git clone https://github.com/atsyplikhin/robots.git The Device Connect integration code for `robots` lives on the `feat/device-connect-integration-draft` branch. This branch adds the `RobotDeviceDriver` adapter and the updated `robot_mesh` tool that routes calls through the Device Connect SDK rather than the raw Zenoh mesh. -TODO: remove feature branch? replace robots and feat/device-connect-integration-draft - ```bash cd ~/strands-device-connect/robots git checkout feat/device-connect-integration-draft From 4ff17dd934a13bbd8fd1d43d8546879c95b0fdb5 Mon Sep 17 00:00:00 2001 From: Annie Tallund Date: Mon, 16 Mar 2026 13:31:28 -0700 Subject: [PATCH 7/7] Remove draft status for internal review --- .../device-connect-strands/_index.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/_index.md b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/_index.md index 279bfaa32b..9f720cce25 100644 --- a/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/_index.md +++ b/content/learning-paths/embedded-and-microcontrollers/device-connect-strands/_index.md @@ -1,11 +1,6 @@ --- title: Connect AI agents to edge devices using Device Connect and Strands - -draft: true -cascade: - draft: true - minutes_to_complete: 30 who_is_this_for: This Learning Path is for software developers who want to connect AI agents to physical or simulated edge devices using Device Connect — Arm's platform for structured device access — and Strands, the open-source agent SDK from AWS.