Network Two Pis into a Distributed AI System
Connect two Raspberry Pis into a two-node AI network with shared inference.
Introduction
30 Second Summary
When you run AI on a single device, you're limited to that device's processing power and whatever models fit in its memory. But what if your devices could talk to each other and share their AI capabilities across the network?
In this project, you will network two Raspberry Pis into a distributed AI system where each Pi contributes different AI capabilities. You'll configure hostname discovery, set up cross-device model fallback chains, and build an automated workflow that delegates tasks between machines.
What You'll Build
A two-node AI network where Pi 1 (running Ollama and n8n in Docker) and Pi 2 (running OpenClaw with Cerebras) communicate over your local network to share AI inference and automate workflows across both machines.
By the end of this project, you'll have:
- mDNS hostname resolution configured on both Pis so they discover each other as pi-one.local and pi-two.local across reboots.
- Multi-provider model configuration in OpenClaw with Cerebras as primary and Ollama on Pi 1 as a free local fallback.
- A working n8n workflow on Pi 1 that sends tasks to OpenClaw on Pi 2 via HTTP Request and returns AI-generated responses, proving full cross-Pi communication.
- Secret Mission: Build a model router workflow in n8n that intelligently routes tasks to either Pi's AI based on task complexity.
Are there any prerequisites?
This project requires two completed prerequisite projects. Pi 1 must already have Docker with Ollama and n8n running (from the "Local AI Server on Raspberry Pi 5" project). Pi 2 must already have OpenClaw with Cerebras configured (from the "Deploy an AI Agent on Raspberry Pi" project).
Both Pis need to be connected to the same local Wi-Fi network before you begin.
Configure mDNS for Cross-Pi Discovery
Right now, your two Pis are strangers on the same Wi-Fi network. They can't find each other by name because neither one has a unique hostname or a way to broadcast it.
In this step, you'll set up mDNS (multicast DNS) using Avahi so both Pis can discover each other as pi-one.local and pi-two.local without relying on fragile static IPs.
In this step, get ready to:
- Set unique hostnames and install Avahi on both Pis.
- Configure mDNS resolution and open the firewall for discovery traffic.
- Test that both Pis resolve each other by hostname and confirm Ollama is reachable cross-Pi.
Set unique hostnames and install Avahi on both Pis
mDNS broadcasts a device's hostname with a .local suffix so other devices on the same network can find it. For this to work, each Pi needs a unique hostname and the Avahi daemon running.
- In your Pi 1 SSH terminal, set the hostname to pi-one by running this command:
sudo hostnamectl set-hostname pi-one
- Install the Avahi daemon and mDNS name resolution library on Pi 1 by running:
sudo apt install avahi-daemon libnss-mdns
What is Avahi?
Avahi is the Linux implementation of mDNS/DNS-SD (the same protocol macOS calls Bonjour). It lets devices advertise and discover services on a local network with zero configuration.
The libnss-mdns package hooks mDNS into the system's name resolution so commands like ping and curl can resolve .local addresses.
- Now switch to your Pi 2 SSH terminal.
- Set the hostname to pi-two by running:
sudo hostnamectl set-hostname pi-two
- Install Avahi on Pi 2 by running:
sudo apt install avahi-daemon libnss-mdns
- Restart the Avahi daemon on both Pis so the new hostnames take effect.
- Run this on Pi 1:
sudo systemctl restart avahi-daemon
- Run the same command on Pi 2:
sudo systemctl restart avahi-daemon
- Verify Avahi is running on each Pi by running this on both terminals:
sudo systemctl status avahi-daemon
You should see active (running) in the output on both Pis.
Avahi not starting?
If you see a failed status, try running sudo apt update && sudo apt install avahi-daemon libnss-mdns again to ensure the packages installed correctly.
If you're prompted to confirm installation with Y/n, type Y and press Enter.
Help me troubleshoot Avahi not starting on my Raspberry Pi
Configure nsswitch.conf and open the firewall for mDNS
Installing libnss-mdns usually updates /etc/nsswitch.conf automatically, but you should verify the configuration is correct. This file controls how your system resolves names.
- On Pi 1, open the nsswitch configuration file by running:
sudo nano /etc/nsswitch.conf
- Find the line that starts with hosts:.
- Make sure it reads:
hosts: files mdns4_minimal [NOTFOUND=return] dns
What does this line do?
This tells your system the order in which to look up hostnames.
- files checks /etc/hosts first.
- mdns4_minimal [NOTFOUND=return] resolves .local addresses using mDNS. If a .local name isn't found via mDNS, it stops immediately instead of falling through to DNS.
- dns handles everything else (regular internet domains).
- If the line already matches, no changes are needed. If it says hosts: files dns without the mDNS entry, add mdns4_minimal [NOTFOUND=return] between files and dns.
- Save the file with Ctrl+O, press Enter, then exit with Ctrl+X.
- Repeat the same check on Pi 2 by running:
sudo nano /etc/nsswitch.conf
- Confirm the hosts: line matches the same format. Edit if needed, then save and exit.
Pi 2 has UFW (Uncomplicated Firewall) active from the prerequisite project. mDNS uses UDP port 5353, so you need to allow that traffic through.
- On Pi 2, allow mDNS traffic through the firewall by running:
sudo ufw allow 5353/udp
- Verify the rule was added by running:
sudo ufw status
You should see 5353/udp listed with ALLOW in the output.
Why only Pi 2 needs the firewall rule
Pi 1 doesn't have UFW enabled (it wasn't required in the Local AI Server project). Pi 2 has UFW because the OpenClaw project locked it down for security. Without this rule, Pi 2 would silently drop mDNS packets and never appear on the network.
UFW rule not being added?
If you see a permission error, make sure you included sudo at the start of the command.
If UFW reports that it's inactive, that's fine. The rule is stored and will apply when UFW is next enabled.
Help me troubleshoot UFW on my Raspberry Pi
Test bidirectional hostname resolution
Everything is configured. Time to prove both Pis can actually find each other by name.
- On Pi 1, test that it can reach Pi 2 by running:
ping -c 3 pi-two.local
You should see three replies with response times, confirming Pi 1 can resolve and reach Pi 2.
- On Pi 2, test that it can reach Pi 1 by running:
ping -c 3 pi-one.local
You should see three replies confirming Pi 2 can resolve and reach Pi 1.
- Now verify that Ollama on Pi 1 is reachable from Pi 2 over the network. On Pi 2, run:
curl http://pi-one.local:11434/api/tags
You should see a JSON response listing the Ollama models installed on Pi 1 (including qwen3:1.7b).
What just happened?
That curl request traveled from Pi 2 across your local network to Pi 1, resolved pi-one.local via mDNS, and hit Ollama's REST API on port 11434.
This is the same path OpenClaw will use in the next step to send inference requests to Ollama. If this curl works, the entire networking layer is ready.
Ping or curl not resolving?
- Make sure both Pis are on the same Wi-Fi network. mDNS only works within the same network segment.
- Verify Avahi is running on both Pis with sudo systemctl status avahi-daemon. If it's not active, restart it with sudo systemctl restart avahi-daemon.
- Double-check that the hosts: line in /etc/nsswitch.conf includes mdns4_minimal [NOTFOUND=return] on the Pi that can't resolve the other.
- If the curl to Ollama specifically fails with "Connection refused", the Docker container may not be running. On Pi 1, run docker ps to confirm the Ollama container is up.
Help me troubleshoot mDNS resolution between my two Raspberry Pis
Your Pis can now find each other by name across reboots. Next up, you'll expose Ollama on Pi 1 so it can serve AI inference to any device on your network.
Expose Ollama on Pi 1 to the Network
Your two Pis can find each other by hostname. The next challenge is making Ollama's AI inference available across the network so Pi 2 can actually use it.
Ollama is already running inside Docker on Pi 1, but Docker's port mapping and the host firewall both need to allow external traffic. In this step, you'll confirm Docker is exposing the right port, open the firewall, and prove that Pi 2 can send inference requests to Pi 1.
In this step, get ready to:
- Verify Docker's port mapping and confirm the Qwen3 model is loaded.
- Open UFW on Pi 1 to allow Ollama traffic from your local network.
- Send a cross-Pi inference request from Pi 2 to Ollama on Pi 1.
Verify Ollama's Docker port mapping and loaded model
Docker containers only accept external traffic on ports that are explicitly mapped. You need to confirm that Ollama's port 11434 is bound to all network interfaces (not just localhost).
- Switch to your SSH terminal connected to Pi 1.
- Check Ollama's port mapping by running this command:
docker port ollama
You should see output like 11434/tcp -> 0.0.0.0:11434. The 0.0.0.0 means Docker is listening on all network interfaces, not just localhost.
What does 0.0.0.0 mean?
When Docker maps a port to 0.0.0.0, it accepts connections from any network interface on the host. This includes Wi-Fi, Ethernet, and other devices on your LAN.
If it showed 127.0.0.1:11434 instead, only Pi 1 itself could reach Ollama. Since the prerequisite project mapped the port as 11434:11434 in Docker Compose, it defaults to all interfaces.
- Confirm the Qwen3 1.7B model is loaded by running:
docker exec ollama ollama list
You should see qwen3:1.7b in the list of models. This is the model Pi 2 will call for inference later.
Don't see qwen3:1.7b in the list?
If the model isn't listed, it may not have been pulled in the prerequisite project. Pull it now by running docker exec ollama ollama pull qwen3:1.7b on Pi 1. This may take a few minutes to download.
If the Ollama container isn't running at all, start it with cd ~/ai-server && docker compose up -d on Pi 1.
Help me troubleshoot why Ollama isn't showing my model on Pi 1.
Open UFW on Pi 1 to allow Ollama traffic
Even though Docker exposes the port, the host firewall (UFW) might still block incoming connections from other devices. You need to allow TCP traffic on port 11434 from your local subnet.
- On Pi 1, first check if UFW is active by running:
sudo ufw status
✔️ UFW is active
UFW is running, so you need to add a rule to let Pi 2's traffic through.
- Find your local subnet by running:
ip -4 addr show wlan0 | grep inet
You'll see something like 192.168.0.105/24. The /24 tells you the subnet is the first three octets. Your subnet would be 192.168.0.0/24 (or whatever your first three numbers are).
- Allow TCP port 11434 from your local subnet by running:
sudo ufw allow from [[LOCAL_SUBNET="your subnet, e.g. 192.168.0.0/24"]] to any port 11434 proto tcp
You should see Rule added confirmed in the terminal.
ⓧ UFW is inactive
If UFW shows as inactive, the firewall isn't blocking anything. No action needed here. Move on to testing the connection from Pi 2.
Why restrict to the local subnet?
Opening port 11434 to your entire local subnet means only devices on your home Wi-Fi can reach Ollama. This is more secure than opening the port to the entire internet.
Since your Pis are on a home network behind a router, external traffic can't reach them anyway. The subnet rule adds defense-in-depth.
- Now switch to your SSH terminal connected to Pi 2.
- Test that Pi 2 can reach Ollama on Pi 1 by running:
curl http://pi-one.local:11434/api/tags
You should see a JSON response listing the models available on Pi 1's Ollama, including qwen3:1.7b.
Connection refused or timed out?
If you get "Connection refused", UFW on Pi 1 is likely blocking the port. Double-check the rule was added by running sudo ufw status on Pi 1 and looking for port 11434 in the list.
If you get "Could not resolve host", mDNS resolution isn't working. Verify by running ping pi-one.local from Pi 2. If that fails, restart Avahi on both Pis with sudo systemctl restart avahi-daemon.
Help me troubleshoot why Pi 2 can't reach Ollama on Pi 1.
Send a test inference request from Pi 2
Reaching the /api/tags endpoint proves network connectivity. Now you'll send an actual inference request to confirm Ollama can generate responses for Pi 2 over the network.
- On Pi 2, send a test prompt to Ollama on Pi 1 by running:
curl -X POST http://pi-one.local:11434/api/generate -d '{"model":"qwen3:1.7b","prompt":"Say hello","stream":false}'
This may take 10-30 seconds on the first call as Ollama loads the model into memory. You should see a JSON response with a response field containing generated text.
What does this prove?
This request travels from Pi 2, over your local Wi-Fi, to Pi 1's Docker container running Ollama. Ollama loads the Qwen3 1.7B model, generates a response, and sends it back to Pi 2.
You've just proven that Pi 2 can use Pi 1 as a remote AI inference server. This is the foundation for everything that follows.
Getting a slow or empty response?
The first inference after a model cold-start can take 30+ seconds on a Raspberry Pi. Wait for the full response before assuming something is broken.
If you see a 404 error or "model not found", confirm the model name matches exactly. Run docker exec ollama ollama list on Pi 1 and use the exact name shown in the output.
Help me debug why Ollama isn't returning a response to my inference request from Pi 2.
Pi 2 can now use Pi 1 as a remote AI brain. Next, you'll wire this connection into OpenClaw so it can automatically fall back to Ollama when Cerebras is unavailable.
Configure OpenClaw with Ollama Fallback
Pi 2 can now reach Ollama on Pi 1 over the network. That means Pi 2 has access to a free, local AI model sitting on the other machine.
Right now, OpenClaw on Pi 2 relies entirely on Cerebras for inference. If your internet drops, OpenClaw has nothing to fall back on. In this step, you'll add Ollama on Pi 1 as a secondary provider and configure a fallback chain so OpenClaw automatically routes to the local model when the cloud is unavailable.
In this step, get ready to:
- Add Ollama on Pi 1 as a provider in OpenClaw's configuration file.
- Configure a model fallback chain with Cerebras as primary and Ollama as backup.
- Test the fallback by disabling Cerebras and verifying Ollama takes over.
Add the Ollama provider to OpenClaw's config
OpenClaw stores its configuration in a JSON5 file at ~/.openclaw/openclaw.json. You'll add an ollama provider entry that tells OpenClaw where to find the Ollama API on Pi 1.
- Switch to your Pi 2 SSH terminal and open the config file by running:
nano ~/.openclaw/openclaw.json
You should see the existing configuration with your Cerebras provider already defined.
- Find the models section (or create it if it doesn't exist). Inside models.providers, add the following ollama block:
"ollama": {
"baseUrl": "http://pi-one.local:11434",
"apiKey": "ollama-local",
"api": "ollama",
"timeoutSeconds": 300,
"models": [
{
"id": "qwen3:1.7b",
"name": "qwen3:1.7b",
"params": {
"keep_alive": "15m"
}
}
]
}
What does this config do?
Each field tells OpenClaw how to connect to Ollama on Pi 1:
- baseUrl points at Pi 1's Ollama API using the mDNS hostname you configured earlier. No /v1 suffix because that breaks tool calling.
- apiKey is set to "ollama-local". OpenClaw accepts this marker for private-network and .local hosts without requiring a real credential.
- api is set to "ollama" to use the native Ollama API instead of the OpenAI-compatible endpoint.
- timeoutSeconds gives the small Qwen model up to 5 minutes to respond, which covers cold starts when the model is not already loaded in memory.
Why no /v1 in the URL?
OpenClaw's Ollama docs explicitly warn against using the /v1 OpenAI-compatible URL. That path breaks tool calling and can cause models to output raw tool JSON as plain text. Always use the base Ollama URL without a path suffix.
Configure the model fallback chain and restart
With the provider registered, you need to tell OpenClaw to use Cerebras as its primary model and fall back to Ollama when Cerebras is unavailable.
- In the same file, find the agents section (or create it). Add the defaults.model block with a primary and fallbacks array:
"agents": {
"defaults": {
"model": {
"primary": "cerebras/gpt-oss-120b",
"fallbacks": ["ollama/qwen3:1.7b"]
}
}
}
What does the fallback chain do?
OpenClaw tries the primary model first. If Cerebras is unreachable or returns an error, OpenClaw automatically routes the request to the first model in the fallbacks array.
The ollama/qwen3:1.7b reference tells OpenClaw to use the qwen3:1.7b model through the ollama provider you just configured.
- Save the file by pressing Ctrl+O, then Enter, then Ctrl+X to exit nano.
- Restart the OpenClaw gateway to apply the new config by running:
openclaw gateway restart
You should see output confirming the gateway has restarted successfully.
Gateway won't restart?
- If you see a validation error, check your JSON syntax. A missing comma or unmatched brace is the most common cause.
- Make sure the ollama block sits inside models.providers and the agents block is at the top level of the config object.
- If you see a file-not-found error, confirm the path is ~/.openclaw/openclaw.json and it exists.
Still stuck? Help me debug why my OpenClaw gateway restart is failing after editing the config file.
✔️ Awesome, I've got everything!
Great. Double check you saved the file and the gateway restarted without errors.
ⓧ I'd like to double check the full config
Your ~/.openclaw/openclaw.json should now include both the Ollama provider and the fallback chain. The exact structure depends on what was already in the file, but the new blocks you added should look like this:
{
"models": {
"providers": {
"ollama": {
"baseUrl": "http://pi-one.local:11434",
"apiKey": "ollama-local",
"api": "ollama",
"timeoutSeconds": 300,
"models": [
{
"id": "qwen3:1.7b",
"name": "qwen3:1.7b",
"params": {
"keep_alive": "15m"
}
}
]
}
}
},
"agents": {
"defaults": {
"model": {
"primary": "cerebras/gpt-oss-120b",
"fallbacks": ["ollama/qwen3:1.7b"]
}
}
}
}
Test the fallback behavior
The config is in place and the gateway is running. Now you'll verify that OpenClaw responds using Cerebras under normal conditions, then simulate a Cerebras outage to confirm the Ollama fallback works.
- Test that OpenClaw responds normally by sending a request to the hooks endpoint on Pi 2:
curl -X POST http://localhost:18789/hooks/agent \
-H "Authorization: Bearer your-hook-token-here" \
-H "Content-Type: application/json" \
-d '{"message": "Say hello in one sentence"}'
You should receive a response from Cerebras. It will arrive quickly because Cerebras processes inference in the cloud.
No response or connection refused?
- Make sure the OpenClaw gateway is running. Run openclaw gateway restart if needed.
- Check that you're using the correct hook token from your Pi 2 setup. You can find it in your OpenClaw hooks configuration.
- Verify the gateway port is 18789 by checking your OpenClaw config.
Still stuck? Help me debug why my curl to OpenClaw's hooks endpoint is not getting a response.
Now you'll simulate Cerebras going offline to confirm the fallback to Ollama on Pi 1.
- Temporarily remove the Cerebras API key from the environment and restart the gateway by running:
unset CEREBRAS_API_KEY
openclaw gateway restart
- Send the same test request again to trigger the fallback:
curl -X POST http://localhost:18789/hooks/agent \
-H "Authorization: Bearer your-hook-token-here" \
-H "Content-Type: application/json" \
-d '{"message": "Say hello in one sentence"}'
This time the response will be slower because it is coming from the Qwen 1.7B model on Pi 1 over your local network. You should still get a valid response.
What just happened?
With Cerebras unavailable, OpenClaw automatically tried the next model in the fallback chain: ollama/qwen3:1.7b. That routed the request across your local network to Pi 1's Ollama API.
Your distributed system just proved it can survive a cloud outage and keep responding using local inference.
- Restore your Cerebras API key and restart the gateway so everything is back to normal by running:
export CEREBRAS_API_KEY="your-cerebras-api-key-here"
openclaw gateway restart
Fallback not working?
- If you get no response at all, verify Pi 2 can still reach Ollama on Pi 1. Run curl http://pi-one.local:11434/api/tags from Pi 2 to check connectivity.
- If you see a timeout, the Qwen model may need to cold-start. Wait 30 seconds and try again. The timeoutSeconds: 300 in your config gives it up to 5 minutes.
- Check that your baseUrl uses http://pi-one.local:11434 with no /v1 suffix.
Still stuck? Help me figure out why OpenClaw is not falling back to Ollama on Pi 1 when Cerebras is unavailable.
Your distributed AI system now has built-in resilience. Cerebras handles requests at cloud speed when available, and Ollama on Pi 1 picks up the slack when it is not. Next up, you'll build an n8n workflow that ties both Pis together into an automated task pipeline.
Build the Cross-Pi n8n Workflow
Your two Pis can now find each other by hostname, and OpenClaw on Pi 2 has access to AI models on both machines.
The missing piece is orchestration. In this step, you'll build an n8n workflow on Pi 1 that receives a task via webhook, forwards it to OpenClaw on Pi 2, and returns the AI-generated response. This creates a distributed AI pipeline you can trigger with a single HTTP call.
In this step, get ready to:
- Create an n8n workflow with a Webhook trigger on Pi 1.
- Connect it to OpenClaw on Pi 2 via an HTTP Request node.
- Test the full cross-Pi inference loop from your Mac.
Create the workflow and add a Webhook node
n8n workflows start with a trigger node that defines how the workflow gets activated. You'll use a Webhook node so external services (or a simple curl command) can kick off the workflow by sending an HTTP request.
- Open your browser and navigate to http://pi-one.local:5678.
- Click the + button (or Create Workflow) to create a new workflow.
- Click the workflow name at the top and rename it to Distributed AI Router.
- Click Add first step on the canvas to open the node picker.
- Search for Webhook and select the Webhook node.
The Webhook node panel opens with its configuration fields.
- Set HTTP Method to POST.
- Set Path to distributed-ai.
- Under Respond, select Using 'Respond to Webhook' Node.
- Close the node panel by clicking the X or clicking on the canvas background.
Why use Respond to Webhook mode?
By default, a Webhook node responds immediately with a generic acknowledgement. Setting the response mode to "Using 'Respond to Webhook' Node" tells n8n to wait until a dedicated Respond to Webhook node executes later in the workflow. This lets you return the actual AI-generated response from OpenClaw instead of a generic confirmation.
Add the HTTP Request and Respond to Webhook nodes
The HTTP Request node will forward the incoming task to OpenClaw's hooks endpoint on Pi 2. OpenClaw expects a POST request with a JSON body containing a message field and a Bearer token for authentication.
- Click the + on the right edge of the Webhook node to add a connected node.
- Search for HTTP Request and select the HTTP Request node.
Configure the HTTP Request node with these settings:
- Set Method to POST.
- Set URL to http://pi-two.local:18789/hooks/agent.
- Toggle Send Headers on.
- Under Header Parameters, click Add Parameter.
- Set the Name to Authorization.
- Set the Value to Bearer followed by a space and then your Pi 2 hook token from the prerequisite project.
- Toggle Send Body on.
- Set Body Content Type to JSON.
- Select Using Fields Below for specifying the body.
- Click Add Parameter in the Body Parameters section.
- Set the Name to message.
- Set the Value to the expression {{ $json.body.task }} by clicking the expression toggle (the small gear/expression icon) and typing this expression.
What does this expression do?
The expression {{ $json.body.task }} pulls the task field from the JSON body that the caller sends to the Webhook. This dynamically maps whatever task description arrives into the message field that OpenClaw expects.
Now add the final node that sends the response back to the original caller.
- Click the + on the right edge of the HTTP Request node.
- Search for Respond to Webhook and select the Respond to Webhook node.
- In the node panel, set Respond With to All Incoming Items.
- Close the node panel.
What does the Respond to Webhook node do?
This node takes whatever data flows into it (in this case, the JSON response from OpenClaw on Pi 2) and sends it back as the HTTP response to whoever triggered the Webhook. The caller sees the AI-generated output directly in their terminal.
Your workflow canvas should now show three nodes connected in a chain: Webhook, HTTP Request, then Respond to Webhook.
Nodes not connected?
Make sure each node's output connector (right side) is linked to the next node's input connector (left side). You can drag a connection line between them if they aren't linked.
help me connect my n8n nodes in the Distributed AI Router workflow
Activate the workflow and test end-to-end
With all three nodes configured, you need to activate the workflow so n8n listens on the production Webhook URL. Then you'll send a test request from your Mac to prove the full cross-Pi loop works.
- Click the Active toggle in the top-right corner of the n8n editor to activate the workflow.
- Confirm the toggle turns on and the workflow shows as active.
Test URL vs Production URL
n8n generates two webhook URLs: a test URL (active for 120 seconds while you click "Listen for test event") and a production URL (active whenever the workflow is toggled on). By activating the workflow, you enable the production URL so it stays active across sessions.
- Switch to a terminal on your Mac and test the full pipeline by running this command:
curl -X POST http://pi-one.local:5678/webhook/distributed-ai -H "Content-Type: application/json" -d '{"task":"What is the uptime on this machine?"}'
What does this command do?
- It sends a POST request to n8n's Webhook on Pi 1 with a JSON body containing a task field.
- n8n receives it, extracts the task, and forwards it to OpenClaw on Pi 2 as a message.
- OpenClaw processes the task using Cerebras (or falls back to Ollama on Pi 1), generates a response, and sends it back through n8n to your terminal.
You should see a JSON response in your terminal containing the AI-generated output from OpenClaw. The response may take a few seconds depending on whether Cerebras or Ollama handles the request.
Getting a connection refused or timeout?
- Make sure the workflow is toggled to Active in n8n. The production webhook URL only works when the workflow is active.
- Verify Pi 2's UFW allows incoming connections on port 18789 from Pi 1's local network address. Run sudo ufw status on Pi 2 to check. If needed, add a rule for the local subnet.
- Confirm OpenClaw is still running on Pi 2 by SSHing into Pi 2 and running openclaw gateway restart.
- Check that the Bearer token in your HTTP Request node matches the hook token configured on Pi 2. A mismatch causes authentication failures.
help me troubleshoot my cross-Pi n8n workflow that is not returning a response from OpenClaw
Secret mission
Build a Model Router Workflow
Your distributed system works, but right now every task goes to OpenClaw on Pi 2. What if simple tasks like checking system status could be handled locally on Pi 1 without the network hop? Build a smarter n8n workflow that inspects each incoming task and routes it to the right Pi based on complexity.
Clean Up Your Resources
Clean Up Your Resources
This project runs entirely on your local network with no cloud resources or paid services. There are zero ongoing costs regardless of whether you leave everything running.
Decide whether to keep your resources running, pause them to come back later, or delete them entirely.
Resources you used:
- mDNS configuration on both Pis (hostnames, Avahi, nsswitch.conf). No cost, persists across reboots.
- OpenClaw Ollama provider configuration on Pi 2 (stored in ~/.openclaw/openclaw.json). No cost.
- n8n workflow "Distributed AI Router" on Pi 1 (stored in the n8n Docker volume). No cost.
Keep everything running
No action needed. Both Pis continue to find each other by hostname and the workflow stays active. Zero ongoing cost.
- Both Pis resolve each other as pi-one.local and pi-two.local across reboots.
- The n8n workflow remains active and ready to receive webhook requests.
- OpenClaw's fallback chain (Cerebras primary, Ollama fallback) stays configured.
Pause - I'll come back to this later
Shut down running processes on both Pis to free up memory and CPU. Your configurations are preserved and you can resume anytime.
- On Pi 1, stop the n8n and Ollama containers by running:
cd ~/ai-server && docker compose stop
- On Pi 2, stop the OpenClaw gateway by running:
openclaw gateway stop
- To resume later, run cd ~/ai-server && docker compose start on Pi 1 and openclaw gateway restart on Pi 2.
Delete - I don't want to use this again
Remove all project-specific configurations and revert both Pis to their pre-project state.
- On Pi 1, open n8n at http://pi-one.local:5678. Open the "Distributed AI Router" workflow, click the three-dot menu, and select Delete.
- On Pi 2, remove the Ollama provider block and fallback configuration from ~/.openclaw/openclaw.json. Delete the entire ollama object inside models.providers and revert agents.defaults.model to only reference cerebras/gpt-oss-120b without a fallbacks array.
- To revert hostnames on both Pis, run the following on each Pi (replacing the name with the original hostname):
sudo hostnamectl set-hostname original-hostname
- After reverting the hostname, restart Avahi to broadcast the change:
sudo systemctl restart avahi-daemon
What about Avahi and nsswitch.conf?
Avahi and the nsswitch.conf changes are harmless to leave in place. They enable mDNS resolution for any future .local hostname lookups on your network.
If you want a full removal, run sudo apt remove avahi-daemon libnss-mdns on both Pis and revert the hosts line in /etc/nsswitch.conf to remove mdns4_minimal [NOTFOUND=return].
Nice Work!
Nice Work!
You just built a fully self-controlled distributed AI network across two Raspberry Pis. Tasks flow from one machine to the other, AI inference happens wherever you decide, and not a single cloud vendor owns the pipeline.
Here's what you learned:
- Configured mDNS with Avahi on two Raspberry Pis so they reliably discover each other by hostname across reboots.
- Exposed Ollama on Pi 1 as a network-accessible AI inference endpoint for other devices on your LAN.
- Configured OpenClaw on Pi 2 with a multi-provider model chain: Cerebras (cloud, fast) as primary with Ollama on Pi 1 (local, free) as fallback.
- Built an n8n workflow on Pi 1 that sends tasks to OpenClaw on Pi 2 and returns AI-generated responses, proving full cross-Pi distributed AI inference.
- Secret Mission: Built a model router that intelligently sends simple tasks to local Ollama and complex tasks to Cerebras-powered OpenClaw across the network.
Ready to quiz yourself?