# For agents (/docs/agents)

The SDK and CLI are built to be driven by agents. Every operation is
discoverable at runtime with a JSON schema, every mutation can be previewed
before it spends anything, every failure returns a machine-readable code with a
remediation hint, and a `Policy` can hard-bound what a session is allowed to
do. Nothing here requires parsing human prose.

## Searching these docs [#searching-these-docs]

Start with one fetch: [`/llms.txt`](/llms.txt). Every docs link in it is
already raw markdown (`content.md`), so you can open a page without rewriting
URLs or scraping HTML.

```bash
# Curated index (start here)
curl -s https://www.bittensor.com/llms.txt

# Full docs corpus (for rg, not for stuffing into context)
curl -s https://www.bittensor.com/llms-full.txt | rg -n '<pattern>'

# One page (same URLs as the links inside llms.txt)
curl -s https://www.bittensor.com/llms.mdx/docs/quickstart/content.md

# Chain source: search by symbol, or fetch a known path
curl -s 'https://www.bittensor.com/code/search.json?q=do_move_stake'
curl -s https://www.bittensor.com/code/raw/pallets/subtensor/src/staking/move_stake.rs

# Heavy exploration: clone the repo (docs live in docs/)
git clone --depth 1 https://github.com/RaoFoundation/subtensor
```

Prefer that index plus the JSON catalogs below over dumping
[`/llms-full.txt`](/llms-full.txt) into context.

## Discover the operations [#discover-the-operations]

```bash
btcli tools        # JSON: every transaction op + summary, description, signer, input schema
```

```python
import bittensor as bt
bt.intents.list_tools()   # same catalog, as Python dicts
bt.reads.list_reads()     # every read: name, params, docs, category
```

The same catalogs are published statically by these docs:
[`/catalog/intents.json`](/catalog/intents.json),
[`/catalog/reads.json`](/catalog/reads.json),
[`/catalog/errors.json`](/catalog/errors.json). Each entry includes
`docs_url` (HTML), `markdown_url` (raw markdown to fetch), and often
`sources` / `hits` with a `raw_url` into `/code`. Errors live under
`.codes` (semantic) and `.chain_errors` (exact pallet names); see `.note`.

## Execute by name [#execute-by-name]

An agent never needs to import intent classes — build and execute by op name
with a plain dict, validated against the schema:

```python
async with bt.Subtensor() as client:
    result = await client.execute_tool(
        "transfer", {"dest_ss58": "5F...", "amount_tao": 1.0}, wallet
    )
```

On the CLI, every op in the catalog is `btcli tx <op-name>` (underscores
become dashes) and every read is `btcli query <name>`.

## Preview before you spend [#preview-before-you-spend]

`plan` (SDK) and `--dry-run` (CLI) run the full pipeline — fee estimation,
predicted effects, warnings, policy check — without submitting:

```python
plan = await client.plan(intent, wallet)
plan.fee        # estimated fee
plan.effects    # list[str]: what this will do
plan.warnings   # non-fatal cautions (e.g. dust amounts)
plan.ok         # would policy allow it?
```

## Bound the blast radius with Policy [#bound-the-blast-radius-with-policy]

Attach a `Policy` to the client and every execution — by class, by name, or
raw — passes through one choke point:

```python
policy = bt.Policy(max_spend_tao=5.0, allowed_netuids=[1, 2])
async with bt.Subtensor("finney", policy=policy) as client:
    ...  # anything exceeding the caps raises PolicyError at execute time
```

Operations whose cost cannot be bounded ahead of time (e.g. subnet
registration, whose price floats) are blocked by a spend cap until it is
raised — the safe default. Raw calls are refused unless the policy sets
`allow_raw_calls=True`.

## Branch on failures, don't parse them [#branch-on-failures-dont-parse-them]

Every write returns an `ExtrinsicResult`; failures carry a semantic
[`ErrorCode`](/docs/errors) and a remediation hint:

```python
result = await client.execute(intent, wallet)
if not result.success:
    match result.error.code:
        case bt.ErrorCode.RATE_LIMITED:   ...  # wait and retry
        case bt.ErrorCode.INSUFFICIENT_BALANCE: ...  # reduce amount
        case _:
            log(result.error.remediation)   # actionable next step, always present
```

## CLI rules for non-interactive use [#cli-rules-for-non-interactive-use]

* `--json` on any command produces machine-readable output.
* `--yes` skips confirmation prompts. Without it, a non-interactive session is
  **declined, not blocked** — the CLI never hangs waiting for input it can't get.
* `--dry-run` previews any `tx` command.
* Configuration comes from flags, `BT_*` environment variables, or
  `btcli config` — highest to lowest precedence.

## The escape hatch [#the-escape-hatch]

Anything on chain that no intent wraps (deprecated, root/admin-only, or
off-chain-signed calls) is still reachable:

```python
call = bt.calls.Commitments.set_commitment(netuid=1, info={...})
await client.submit_call(call, wallet, signer="hotkey")
```

And generic accessors cover any storage item, constant, or runtime API in the
chain metadata:

```python
tempo = await client.query(bt.storage.SubtensorModule.Tempo, [1])
ed = await client.constant(bt.constants.Balances.ExistentialDeposit)
```
