-
Notifications
You must be signed in to change notification settings - Fork 306
New LP with AI agents using Strands and Device Connect #2983
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
pareenaverma
merged 7 commits into
ArmDeveloperEcosystem:main
from
annietllnd:gtc-strands
Mar 16, 2026
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
94726d6
New LP with AI agents using Strands and Device Connect
annietllnd a1a7428
Swap order of options
annietllnd fbf287c
Add target approach to local example
annietllnd 04c96b6
Update with single repo approach
annietllnd a0653d1
Update repo name
annietllnd eb69a7a
Final touches
annietllnd 4ff17dd
Remove draft status for internal review
annietllnd File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
59 changes: 59 additions & 0 deletions
59
...t/learning-paths/embedded-and-microcontrollers/device-connect-strands/_index.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| --- | ||
| title: Connect AI agents to edge devices using Device Connect and Strands | ||
|
|
||
| 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 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 device-to-device (D2D) setup. | ||
|
|
||
| author: | ||
| - Annie Tallund | ||
| - Kavya Sri Chennoju | ||
|
|
||
|
|
||
|
|
||
| ### 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 | ||
| - 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 | ||
| # ================================================================================ | ||
| 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. | ||
| --- |
8 changes: 8 additions & 0 deletions
8
...rning-paths/embedded-and-microcontrollers/device-connect-strands/_next-steps.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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. | ||
| --- |
73 changes: 73 additions & 0 deletions
73
...arning-paths/embedded-and-microcontrollers/device-connect-strands/background.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| --- | ||
| 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. | ||
|
|
||
| ## 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, 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** | ||
|
|
||
| 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. | ||
|
|
||
| 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 │ | ||
| │ Simulated SO-100 arm | | ||
| | — so100-abc123 │ | ||
| │ heartbeat · execute · getStatus │ | ||
| └──────────────────────────────────────┘ | ||
| ``` | ||
|
|
||
| ## How device discovery works | ||
|
|
||
| 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 | ||
|
|
||
| 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 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. | ||
| - 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: replace robots and feat/device-connect-integration-draft. Update furhter reading links. Clarify device support. | ||
196 changes: 196 additions & 0 deletions
196
...rning-paths/embedded-and-microcontrollers/device-connect-strands/run-example.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,196 @@ | ||
| --- | ||
| title: Run the example end to end | ||
| weight: 4 | ||
|
|
||
| # FIXED, DO NOT MODIFY | ||
| layout: learningpathall | ||
| --- | ||
|
|
||
| ## Overview | ||
|
|
||
| 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. | ||
|
|
||
| ### 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 repository directory and that your virtual environment is activated: | ||
|
|
||
| ```bash | ||
| cd ~/strands-device-connect/robots | ||
| 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 | ||
| 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-abc123`. | ||
|
|
||
| You should see INFO-level log output similar to: | ||
|
|
||
| ```output | ||
| 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. | ||
| ``` | ||
|
|
||
| Leave this process running. The simulated robot is only discoverable as long as this process is alive. | ||
|
|
||
| ## 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 | ||
| Discovered 1 device(s): | ||
| [robot] so100-abc123 — idle | ||
| Functions: execute, getFeatures, getStatus, reset, step, stop | ||
| ``` | ||
|
|
||
| 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-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-abc123', | ||
| instruction='pick up the cube', | ||
| policy_provider='mock', | ||
| )) | ||
| PY | ||
| ``` | ||
|
|
||
| You will see the following output: | ||
|
|
||
| ```output | ||
| -> so100-abc123: pick up the cube | ||
| {"status": "success", "content": [...]} | ||
| ``` | ||
|
|
||
| {{% 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-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 | ||
| ``` | ||
|
|
||
| ## 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', | ||
|
annietllnd marked this conversation as resolved.
|
||
| {'instruction': 'pick up the cube', 'policy_provider': 'mock'}, | ||
| ) | ||
| print(f'Execute result: {result}') | ||
|
|
||
| status = invoke_device(devices[0]['device_id'], 'getStatus') | ||
| print(f'Status: {status}') | ||
| 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: | ||
|
|
||
| ```output | ||
| Found 1 robot(s): | ||
| so100-abc123 — 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 | ||
|
|
||
| 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 extend the configuration to a Docker-based approach, opening up a new category of possibilites with agent integration. | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.