Skip to main content

Bittensor and EVM chain monitoring for AI agents.

Project description

Blockmachine Chainwake

Set a hook on chain state. Put your agent to sleep. Wake it the moment the chain moves.

Chain monitoring for AI agents across Bittensor, Ethereum, Base, and BNB Smart Chain. Chainwake is a watcher CLI and MCP server. One invocation watches one condition — a price threshold, a transaction reaching finality, an on-chain event — then exits with a single structured JSON payload. It is observation-only: no keys, no signing, no transaction submission.

An agent sets a chainwake hook on subnet 19's price, sleeps at zero token cost, then wakes when the price breaks 0.01 TAO, fetches TAO's USD price, and sends a Telegram report

Why

An agent that needs to react to chain state has two bad options today:

  • Poll in a loop. Every empty check burns model tokens and context, and the agent still reacts late.
  • Stay out of it. A human watches a dashboard and re-prompts the agent.

Chainwake is the third option. The agent starts a watcher and ends its turn. No model runs while the watcher waits — the hook lives in a cheap subprocess holding a WebSocket subscription. When the condition fires, the watcher exits with JSON on stdout and the host wakes the agent with the result. Tokens are spent only on the turns where something actually happened.

agent turn ──▶ chainwake watcher (no tokens) ──▶ condition fires ──▶ agent woken with JSON

What you can watch

Chain Examples
bt (Bittensor) TAO/USD and subnet prices, validator/neuron state, account balance and transfers, hyperparameter changes, chain events, epoch boundaries
eth (Ethereum) Transaction receipt, confirmations, finality; EIP-1559 base fee; ERC-20 USD prices
base (Base) Transaction finality (safe/finalized), L2 and L1 fee inputs; ERC-20 USD prices
bsc (BNB Smart Chain) Transaction confirmations and finality, gas price, BEP-20 USD prices

The full observable catalogue is in the CLI reference.

Install

uv tool install chainwake        # isolated install (recommended)
pip install chainwake            # or into the active environment

To try unreleased code: uv tool install git+https://github.com/taostat/chainwake.git. Enable shell completion with chainwake --install-completion.

Quickstart

Every command below blocks until its condition fires, then exits with one JSON payload. All defaults are anonymous public endpoints — no configuration, no API key needed for a first watcher.

Wait for a Bittensor subnet price to cross a threshold, or move 5% within an hour:

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

Watch TAO/USD directly:

chainwake bt network tao-price --below 180
chainwake bt network tao-price --move-pct 5 --window-time 1h

TAO/USD is a CoinGecko aggregate quote sampled every 60 seconds. It supports thresholds and percentage moves with a time window or watcher-start baseline.

The window controls which samples are compared; it does not impose a runtime limit. Omit it to keep the first successful observation as an unexpiring baseline. --max-runtime alone controls when an unmatched watcher exits with timeout.

Wait for an on-chain event:

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

Wait for an Ethereum transaction, or for the EIP-1559 base fee (in gwei) to get cheap:

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

Base and BSC use the same grammar with chain-specific finality and fees:

chainwake base tx 0x0123...abcd --finality safe
chainwake base network l1-blob-base-fee --below 2
chainwake bsc tx 0x0123...abcd --confirmations 12

Watch DAI by symbol on any supported EVM chain, or GRAM on Ethereum/BSC:

chainwake eth token DAI price --below 0.995
chainwake base token DAI price --above 1.005
chainwake bsc token GRAM price --rise-pct 10 --window-time 1h

Token symbols are resolved within the selected chain. If a symbol is ambiguous, pass its contract address instead. Prices are CoinGecko aggregate USD quotes, sampled every 60 seconds by default; set CHAINWAKE_COINGECKO_API_KEY only if anonymous requests hit CoinGecko's rate limit.

Fee and transaction watchers subscribe to newHeads and pin reads to the notified block. Transaction watches report success or reverted, gas used, and effective gas price; a missing receipt stays pending — Chainwake never guesses that a transaction was dropped or replaced.

The payload

A matched watcher exits 0 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" }
}

