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

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 output-v1 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:

{
  "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 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.3.0.tar.gz (457.7 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.3.0-py3-none-any.whl (153.5 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for chainwake-0.3.0.tar.gz
Algorithm Hash digest
SHA256 591c90e7ec376e350860571a950bbadc395c8ccbf97648570984bc1e24fca86d
MD5 877c5db144948987acc7f41c6da5cd26
BLAKE2b-256 95eafe92687fd9bd364c2f2618103f57c3eaecb3e90c13dc9057738716640b7f

See more details on using hashes here.

Provenance

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

File metadata

  • Download URL: chainwake-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 153.5 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.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 de6ae8bf602064c9b97c565885a9fe96feeeb5c535a10af71425eb516d20d36a
MD5 ebd9c0f7cd09fdbaaf0b51b9886008e7
BLAKE2b-256 8c75a306a156ee54b9f1b437cd613eb37835d05c4a099f9c42610de9981a2ee4

See more details on using hashes here.

Provenance

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