Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 16 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@
<h1>ClawRouter for Hermes</h1>

<p>Hermes gives your agent a body. ClawRouter gives it a wallet.<br>
No provider accounts. No API keys. No credit card.<br><br>
Use a BlockRun account API key or x402 wallet payments.<br><br>
<strong>One Hermes provider, <!-- br:models.chatVisible -->76<!-- /br:models.chatVisible --> models from 12 labs, paid per request in USDC.</strong><br><br>
<em><!-- br:models.free -->7<!-- /br:models.free --> models free — no crypto, no balance, no signup required.</em></p>

<br>

<img src="https://img.shields.io/badge/🆓_6_Free_Models-success?style=for-the-badge" alt="6 free models">&nbsp;
<img src="https://img.shields.io/badge/🐍_Hermes_Plugin-black?style=for-the-badge" alt="Hermes plugin">&nbsp;
<img src="https://img.shields.io/badge/🔑_Zero_API_Keys-blue?style=for-the-badge" alt="No API keys">&nbsp;
<img src="https://img.shields.io/badge/🔑_API_Key_or_Wallet-blue?style=for-the-badge" alt="API key or wallet">&nbsp;
<img src="https://img.shields.io/badge/⚡_Smart_Routing-yellow?style=for-the-badge" alt="Smart routing">&nbsp;
<img src="https://img.shields.io/badge/💰_x402_USDC-purple?style=for-the-badge" alt="x402 USDC">&nbsp;
<img src="https://img.shields.io/badge/🔓_MIT-green?style=for-the-badge" alt="MIT licensed">
Expand All @@ -26,31 +26,33 @@ No provider accounts. No API keys. No credit card.<br><br>

