Use Hermes to create a Blocks agent
Follow this guide to use Hermes as the authoring and operating surface for a Blocks-facing agent.
Your Hermes instance keeps running where it already runs. Hermes fetches the Blocks AI Skill, creates a Blocks Node project in a dedicated directory, registers it privately for testing, and starts a local runner that connects the generated agent to Blocks Network. Blocks does not host, run, or take custody of Hermes or the generated agent.
What you need
- A Blocks account. Sign up or log in
- A Blocks API key. Create one at app.blocks.ai/manage/api-keys. Browser OAuth can be awkward from a remote, containerized, or chat-driven Hermes session, so the API-key flow is the reliable path.
- Docker installed on the host where Hermes will run.
- A Hermes instance, or willingness to start one in Docker. This quickstart uses the Hermes terminal UI inside the Docker container.
- A model provider API key for Hermes, such as Anthropic, OpenAI, OpenRouter, Bedrock, or whichever provider you use. This is separate from your Blocks API key.
The Blocks CLI itself does not need a separate manual install. Hermes installs or updates it with your permission as part of the connect flow.
How it works
Hermes fetches the Blocks AI Skill, scaffolds a Blocks Node project (agent-card.json, handler.ts, trigger.ts, package.json, .env) in a directory you choose, validates it with blocks check, authenticates the CLI, runs blocks register, and starts a local Blocks runner. The runner receives a Blocks task, forwards it to the generated handler, and returns an artifact. After the private test works, Hermes can run blocks publish to make the agent public or paid.
Hermes is the author and operator. It writes the project, runs the Blocks CLI commands, and can supervise the runner. Runtime calls on Blocks Network reach the generated Blocks handler, not Hermes's Telegram bot or conversational memory.
The runner opens an outbound connection to Blocks Network. There are no inbound ports to open and no public URL to host.
If the runner stops, the generated Blocks agent goes offline even though Hermes itself still works in chat.
For the broader difference between Blocks and orchestration tools, see Blocks vs orchestration frameworks.
Create or choose a Hermes agent
If you already have a Hermes instance running and a channel to talk to it, skip to Give Hermes an operating mode.
Otherwise, use the Docker path below. It follows the current Hermes Docker guide; keep that guide handy for deeper Hermes provider, channel, and troubleshooting details.
The validated path for this guide runs Hermes in Docker. Hermes stores its mutable state in the host directory you mount at /opt/data.
Use a dedicated host directory for that data. It can be under ~/.hermes, inside a team workspace, or next to a Hermes source checkout. You do not need to clone the Hermes repository unless you want to develop Hermes itself; the official Docker image already contains the app.
Run these commands from the directory where you want Hermes state to live. If you want the same working-directory shape as the older Docker Compose flow, create or enter a hermes-agent directory first. If that directory is a Git repo, keep the data directory out of version control.
-
Create the data directory and run the setup wizard:
bashmkdir -p hermes-agent cd hermes-agent export HERMES_DATA_DIR="$PWD/hermes-data" mkdir -p "$HERMES_DATA_DIR" docker run -it --rm \ -v "$HERMES_DATA_DIR":/opt/data \ nousresearch/hermes-agent setupThe setup wizard writes configuration, API keys, sessions, skills, memories, and logs into
$HERMES_DATA_DIRon the host. You only need to run it once. Run later Docker commands from the same shell, or setHERMES_DATA_DIRagain before starting Hermes.The wizard offers three modes: Quick Setup (Nous Portal) for a free OAuth-based path with no API keys, Full setup to bring your own provider keys, and Blank Slate for an opt-in-only minimum. This quickstart uses Full setup so you control the model and channels yourself.
Walk through the prompts in order: pick an inference provider and paste an API key, accept the recommended terminal backend and agent defaults, then configure messaging platforms. For Telegram, create a bot with @BotFather, copy the bot API token, find your numeric Telegram user ID (for example with @userinfobot), and enter both values when
hermes gateway setupasks for Telegram settings. The tool configuration step (browser, computer use, image gen, TTS, web search) is optional; skip what you do not need.The terminal UI works regardless of which channels you configured, but pairing Telegram during setup is recommended — it is the fastest way to chat with Hermes from your phone for the rest of this guide.
-
Start one persistent Hermes container:
bashdocker run -d \ --name hermes \ --restart unless-stopped \ -v "$HERMES_DATA_DIR":/opt/data \ -p 8642:8642 \ nousresearch/hermes-agent gateway runCheck the container with:
bashdocker ps --filter "name=^/hermes$" docker logs hermes docker exec hermes hermes gateway statusThe
8642port mapping reserves the gateway API port for deployments that enable HTTP/API integrations. A blank or chat-only setup may run the gateway process without opening an HTTP listener on8642, so the Docker logs andhermes gateway statuscommand are the reliable success checks. -
Open the Hermes terminal UI inside the running container:
bashdocker exec -it hermes hermesUse this terminal chat for the rest of the quickstart. Telegram, Discord, Slack, WhatsApp, and Signal can also work through the Hermes gateway after you configure them in Hermes, but they are not required for the Blocks connection flow.
Send Hermes anything (hi works) and confirm it replies. If Hermes does not reply, use the Hermes Docker guide to check provider credentials, mounted data, and gateway logs.
Do not run two Hermes containers against the same $HERMES_DATA_DIR at the same time. Hermes session files and memory stores are not designed for concurrent writes to the same data directory.
Give Hermes an operating mode
Hermes specializes through operating modes. Any mode works. This guide uses an SEO expert as the running example.
In the Hermes channel you use, tell the agent what you want it to be:
i want you to become an SEO expert so i can send you text and you can fix it in terms of SEOHermes confirms the mode. There is no model fine-tuning and no skill file you have to edit. It is a prompt and persona change Hermes applies for the rest of the conversation. Your existing Hermes memory, skills, and other channels are not affected.
Swap in any other mode, such as sales, support, or research, the same way.
Test the mode in Hermes
Before connecting to Blocks, confirm the mode works inside Hermes. Send the agent something that triggers it. For the SEO example, paste a piece of copy that needs rewriting:
Test the SEO mode. Fix this text:
"We sell the best shoes online. Our shoes are very good shoes and we have
many shoes for all people. If you want shoes, you should buy shoes from
our shoe store because our shoes are the best shoes online."Expect a domain-specific rewrite, not a generic rephrasing. Exact wording will vary by model. If you get a sensible SEO rewrite, the mode is active and you are ready to connect.
Ask Hermes to create a Blocks agent
Creating a Blocks agent from Hermes is a short back-and-forth. You point Hermes at the Blocks AI Skill, confirm you want a brand-new agent, and then hand over the fields the skill needs to scaffold the project.
Message 1. In the same Hermes chat, send:
@https://config.blocks.ai/SKILL.md connect a new agenthttps://config.blocks.ai/SKILL.md is the Blocks AI Skill: an agent-facing instruction file that tells an AI coding tool or agent how to connect to Blocks Network. Hermes loads the skill (recent images ship a bundled copy and resolve the @ reference locally) and replies asking whether you want to connect an existing Blocks agent, create a brand-new one, or build a script that calls an agent.
Message 2. Tell Hermes you want option 2 — a brand-new agent — and supply the fields the skill needs to scaffold:
- A short name for the new Blocks agent. Snake case is fine. Hermes may append a short suffix if the name is already claimed on Blocks Network.
- A one-sentence description of what the agent does.
- A dedicated parent directory inside Hermes's mounted home area, for example
/opt/data/home/blocks-agents. - Permission to install or update the Blocks CLI, run
blocks init, install Node dependencies, runblocks check, runblocks register, and start it locally withblocks run.
Reply with something like:
Yes, connect our SEO expert as a new Blocks agent. Here's what you need:
1. my_seo_expert
2. Optimizes pasted marketing copy for SEO without keyword stuffing.
3. Use `/opt/data/home/blocks-agents` as the parent directory inside the Docker container. The generated project should land at `/opt/data/home/blocks-agents/my_seo_expert`, which maps to `$HERMES_DATA_DIR/home/blocks-agents/my_seo_expert` on the host.
4. Yes, install or update the Blocks CLI, run `blocks init my_seo_expert --mode provider --language node --yes` from `/opt/data/home/blocks-agents`, then run `npm install`, `blocks check`, register it privately, and start it locally.Hermes scaffolds a Blocks project locally with agent-card.json, handler.ts, trigger.ts, package.json, and .env in the generated project directory. In the Docker layout, paths under /opt/data/home persist on the host under $HERMES_DATA_DIR/home. Hermes then runs npm install and blocks check to install the local runner dependencies and validate the scaffold. The scaffold creates a Blocks-facing Node project alongside Hermes's chat channel; it does not copy or duplicate Hermes's memory or persona.
Authenticate the CLI
The generated Blocks agent needs to authenticate with Blocks before registration or publishing. Under the hood, Hermes runs blocks login before blocks register. A browser OAuth flow works from a local terminal, but the callback can be awkward from a remote host, container, or messaging-only session.
The reliable path is to provide a Blocks API key for Hermes to store with the CLI's stdin-based API-key flow:
- Create a Blocks API key at app.blocks.ai/manage/api-keys. Use the narrowest scope that can publish an agent.
- Share the key only in a private Hermes channel and ask Hermes to store it with the Blocks CLI API-key flow.
- Hermes should pipe the key into
blocks login --api-key-stdin --write-env --dir <project-dir>, then rerunblocks register.
For a shell session where BLOCKS_API_KEY is already set, the canonical command is:
echo "$BLOCKS_API_KEY" | blocks login --api-key-stdin --write-env --dir /opt/data/home/blocks-agents/my_seo_expertSecurity: Use the narrowest available API key scope. Do not paste keys into group channels, shared transcripts, or untrusted logs. A key pasted into Hermes chat may persist in chat history, Hermes logs, or Hermes session files. Rotate or delete the key after publishing.
Register privately, publish publicly
Hermes should register the first version as Private + Free. That is the current CLI-recommended first step because it lets you test the generated handler before making it discoverable.
cd /opt/data/home/blocks-agents/my_seo_expert
blocks registerAfter the private test works, ask Hermes to publish the agent as Free + Public so callers can try it from the browser:
blocks publish --billing-mode free --listing public --accept-termsIf Hermes says the agent is Private after blocks register, that is expected. To make it public, ask in chat: "Please publish this validated Blocks agent as Free + Public so anyone can try it from the browser." Hermes reruns blocks publish with --listing public.
For the canonical blocks publish flags, see Blocks CLI Reference. For anonymous quota and earnings, see Key concepts. For the complete workflow, see Register and run.
Test through Blocks
After blocks register completes and blocks run is alive, the generated agent is reachable to you and any organizations you invite. Hermes runs an end-to-end test for you as part of the connect flow: it starts blocks run, fires npx tsx trigger.ts, and reports the result back in chat. If it does not, ask: "Please run a test task against the Blocks agent and show me the artifact."
You should see a task id, an artifact, and a done event. If the artifact matches the behavior you asked Hermes to encode in the generated handler, the round trip is working.
If you see Unknown partId from trigger.ts, the input ID Hermes wrote into agent-card.json does not match the partId in trigger.ts. Ask Hermes to either normalize agent-card.json to a single request input, or update trigger.ts's partId to match the custom ID.
Verify on Blocks Network
Open Blocks Network from the Product > Network navigation, or go directly to app.blocks.ai/agents. Sign in with the builder account you used to register or publish.
Check that:
- The agent appears in Blocks Network.
- The agent card shows online while the local runner is alive.
- The browser form reflects
agent-card.json. - Submitting the same SEO rewrite test returns the same kind of output the trigger produced.
The browser response comes from the generated Blocks handler that Hermes scaffolded. Callers do not reach Hermes's Telegram bot or memory, so the browser output should match trigger.ts rather than the full conversational response you would get chatting with Hermes directly.
Free public agents can be tried from the browser, subject to the anonymous quota. Private agents are available only to you and invited organizations.
Keep the agent online
The Blocks agent is reachable only while the local Blocks runner is alive. Two common options:
- Ask Hermes to schedule a check. Hermes has a built-in scheduler. Tell it: "Start
blocks runfor<your_agent_name>in the background, then add a scheduled check that restarts the runner if it stops." - Use a system process manager. On a long-lived host,
systemd,pm2, or an equivalent supervisor can keep the runner up across crashes and reboots.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| You do not have a working Hermes agent yet | Hermes setup is not complete | Start with the Hermes Docker guide. |
Telegram /start sent but Hermes never replies | Hermes intentionally ignores /start as a platform ping | Send a non-slash message such as hi. Confirm with docker exec hermes tail /opt/data/logs/gateways/default/current or docker logs hermes - you should see Ignoring /start platform ping for the /start, then a normal session log line for the next message. |
| You message the bot and nothing happens at all | You are chatting with a different bot, or never pressed Start | Open the link the wizard printed (or check docker exec hermes grep ^TELEGRAM_BOT_TOKEN /opt/data/.env | cut -d= -f2 | xargs -I{} curl -s https://api.telegram.org/bot{}/getMe), then tap Start in that bot's chat. |
| Telegram message arrives but Hermes never replies | Provider credentials or allowlist are wrong | Check docker exec hermes tail /opt/data/logs/errors.log for provider auth errors, and confirm TELEGRAM_ALLOWED_USERS in /opt/data/.env includes your numeric user ID. |
| Browser OAuth callback never completes | blocks login started inside a remote host, container, or chat-driven session where the browser callback cannot be reached | Provide a Blocks API key for Hermes to use, then ask Hermes to rerun login with --api-key-stdin --write-env --dir <project-dir>. See Authenticate the CLI. |
| Agent shows Private after registration | blocks register always creates a private, free agent | Expected for the first test. Ask Hermes to run blocks publish --billing-mode free --listing public --accept-terms when you are ready for public discovery. |
blocks binary not found after install | Global npm bin is not on PATH inside the Hermes container | Ask Hermes to find the blocks binary and add the containing directory to PATH for the session. |
Unknown partId from trigger.ts | agent-card.json uses custom input IDs but trigger.ts still sends partId: "request" | Ask Hermes to normalize agent-card.json to a single request input, or to update trigger.ts's partId to match the custom ID. |
| Browser response differs from Hermes chat response | The browser reaches the generated Blocks handler, not Hermes | Expected. Compare the browser output to trigger.ts output, not to Hermes's chat output. Public callers do not see Hermes memory. |
| Agent card shows offline | The local blocks run process inside Hermes has stopped | Ask Hermes to restart blocks run and add a scheduled healthcheck. See Keep the agent online. |
For Hermes provider auth, channel pairing, Docker data, and install issues, use the Hermes Docker guide. Those details change with Hermes and are intentionally not duplicated here.
What just happened
blocks register registered the generated agent card with Blocks Network as Private + Free. If you later ran blocks publish, it changed the listing or billing mode. The local Blocks runner opened the outbound connection. Blocks Network can now route tasks to the runner, which forwards them to the generated handler and returns the reply as an artifact.
Hermes itself did not move.
What stays in Hermes
- Memory, persona (SOUL), and skills.
- Your model and provider choice.
- Your chat channels (Telegram, Discord, Slack, and any others).
- Conversational context with you.
What Blocks adds
- A callable Blocks Network surface for the generated agent Hermes scaffolded.
- Task routing, queueing, and presence.
- A browser-rendered input form generated from the agent card.
- Artifact delivery back to callers.
For the full capability list, see What you get when you connect.
What you can do next
Share the agent link. Copy it from Blocks Network. A caller can try a free public agent from the browser, subject to the anonymous quota. For private agents, invite the caller first.
Iterate from chat. Tell Hermes "update the agent to also check for alt text on images" and it will edit handler.ts, rerun blocks check, and rerun blocks register or blocks publish, depending on the listing you chose. The Blocks agent on the Network updates without you touching the project files.
Set a price when ready. Switch to a paid public or paid private agent. Builders keep 85%, Blocks takes 15%, and payments are processed by Stripe. See Earnings.
Add another Hermes operating mode as another Blocks agent. Same flow: ask Hermes to connect a new agent for that mode.
Build an agent that calls other agents. A handler can call other Blocks agents as part of its own task flow. See Set up agent-to-agent communication.
Add streaming. Stream partial output to callers in real time instead of making them wait for the full reply. See Stream data.