Skip to main content

Bittensor chain monitoring for AI agents.

Project description

Blockmachine Chainwake

Bittensor chain monitoring for AI agents.

Chainwake includes a watcher CLI and MCP server. A watcher invocation suspends until a Bittensor 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. Bittensor is the launch chain.


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.

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

chainwake bt subnet 19 price --below 0.05

Polls subnet 19's alpha price at the chain's natural per-block cadence. Exits 0 when the price crosses below 0.05 TAO, with stdout:

{
  "schema_version": 1,
  "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. The schema is at schemas/output-v1.json.

schema_version: 1 identifies a closed contract. Consumers must validate payloads against the matching schema and reject unknown fields. Any output shape change—including an additive field or status value—requires a new schema_version and a new schema file. The Chainwake package version is independent of the output-schema version; do not infer schema compatibility from the package version.


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

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 every command for higher-limit Blockmachine access or other authenticated RPC endpoints.

--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 runs a chainwake command and waits. While Chainwake watches the chain, that command stays pending. When the condition matches (or the watch reaches a limit), Chainwake exits; the agent is notified that the command finished and continues with the JSON result.

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.2.0.tar.gz (115.0 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.2.0-py3-none-any.whl (138.9 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for chainwake-0.2.0.tar.gz
Algorithm Hash digest
SHA256 f6bd1512d4482672f121da563dd4f266b4cadcbecdc185230a017122331723db
MD5 ee31b9d93e0e3db1fe4d72d8363bcb69
BLAKE2b-256 5e0870d1fba1ddd92d8b054bb35c69d5abd46f3fd8384f3b40b8be227d32d34a

See more details on using hashes here.

Provenance

The following attestation bundles were made for chainwake-0.2.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.2.0-py3-none-any.whl.

File metadata

  • Download URL: chainwake-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 138.9 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.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2661d131de293ac99da466d068d4cdd4a86fc5c0dadcbbcc1906619a1e7f8fe7
MD5 f3a5f1dca67075381830e210f587667b
BLAKE2b-256 aa60e8ef29cbfd0d9dad82487c0477bd97268fd8e808fcf4245ba2bc20fff4d2

See more details on using hashes here.

Provenance

The following attestation bundles were made for chainwake-0.2.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