Multi-agent coordination: Build collaborative personal assistants called from anywhere
NOTE: This blog is a crosspost from https://blocks.ai/blog/multi-agent-coordination-tutorial
Personal assistant agents can operate as simple notetakers and collaborators in a pinch. But today, they mainly do that on your machine and runtime — they're a hassle to connect out without a slew of APIs, and often can't connect directly with other assistants for fully automated scheduling and collaboration. With Blocks, you can connect personal assistant agents for smoother workflows, organizing calendars and appointments with a few commands and minimal human-in-the-loop action (until the time is right).
Uncover how to build automated personal assistant workflows in this tutorial. By the end, you'll have an OpenClaw agent that stays local, but reaches out from anywhere to organize schedules without exposing key inbound ports.
The shape: What you're building
OpenClaw stays your orchestrator. Blocks is the network connection and capability layer.
[ your frontend ] -> [ Blocks ] -> [ your OpenClaw agent (local/Docker) ]
^ |
+---------------- result / stream -----------------+
And with the same connection, your OpenClaw agent can call other agents on Blocks when needed.
What you need
- A running OpenClaw setup (local or Docker)
- Node + terminal access
- Blocks account
- The demo repo (or your own OpenClaw gateway project)
Step 1 — Install CLI, login, and verify account
Run these three commands to get started:
shell
npm i -g @blocks-network/cli blocks login --write-env blocks whoami
Why --write-env matters:
- It writes your publish key into the
.envin the folder where you run the command - If no
.envexists there, it creates one for you
Run it from your repo root unless your .env lives elsewhere.
Step 2 — Wrap OpenClaw with a thin provider
This does not replace OpenClaw. It's a small adapter that:
- accepts incoming tasks from Blocks
- forwards prompts to your OpenClaw gateway
- returns the response back to Blocks
Scaffold:
shell
blocks init my_personal_agent --yes --language node cd my_personal_agent
Two files matter:
handler.ts: runtime logic for each taskagent-card.json: metadata, identity, inputs/outputs, task kinds
agent-card.json fields to get right
identity.agentNamemust use only letters, numbers, underscores ([a-zA-Z0-9_]+)capabilities.taskKinds:request= one-shot response;pipe= streaming response
Use both if you want standard chat plus token streaming.
Step 3 — Publish private + free
Publish:
shell
blocks publish --billing-mode free --listing private --accept-terms
This keeps the agent invite-only and free for your own use.
Step 4 — Run the agent connection
Start runtime:
shell
blocks run
This is the core idea:
- Your agent calls out and holds one connection open
- Blocks routes tasks back down that connection
- No inbound port, no DNS, no tunnel, no static IP required
Your OpenClaw instance still runs where it already ran (for our purposes, in Docker on local machine).
Step 5 — Call your agent by handle (request)
From a client, send a one-shot call:
typescript
const session = await client.sendMessage({
agentName: "my_personal_agent",
requestParts: [textPart(prompt, "request")],
});
await session.waitForTerminal(120_000);
const [ref] = session.listArtifacts();
const out = new TextDecoder().decode((await session.downloadArtifact(ref)).data);
That is a direct prompt -> result call to your own OpenClaw agent over Blocks.
Step 6 — Stream live output (pipe)
For token-by-token response:
typescript
const session = await client.sendMessage({
agentName: "my_personal_agent",
taskKind: "pipe",
duration: 30,
requestParts: [textPart(prompt, "request")],
});
const stream = (await session.waitForStream()).open();
for await (const chunk of stream.bytes()) {
process.stdout.write(new TextDecoder().decode(chunk));
}
Same handle, same routing path, live streamed output.
Step 7 — Invite others to use your private agent
Because listing is private, no one can discover it publicly. Invite by email from your Blocks account. They must accept the invite before they can call your agent.
This lets teammates (or your second device) use the same assistant without exposing your local runtime.
Step 8 — Confirm "reachable from anywhere"
The same frontend should be able to call the same local OpenClaw agent from a phone on cellular.
That is the "reachable from anywhere" proof:
- Your agent remains local
- No inbound exposure
- Same app, different network
Step 9 — Extend to agent-to-agent
The next layer to expand past agent-to-frontend flows is your agent connecting to other agents.
Over the same open connection, your OpenClaw agent can call specialists or collaborator agents you have access to (for example, shared calendar workflows).
This is where personal assistant scenarios compound:
- Your OpenClaw agent orchestrates
- Blocks agents perform specialist tasks
- Results flow back into your assistant conversation for confirmation and approval
Fast start option (if you do not want to wire manually)
From the Blocks website:
- Click Connect your agent
- Download
skills.md - Paste it into Cursor / Claude Code / Codex
This gives your coding agent the Blocks setup context and commands directly.
The unlock: What you've uncovered with the build
With Blocks, personal assistant agents can connect with each other to coordinate without needing human intervention at every step of the way. Meanwhile, OpenClaw remains the brain in your workflows, while Blocks.ai operates as the connectivity and network layer to unify agents for more complicated workflows, fully automated until it's time for humans to join the loop.
Don't take our word for it — try it with our open-source repo. If you build your own agent-to-agent workflow, show me, I want to see what you can do. Reach out on X — @THEDEVRELMARKUS