Skip to main content

Bittensor and Ethereum chain monitoring for AI agents.

Project description

Blockmachine Chainwake

Chain monitoring for AI agents, starting with Bittensor and Ethereum.

Chainwake includes a watcher CLI and MCP server. A watcher invocation suspends until a chain-state condition fires, then exits with a structured JSON payload. It is observation-only: no keys, no signing, no extrinsic submission.

Agents spawn a chainwake watcher as a subprocess and parse stdout to decide what to do next. The exit code is for shell-level control flow; the JSON is where the detail lives.


Install

Install the stable CLI in an isolated environment with uv:

uv tool install chainwake

Or install it in the active Python environment:

pip install chainwake

To try unreleased code or contribute, install the current GitHub source:

uv tool install git+https://github.com/taostat/chainwake.git

Quickstart

All three examples run against a live Bittensor node. Set CHAINWAKE_BT_RPC_URL or pass --rpc-url; the default is wss://rpc.blockmachine.io. Enable shell completion: chainwake --install-completion.

Ethereum works without configuration through the anonymous public endpoint. Watch the EIP-1559 base fee in gwei, or wait for a transaction receipt:

chainwake eth network base-fee --below 10
chainwake eth tx 0x0123...abcd
chainwake eth tx 0x0123...abcd --confirmations 3
chainwake eth tx 0x0123...abcd --finality finalized

The watcher reads one baseline, subscribes to newHeads, and then reads each notified block by its exact hash. Use --above, --drop-pct, --rise-pct, or --move-pct for other base-fee conditions; delta windows may use time or blocks. Transaction watches default to one canonical confirmation and return success or reverted, gas used, and effective gas price. A missing receipt remains pending; Chainwake does not guess that it was dropped or replaced.

1. Threshold — wait until subnet price drops below 0.05 TAO

chainwake bt subnet 19 price --below 0.05

Add --durable when the watcher must outlive the shell or agent turn that created it:

chainwake --json --durable \
  --context "Tell me the observed price and block." \
  bt subnet 19 price --below 0.05

Chainwake persists the validated watcher, starts its local supervisor, prints the job id, and exits immediately. A host can wait without polling the chain:

chainwake --json jobs wait <job-id>

The completion contains the supplied context and the normal watcher result. Use jobs list, jobs show, and jobs cancel to manage persisted jobs. Because job arguments are stored locally, durable mode rejects literal --api-key and --rpc-url values; configure CHAINWAKE_BT_API_KEY or CHAINWAKE_BT_RPC_URL in the supervisor environment.

Subscribes to subnet 19's TAO and alpha pool reserves and recomputes the price when either changes. Exits 0 when the price crosses below 0.05 TAO, with stdout:

{
  "status": "matched",
  "watcher": { "chain": "bt", "resource": "subnet", "resource_id": "19",
               "sub_resource": "pool.price", "name": null,
               "primitive": "threshold",
               "invocation": ["chainwake", "bt", "subnet", "19", "price",
                              "--below", "0.05"] },
  "condition": { "operator": "below", "target": 0.05 },
  "observed": { "path": "subnet.19.pool.price", "value": 0.0487,
                "block": 4291820, "block_hash": "0xabc...",
                "timestamp": "2026-05-06T10:00:00Z" },
  "budget": { "runtime_ms": 3210, "rpc_calls": 3, "estimated_ru_consumed": 3 },
  "process": { "pid": 12345, "started_at": "2026-05-06T09:59:57Z" }
}

budget.estimated_ru_consumed and --max-ru form a registry-estimated observation budget, not a provider billing cap. They intentionally exclude connection bootstrap, transient retries, and RPCs hidden inside the SDK.

2. Delta — wait until price drops 5% within a 1-hour window

chainwake bt subnet 19 price --drop-pct 5 --window-time 1h

Fires when the oldest price in the rolling 1-hour window is more than 5% above the current price. The window controls which samples are compared; it does not impose a runtime limit. --max-runtime alone controls when an unmatched watcher exits with timeout.

Omit the window to keep the first successful observation as an unexpiring baseline for this watcher:

chainwake bt subnet 28 burnrate --move-pct 1

3. Event — wait for a new subnet to be registered

chainwake bt event --type subnet-registered --max-runtime 24h

Subscribes to subnet registration events. Exits 0 on the first match with the event's decoded args in observed. Exits 1 if no event fires within 24 hours.


Exit codes

Agents parse JSON for detail; exit codes are for shell-level control flow.

Code status field Meaning
0 matched Condition fired
1 stopped / timeout / budget_exhausted Watcher finished without a match
2 user_error Invalid args, unknown resource
3 provider_error / auth_error RPC unavailable, or credentials/access required
4 internal_error Bug in chainwake

For watcher automation, pass --json; every watcher exit then emits a JSON payload on stdout, including watcher errors. Without that flag, an interactive TTY uses human-readable output automatically. Stderr carries diagnostics and is not part of the stable contract.


Output schema

Every watcher invocation run with --json emits exactly one JSON object on exit. Piped stdout also selects JSON automatically, but agents should use the explicit flag instead of depending on TTY detection. MCP configuration helpers, help/version output, and parsing before a watcher is selected are outside this watcher-envelope guarantee and use their documented formats. Current watcher output uses schemas/output.json.