[![Hermes](https://img.shields.io/badge/NousResearch-Hermes-000000?style=flat-square)](https://github.com/NousResearch/hermes-agent)
[![x402 Protocol](https://img.shields.io/badge/x402-Micropayments-purple?style=flat-square)](https://x402.org)
[![Base Network](https://img.shields.io/badge/Base-USDC-0052FF?style=flat-square&logo=coinbase&logoColor=white)](https://base.org)
[![Solana-first](https://img.shields.io/badge/Solana-first-9945FF?style=flat-square&logo=solana&logoColor=white)](https://solana.com)

[![Solana](https://img.shields.io/badge/Solana-USDC-9945FF?style=flat-square&logo=solana&logoColor=white)](https://solana.com)
[![Base Network](https://img.shields.io/badge/Base-USDC-0052FF?style=flat-square&logo=coinbase&logoColor=white)](https://base.org)
[![USDC Hackathon Winner](https://img.shields.io/badge/🏆_USDC_Hackathon-Agentic_Commerce_Winner-gold?style=flat-square)](https://x.com/USDC/status/2021625822294216977)
[![Telegram](https://img.shields.io/badge/Telegram-Community-26A5E4?style=flat-square&logo=telegram)](https://t.me/blockrunAI)

</div>

> **hermes-plugin-clawrouter** wires [NousResearch Hermes](https://github.com/NousResearch/hermes-agent) into [ClawRouter](https://github.com/BlockRunAI/ClawRouter), the open-source LLM router built for autonomous agents. One `pip install` gives Hermes <!-- br:models.chatVisible -->76<!-- /br:models.chatVisible --> chat models from OpenAI, Anthropic, Google, xAI, DeepSeek, Moonshot, Z.ai, MiniMax, Qwen, NVIDIA and more — plus image, video and web-search tools — behind a single local provider. Requests are scored across <!-- br:clawrouter.dimensions -->15<!-- /br:clawrouter.dimensions --> dimensions and routed to the cheapest capable model in under 1ms, cutting inference cost by <!-- br:savings.autoVsBaselinePct -->84<!-- /br:savings.autoVsBaselinePct -->% versus pinning Claude Opus 5. Authentication is a wallet signature, billing is USDC over [x402](https://x402.org) on Base or Solana, and <!-- br:models.free -->7<!-- /br:models.free --> models cost nothing at all. MIT licensed.
> **hermes-plugin-clawrouter** wires [NousResearch Hermes](https://github.com/NousResearch/hermes-agent) into [ClawRouter](https://github.com/BlockRunAI/ClawRouter), the open-source LLM router built for autonomous agents. One `pip install` gives Hermes <!-- br:models.chatVisible -->76<!-- /br:models.chatVisible --> chat models from OpenAI, Anthropic, Google, xAI, DeepSeek, Moonshot, Z.ai, MiniMax, Qwen, NVIDIA and more — plus image, video and web-search tools — behind a single local provider. Requests are scored across <!-- br:clawrouter.dimensions -->15<!-- /br:clawrouter.dimensions --> dimensions and routed to the cheapest capable model in under 1ms, cutting inference cost by <!-- br:savings.autoVsBaselinePct -->84<!-- /br:savings.autoVsBaselinePct -->% versus pinning Claude Opus 5. Authentication uses a BlockRun account API key with prepaid credits, or a wallet signature with USDC over [x402](https://x402.org) on Solana or Base, and <!-- br:models.free -->7<!-- /br:models.free --> models cost nothing at all. MIT licensed.

---

## Why this plugin exists

Stock Hermes wants a **provider block and an API key per lab**. Want Claude *and* GPT *and* Gemini *and* Grok? That's four accounts, four billing relationships, four keys to rotate, and a `config.yaml` that grows every time a new model ships.

Your agent can't do any of that. Agents can't open accounts or type in credit cards — they can only sign transactions.
Configure one BlockRun account API key for your agent, or let it pay directly with an x402 wallet.

ClawRouter collapses the whole thing into one provider:

- **Starts at $0** — <!-- br:models.free -->7<!-- /br:models.free --> free models, usable before you ever touch crypto
- **One provider, every lab** — Hermes' `/model` picker shows the full curated catalog, grouped by provider
- **No API keys** — the local wallet signature *is* authentication; you never hold a lab's key
- **API key or wallet** — one BlockRun account key, or local wallet signatures; no separate provider keys
- **No model babysitting** — `blockrun/auto` scores each request across <!-- br:clawrouter.dimensions -->15<!-- /br:clawrouter.dimensions --> dimensions and picks the cheapest model that can actually do the job
- **Pay per request** — USDC via x402 on Base or Solana; $5 covers thousands of calls, non-custodial
- **Same wallet for everything** — image, video and web-search tools bill through it too
- **Pay per request** — prepaid account credits, or non-custodial USDC payments via x402 on Solana or Base
- **Shared authentication** — image, video and web-search tools use the selected account or wallet mode
- **Fixes Hermes' auxiliary-vision breakage** — a single `api_key` provider on `127.0.0.1` sidesteps [#38679](https://github.com/NousResearch/hermes-agent/issues/38679) and [#38685](https://github.com/NousResearch/hermes-agent/issues/38685) ([how](#auxiliary-vision))

---
Expand Down Expand Up @@ -99,6 +101,12 @@ hermes plugins enable clawrouter

In a Hermes chat, open `/model` and choose **ClawRouter → `blockrun/auto`** for smart routing — or pin anything from the catalog, e.g. `blockrun/anthropic/claude-opus-5`, `blockrun/openai/gpt-5.6-terra`, `blockrun/free/nemotron-3.5-lightning`.

### Account API (no wallet)

Register at [user.blockrun.ai](https://user.blockrun.ai), create an [API key](https://user.blockrun.ai/dashboard/keys), and add [credits](https://user.blockrun.ai/dashboard/credits). Export `BLOCKRUN_API_KEY` before starting Hermes. The supervisor already passes the environment to ClawRouter; the shared `~/.blockrun/.api-key` is also understood by ClawRouter.

Account mode requires the ClawRouter release containing [PR #338](https://github.com/BlockRunAI/ClawRouter/pull/338). It supports routing, chat, media and data without creating a wallet. `/clawrouter wallet` remains for x402 users; account billing belongs to the credits portal. Wallet users should choose Solana first, then Base. Trading and wallet-signing features still require a wallet.

### 3. Fund the wallet (optional)

Free models need nothing. For paid models, create and fund the shared wallet:
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "hermes-plugin-clawrouter"
version = "0.3.20"
description = "ClawRouter for Hermes — 70+ models, x402 USDC micropayments, smart routing"
description = "ClawRouter for Hermes — account API or Solana/Base x402, smart routing"
readme = "README.md"
license = { text = "MIT" }
authors = [
Expand Down
14 changes: 14 additions & 0 deletions src/clawrouter_hermes/account.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
"""Read-only shared BlockRun account credential state."""
import os
from pathlib import Path
PORTAL="https://user.blockrun.ai"
def resolve_api_key():
if "BLOCKRUN_API_KEY" in os.environ:
key=os.environ["BLOCKRUN_API_KEY"].strip();source="env"
else:
path=Path.home()/".blockrun"/".api-key"
if not path.is_file(): return None
key=path.read_text(encoding="utf-8").strip();source=str(path)
if not key.startswith("brk_") or any(c.isspace() for c in key):
raise ValueError(f"Invalid BlockRun API key; create one at {PORTAL}/dashboard/keys. Wallet fallback refused.")
return {"source":source,"portal":f"{PORTAL}/dashboard/credits"}
10 changes: 7 additions & 3 deletions src/clawrouter_hermes/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from pathlib import Path
from typing import Iterable, List, Tuple

from . import models, proxy_supervisor, state, tools, wallet
from . import account, models, proxy_supervisor, state, tools, wallet

#: Distribution name as declared in ``pyproject.toml``. Kept as a constant so
#: tests can assert it still matches, since a typo would silently degrade
Expand Down Expand Up @@ -592,11 +592,15 @@ def _doctor(_: argparse.Namespace) -> None:
except (OSError, subprocess.SubprocessError) as exc:
rows.append(("Node >= 18", False, str(exc)))

rows.append(
account_info = account.resolve_api_key()
rows.append(("Account API or wallet configured", bool(account_info or wallet.MNEMONIC_FILE.is_file()), account_info["portal"] if account_info else str(wallet.MNEMONIC_FILE)))

if not account_info:
rows.append(
("Wallet mnemonic present",
wallet.MNEMONIC_FILE.is_file(),
str(wallet.MNEMONIC_FILE)),
)
)

if wallet.MNEMONIC_FILE.is_file():
mode = wallet.MNEMONIC_FILE.stat().st_mode & 0o777
Expand Down
11 changes: 11 additions & 0 deletions tests/test_account.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import importlib.util
from pathlib import Path
import pytest
MODULE=Path(__file__).parents[1]/"src"/"clawrouter_hermes"/"account.py"
def load():
spec=importlib.util.spec_from_file_location("account_isolated",MODULE);mod=importlib.util.module_from_spec(spec);spec.loader.exec_module(mod);return mod
def test_account_env_is_detected_without_wallet(isolated_home,monkeypatch):
monkeypatch.setenv("BLOCKRUN_API_KEY","brk_live_hermes_test");assert load().resolve_api_key()["source"]=="env";assert not (Path.home()/".openclaw"/"blockrun"/"mnemonic").exists()
def test_malformed_account_refuses_fallback(isolated_home,monkeypatch):
monkeypatch.setenv("BLOCKRUN_API_KEY","bad")
with pytest.raises(ValueError,match="fallback refused"):load().resolve_api_key()
Loading