The payload contract is schemas/output.json — the sole current output contract, regenerated from the Pydantic models and CI-checked. Consumers should validate against it and reject unknown fields.

Waking your agent

MCP (Hermes, OpenClaw, Claude Desktop, Cursor)

The built-in MCP server exposes every watcher as an MCP tool:

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

Hermes users install taostat/chainwake from the dashboard's Plugins page; OpenClaw users run openclaw skills install @blockmachine/chainwake --global. Both use native background-process completion notifications — no polling, no long-held MCP request. See the MCP guide.

Subprocess

Any agent framework that can spawn a process can set a hook:

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

See the agent integration guide for parallel wakes, detached processes, and restart durability.

Durable jobs

Add --durable when the watcher must outlive the shell or agent turn that created it. Chainwake persists the watcher, starts a local supervisor, prints the job id, and exits immediately:

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

chainwake --json jobs wait <job-id>   # blocks without polling the chain

The completion carries your context plus the normal watcher result. Manage jobs with jobs list, jobs show, jobs cancel. Because job arguments are stored locally, durable mode rejects literal --api-key/--rpc-url values — use CHAINWAKE_BT_API_KEY / CHAINWAKE_BT_RPC_URL in the supervisor environment.

Notifications (--out)

Route results anywhere apprise can deliver (~100 destinations: Telegram, Discord, Slack, email, webhooks):

chainwake bt subnet 19 price --below 0.05 --out "tgram://bottoken/chatid"
chainwake bt subnet 19 price --below 0.05 --out stream            # NDJSON, keep running
chainwake bt subnet 19 price --below 0.05 --out file:///tmp/w.ndjson

--out is repeatable. See the apprise URI reference.

Exit codes

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

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

For a watcher invocation, automation should always pass --json; every watcher exit then emits one JSON envelope. Piped stdout also selects JSON, but do not depend on TTY detection. Without --json, an interactive TTY uses human-readable output. Help, version, and MCP configuration helpers are outside the watcher-envelope contract. Stderr carries diagnostics and is not part of the stable contract.

Configuration

Method Precedence Example
--rpc-url flag Highest --rpc-url wss://my-node:9944
Env var Middle CHAINWAKE_BT_RPC_URL, CHAINWAKE_ETH_RPC_URL
Anonymous default Lowest wss://rpc.blockmachine.io (bt), wss://ethereum-rpc.publicnode.com (eth)

Blockmachine is the default Bittensor RPC provider; the anonymous free tier needs no API key. Any Substrate-compatible WebSocket endpoint works. No API key is required for a first watcher. Pass --api-key (or CHAINWAKE_BT_API_KEY) for higher-limit access. Base and BSC default to wss://base-rpc.publicnode.com and wss://bsc-rpc.publicnode.com.

--max-runtime accepts 30s, 10m, 2h, 1d. Default is unbounded. Agent and automation calls should always set a bounded runtime. --max-ru and budget.estimated_ru_consumed form a registry-estimated observation budget, not a provider billing cap.

Documentation

Status

Chainwake is in active development. See PROGRESS.md for in-flight work. Issues and ideas: GitHub Issues.

License

MIT

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.5.0.tar.gz (656.6 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.5.0-py3-none-any.whl (176.8 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for chainwake-0.5.0.tar.gz
Algorithm Hash digest
SHA256 3965675def2f53b5a8baf6aaf0469dfd3aa550972c2b01ce63778286436b969a
MD5 dc2dbb1851fb3797df9e4aa070fa896e
BLAKE2b-256 73f17804189c75732ba82e49d047eddba3689853cd67c1affe52e8e4e72ace16

See more details on using hashes here.

Provenance

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

File metadata

  • Download URL: chainwake-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 176.8 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.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5098b0f785f3eb77aa2d14ea33410674406c5c814fbe2ab38fbce1138a180f11
MD5 2c812399f15e17fb3beda2b23e7e6259
BLAKE2b-256 eed14a55a667c8f6ba3cb120fee6fd7db089247047fa1da4a3df411147910e1f

See more details on using hashes here.

Provenance

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