schemas/output.json is the sole current output contract. Consumers must validate payloads against it and reject unknown fields. Output shape changes update the Pydantic models and this schema atomically.


Adapters (--out)

By default Chainwake uses human output on an interactive TTY and indented JSON when stdout is piped. Automation should pass --json explicitly. Use --out to redirect output:

# NDJSON to stdout, keep running after each match
chainwake bt subnet 19 price --below 0.05 --out stream

# Append NDJSON to a file
chainwake bt subnet 19 price --below 0.05 --out file:///tmp/watchers.ndjson

# Notify via Telegram (any apprise URI)
chainwake bt subnet 19 price --below 0.05 --out "tgram://bottoken/chatid"

--out is repeatable. Apprise supports ~100 notification destinations (Telegram, Discord, Slack, email, webhooks, and more). See the apprise URI reference for the full list.


MCP server

chainwake includes a built-in MCP server that exposes chain watchers as MCP tools for Hermes, OpenClaw, Claude Desktop, Cursor, and other MCP clients. Its exit-oriented catalogue maps each wired command to a tool; one filtered event tool covers both curated friendly names and raw Module.Event types. See the MCP guide.

chainwake mcp serve --stdio
chainwake mcp config hermes
chainwake mcp config openclaw

Configuration

Method Precedence Example
--rpc-url flag Highest --rpc-url wss://my-node:9944
CHAINWAKE_BT_RPC_URL env var Middle export CHAINWAKE_BT_RPC_URL=wss://...
Default (Blockmachine RPC) Lowest wss://rpc.blockmachine.io

For Ethereum, the equivalent environment variable is CHAINWAKE_ETH_RPC_URL; its default is wss://ethereum-rpc.publicnode.com. Both defaults are anonymous.

Blockmachine is the default RPC provider for Bittensor at launch. The free tier works anonymously, so no configuration is needed for a first watcher. No API key is required. The architecture also supports any Substrate-compatible WebSocket endpoint.

--api-key is accepted by watcher commands for higher-limit Blockmachine access or other authenticated RPC endpoints. Per-chain environment variables are CHAINWAKE_BT_API_KEY and CHAINWAKE_ETH_API_KEY.

--max-runtime accepts duration strings: 30s, 10m, 2h, 1d. Default is unbounded. Agent and automation calls should always set an explicit bounded runtime.


Agent integration

An agent starts a Chainwake process and ends its turn. While Chainwake watches the chain, no model or agent loop runs. When the condition matches (or the watch reaches a limit), Chainwake exits; a capable host wakes the originating agent with the JSON result.

Hermes users install taostat/chainwake from the dashboard's Plugins page. OpenClaw users install @blockmachine/chainwake from its Skills UI or with:

openclaw skills install @blockmachine/chainwake --global

Both integrations use native background-process completion notifications; they do not poll and do not keep an MCP request pending. See the agent integration guide.

Pass --json for this flow. Stdout is one valid JSON object, the exit code is always 0–4, and stderr is not parsed. Without --json, an interactive TTY is rendered as human-readable text.

import json, subprocess

proc = subprocess.run(
    [
        "chainwake", "bt", "subnet", "19", "price",
        "--below", "0.05", "--max-runtime", "5m",
        "--json",
    ],
    capture_output=True, text=True,
)
payload = json.loads(proc.stdout)
if proc.returncode == 0:
    print(f"Matched at block {payload['observed']['block']}")
elif proc.returncode == 1:
    print(f"No match: {payload['reason']}")  # timeout or budget_exhausted
elif payload["status"] == "auth_error":
    raise RuntimeError(
        "RPC access needs operator action; do not retry unchanged credentials"
    )

For MCP tools, parallel wakes, detached processes, and restart durability, see Agent integration and MCP integration.


Status

chainwake is in active development. See PROGRESS.md for in-flight work.


License — MIT


Links

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

chainwake-0.4.0.tar.gz (485.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

chainwake-0.4.0-py3-none-any.whl (167.0 kB view details)

Uploaded Python 3

File details

Details for the file chainwake-0.4.0.tar.gz.

File metadata

  • Download URL: chainwake-0.4.0.tar.gz
  • Upload date:
  • Size: 485.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for chainwake-0.4.0.tar.gz
Algorithm Hash digest
SHA256 866a3bfe25f15bc47a92a5ab587eb3acb0116ec399909c16993416acfc80beca
MD5 7cf5813b6a8bed1ee524b8a4abbe327b
BLAKE2b-256 e7f316fcf8167b93dfac48f55fd0e7a65e57c7ede132b7be49fe2691f87b92aa

See more details on using hashes here.

Provenance

The following attestation bundles were made for chainwake-0.4.0.tar.gz:

Publisher: publish.yml on taostat/chainwake

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file chainwake-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: chainwake-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 167.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for chainwake-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7be99cf111d48c41eab0fd027423a358df3aec2f7bcbb8442c598b57a658c599
MD5 434512c9bf8ffef38ce9e3e4828e3f01
BLAKE2b-256 2aeff097de7abdb238af39c15ae4f9e492bdc643744fdb65cdd6c7004730ab50

See more details on using hashes here.

Provenance

The following attestation bundles were made for chainwake-0.4.0-py3-none-any.whl:

Publisher: publish.yml on taostat/chainwake

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page