Quick Start
Quick Start
This guide gets you up and running with a SAM node connected to the public bananas.sam-mesh.dev mesh. You can run SAM either directly via a binary or using Docker.
1. Install SAM
Option A: Install Script (macOS / Linux)
The easiest way to install the latest binaries directly:
curl -sL https://sam-mesh.dev/install.sh | bash
Option B: Go Install (macOS / Linux / Windows)
If you have Go installed, you can compile and install directly from the repository:
go install github.com/google/sam/cmd/sam-node@latest
# Optional: if you want to run your own control plane and router:
go install github.com/google/sam/cmd/sam-control-plane@latest
go install github.com/google/sam/cmd/sam-router@latest
Option C: PowerShell (Windows)
For Windows users without WSL, you can download the latest release using PowerShell:
$Release = Invoke-RestMethod -Uri "https://api.github.com/repos/google/sam/releases/latest"
$Version = $Release.tag_name
$Url = "https://github.com/google/sam/releases/download/$Version/sam_Windows_x86_64.zip"
Invoke-WebRequest -Uri $Url -OutFile "sam.zip"
Expand-Archive -Path "sam.zip" -DestinationPath "$env:ProgramFiles\sam"
2. Connect Your Node to the Mesh
Getting a node onto the mesh takes two things: joining — registering the node and obtaining its cryptographic identity (a Biscuit token) via an OIDC login — and running it. The --join flag on run does both in one command: it enrolls the first time (when the node has no identity yet), then starts serving; on every later restart it’s a no-op since the identity is already stored.
Recommended: One Command
Using the Binary
The binary is the simplest way to run a node locally — no volumes or port mapping to think about:
SAM_API_TOKEN=my-secret-token sam-node run --join --bind-addr 127.0.0.1:8080
The CLI will open your browser for login (or print a device code if headless). Once authenticated:
Successfully joined the Sovereign Agent Mesh!
INFO sam-node [AuthN] Successfully authenticated with router via libp2p: ...
SAM Node Online.
PeerID: 12D3KooW...
Using Docker
Docker works the same way, but needs a persistent volume for the identity and explicit port mapping (5001/udp, 5002/tcp for libp2p, 8080/tcp for the local API):
mkdir -p $(pwd)/sam-data
docker run -it \
--user "$(id -u):$(id -g)" \
-v $(pwd)/sam-data:/data \
-p 5001:5001/udp \
-p 5002:5002 \
-p 8080:8080 \
-e SAM_API_TOKEN=my-secret-token \
ghcr.io/google/sam-node:latest \
run --join --data-dir /data --bind-addr 0.0.0.0:8080
Use -it for this first run so you can complete the browser/device-code login; once enrolled, restart it detached with -d instead (--join is a no-op at that point, so it’s safe to leave in your start command). If there’s no interactive terminal attached (e.g. -d on the very first run), the node instead comes up as an unauthenticated sidecar waiting for out-of-band enrollment over MCP.
By default --join enrolls with the public testnet (bananas.sam-mesh.dev); pass --control-plane <url> to join a different mesh.
Running It in the Background
sam-node run stays in the foreground. Add --daemonize to start it detached and return as soon as its local API answers — useful when an AI agent is driving the setup, or when you don’t want a terminal dedicated to the node:
sam-node run --daemonize
sam-node is running in the background.
PID 48213
Endpoint http://127.0.0.1:8080/mcp
Token /home/you/.config/sam-mesh/api-token
Logs /home/you/.config/sam-mesh/sam-node.log
Stop kill 48213
If no API token is configured (SAM_API_TOKEN or --api-token-path), --daemonize generates one under the data directory and reuses it on later starts. The command is idempotent: re-run it to confirm a node is up. Enrollment still needs a one-time login, so on a node with no identity it tells you to run sam-node join --headless <control-plane-url> first.
Starting Over
A node reuses whatever is already in its data directory, which is what you want day to day but not when you are testing setup flows. Two levels of reset:
sam-node reset # forget the mesh identity only, keep the PeerID
sam-node reset --all # delete every file the node keeps, including its key
--all asks for confirmation, and needs --yes when there is no terminal to ask on. Both refuse while a node is still running, so stop it first (kill <pid> from the --daemonize output). After --all the node generates a new PeerID and has to enroll again.
Alternative: Join and Run Separately
If you’re deploying headlessly with a pre-issued bootstrap token, or just prefer explicit steps, you can join and run as two commands instead.
Step 1: Join the Mesh
To register your node with the mesh and obtain a cryptographic identity token (Biscuit), you can use either the interactive OIDC authorization flow or the non-interactive bootstrap token flow.
Option A: Interactive OIDC Flow (Default)
The interactive flow uses your browser to authenticate your identity against Dex (OIDC):
Using the Binary
sam-node join https://bananas.sam-mesh.dev
Using Docker
mkdir -p $(pwd)/sam-data
docker run -it \
--user "$(id -u):$(id -g)" \
-v $(pwd)/sam-data:/data \
ghcr.io/google/sam-node:latest \
join --data-dir /data https://bananas.sam-mesh.dev
The CLI will output a Device Authorization URL (if headless/Docker) or open your browser natively. Once authenticated, the node registers and saves the identity database.
Option B: Non-Interactive Bootstrap Flow (Headless)
If you are deploying a headless server or router and have a generated bootstrap token from the Control Plane API:
Using the Binary
sam-node join --bootstrap-token <your-token> https://bananas.sam-mesh.dev
Using Docker
mkdir -p $(pwd)/sam-data
docker run -it \
--user "$(id -u):$(id -g)" \
-v $(pwd)/sam-data:/data \
ghcr.io/google/sam-node:latest \
join --data-dir /data --bootstrap-token <your-token> https://bananas.sam-mesh.dev
Note: In non-interactive mode, unless the control plane runs with --auto-approve-enrollment, the enrollment request remains PENDING until approved manually by a network administrator.
Step 2: Run the Node
Start your node in the background. We set a security API token (via the SAM_API_TOKEN environment variable or --api-token-path file) to protect access to the local control plane API. Tokens are never accepted as command-line values: they would be visible in process listings.
Using the Binary
SAM_API_TOKEN=my-secret-token sam-node run --bind-addr 127.0.0.1:8080
You should see in the logs:
INFO sam-node [AuthN] Successfully authenticated with router via libp2p: ...
SAM Node Online.
PeerID: 12D3KooW...
Using Docker
Map the required ports (5001/udp, 5002/tcp for libp2p, and 8080/tcp for the local API):
mkdir -p $(pwd)/sam-data
docker run -d \
--name sam-node \
--user "$(id -u):$(id -g)" \
-v $(pwd)/sam-data:/data \
-p 5001:5001/udp \
-p 5002:5002 \
-p 8080:8080 \
-e SAM_API_TOKEN=my-secret-token \
ghcr.io/google/sam-node:latest \
run --data-dir /data --bind-addr 0.0.0.0:8080
Verify the node is running with docker logs sam-node.
3. Query the Local MCP API
Your SAM node exposes a standard Model Context Protocol (MCP) server. The easiest way to interact with it is using the mcp-client CLI tool (which is installed alongside sam-node):
List Local Control Plane Tools
Query the list of tools available on your local node (e.g. peer discovery, message broadcast, and remote tool execution):
mcp-client -url http://localhost:8080/mcp -token my-secret-token -list
Discover Remote Services in the Mesh
List active MCP services currently registered across the public mesh network:
mcp-client -url http://localhost:8080/mcp \
-tool discover_remote_services \
-args '{"type":"mcp"}'
Find Remote Tools on a Peer
Using a peer_id returned from the service discovery, find the tools available on that peer:
mcp-client -url http://localhost:8080/mcp \
-tool find_remote_tools \
-args '{"peer_id":"<target-peer-id>"}'
Call a Remote Tool
Call a tool hosted on a remote peer through your local node’s P2P stream reverse proxy:
mcp-client -url http://localhost:8080/mcp \
-tool call_remote_tool \
-args '{"peer_id":"<target-peer-id>","tool_name":"everything.get-sum","arguments":{"a":12.5,"b":7.5}}'
4. Teach Your AI Agent to Use the Mesh
Knowing the tools exist is not the same as knowing when and how to use them. sam-node ships an agent skill that tells your agent how to bring a node online, discover mesh services, call remote tools, and reach mesh inference models. Install it once:
sam-node skill install
This writes SKILL.md into the per-user skill directories your agents scan:
| Agent | Path |
|---|---|
| Claude Code, Claude Desktop | ~/.claude/skills/sam-mesh/SKILL.md |
| Google Antigravity | ~/.gemini/config/skills/sam-mesh/SKILL.md |
Useful variants:
sam-node skill install --project # install into this project (./.claude and ./.agents)
sam-node skill install --dir DIR # install into a specific skills directory
sam-node skill list # show where it is installed and whether it is current
sam-node skill show # print the document, for agents with a different layout
Re-run sam-node skill install after upgrading sam-node to refresh the document. Then connect your agent to the node’s MCP endpoint — see the integration guides — and restart it so both the skill and the tools load.