> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kaleidoswap.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Build a Local AI Agent with RGB in 15 Minutes

> Run a signet RGB Lightning Node, connect it to kaleido-mcp, and drive it with a local QVAC model through KaleidoMind: check balances, receive and send USDT, quote and swap

This tutorial takes you from an empty machine to a local language model that reads and moves RGB assets on signet. Every piece runs on your computer: the model runs through [QVAC](https://www.npmjs.com/package/@qvac/sdk), the reasoning engine is [KaleidoMind](/ai-tools/kaleido-mind), the tools come from [`kaleido-mcp`](/ai-tools/mcp-servers), and the RGB Lightning Node runs in Docker through [KaleidoCLI](/cli/introduction). The only network calls go to your node, to the signet KaleidoSwap API, and to the Bitcoin and RGB services the node itself needs.

```
you ─▶ KaleidoMind (QVAC model, local) ─▶ kaleido-mcp (stdio) ─▶ RGB Lightning Node (Docker, signet)
                                                    └──────────▶ api.signet.kaleidoswap.com
```

<Note>
  Everything here runs on signet, with test coins that have no value. Do not reuse a seed or a password from this tutorial anywhere else.
</Note>

## Prerequisites

| Requirement | Why |
| - | - |
| Node.js 20+ | Runs `kaleido-mcp` and the KaleidoMind host |
| Python 3.10+ | Runs KaleidoCLI |
| Docker with Compose | Runs the RGB Lightning Node |
| A GitHub account | Signs you in to the RGB faucet |
| About 1 GB of free disk | For the local model and the node's data |

No API key and no hosted LLM are needed.

## 1. Start a Signet RGB Lightning Node

Install KaleidoCLI with its install script. It is not on PyPI yet, so `pip install` will not find it:

```bash theme={null}
curl -fsSL https://raw.githubusercontent.com/kaleidoswap/kaleido-cli/master/install.sh | sh
```

Create and start one node with the signet defaults, then initialise and unlock its wallet:

```bash theme={null}
kaleido setup          # creates and starts one signet node in Docker
kaleido node init      # once: sets the wallet password and prints the mnemonic
kaleido node unlock    # after every restart
kaleido node info      # confirms the node answers on http://localhost:3001
```

KaleidoCLI calls this network `mutinynet`; it is the same signet that the KaleidoSwap signet API and the RGB faucet use. Write down the mnemonic that `kaleido node init` prints.

<Tip>
  The [Node Environments](/cli/node-environments) page covers running several nodes, switching between them, and reading logs.
</Tip>

## 2. Fund the Node

RGB assets live on Bitcoin UTXOs, so the node needs a little signet BTC before it can receive anything.

<Steps>
  <Step title="Get signet BTC">
    Print an on-chain address and send it coins from the public [Mutinynet faucet](https://faucet.mutinynet.com):

    ```bash theme={null}
    kaleido wallet address
    ```

    Signet blocks arrive about every 30 seconds. Check with `kaleido wallet balance`.
  </Step>

  <Step title="Create UTXOs for RGB">
    Split some of that BTC into UTXOs that can hold RGB allocations:

    ```bash theme={null}
    kaleido wallet create-utxos
    ```
  </Step>

  <Step title="Get test RGB assets">
    Create an RGB invoice. Leave out the asset ID to accept any asset:

    ```bash theme={null}
    kaleido asset invoice
    ```

    Open the [KaleidoSwap RGB faucet](https://faucet.mutinynet.kaleidoswap.com), sign in with GitHub, and paste the invoice. Once the transfer confirms, `kaleido asset refresh` followed by `kaleido asset list` shows the asset.
  </Step>
</Steps>

## 3. Run kaleido-mcp on Signet

`KALEIDO_NETWORK=signet` points `kaleido-mcp` at `https://api.signet.kaleidoswap.com` and Spark's test network. Point `RLN_NODE_URL` at the node from step 1:

```bash theme={null}
KALEIDO_NETWORK=signet RLN_NODE_URL=http://localhost:3001 npx -y kaleido-mcp
```

The server logs `network: signet` and waits on stdio. You do not need to keep it running by hand: the agent in the next step starts it as a child process. `WDK_SEED` is optional here, and plain `npx` does not install the Spark wallet package; without them the Spark tools stay off and the RGB, DEX, payment and market tools still work. See [MCP Servers](/ai-tools/mcp-servers#network-preset) for every variable.

<Tip>
  Want to try the tools before writing any code? Add the same command to Claude Desktop or Claude Code with the config in [Client Configuration](/ai-tools/mcp-servers#client-configuration), then ask for your RGB balance. The rest of this tutorial swaps that hosted model for a local one.
</Tip>

## 4. Wire a Local QVAC Model with KaleidoMind

Create a project and install the engine, the QVAC SDK, and the MCP client:

```bash theme={null}
mkdir rgb-agent && cd rgb-agent
npm init -y && npm pkg set type=module
npm install @kaleidorg/mind @qvac/sdk @modelcontextprotocol/sdk
```

KaleidoMind works with `@qvac/sdk` 0.13 and later; installing the latest release is recommended. Save this as `agent.mjs`:

```js agent.mjs theme={null}
import { createInterface } from 'node:readline/promises';
import { completion, cancel, loadModel, QWEN3_600M_INST_Q4 } from '@qvac/sdk';
import { Funnel, ToolRegistry, confirmReadback } from '@kaleidorg/mind';
import { McpToolSource } from '@kaleidorg/mind/mcp';
import { createQvacProvider } from '@kaleidorg/mind/qvac';

// 1. kaleido-mcp on signet, launched over stdio
const kaleido = new McpToolSource({
  id: 'kaleido',
  transport: {
    kind: 'stdio',
    command: 'npx',
    args: ['-y', 'kaleido-mcp'],
    env: {
      PATH: process.env.PATH,
      HOME: process.env.HOME,
      KALEIDO_NETWORK: 'signet',
      RLN_NODE_URL: 'http://localhost:3001',
    },
  },
});
await kaleido.connect();

// 2. A local model through QVAC (downloaded on first run)
const modelId = await loadModel({
  modelSrc: QWEN3_600M_INST_Q4,
  modelType: 'llm',
  modelConfig: { ctx_size: 8192, tools: true },
});
const provider = createQvacProvider({ completion, cancel, getModelId: () => modelId });

// 3. The tiered funnel, with a confirmation prompt before any spend
const funnel = new Funnel({ provider, tools: new ToolRegistry([kaleido]) });
const rl = createInterface({ input: process.stdin, output: process.stdout });

while (true) {
  const text = await rl.question('\n> ');
  if (!text.trim()) continue;
  const out = await funnel.runTurn(text, {
    onConfirm: async (call) => {
      const answer = await rl.question(`${confirmReadback(call)} [y/N] `);
      return { approved: answer.trim().toLowerCase() === 'y' };
    },
  });
  console.log(out.text);
}
```

Run it:

```bash theme={null}
node agent.mjs
```

The first start downloads the model. Every fund-moving tool pauses on the `onConfirm` callback, so nothing leaves the node until you type `y`.

<Note>
  This is a minimal host. The [`@kaleidorg/mind` README](https://www.npmjs.com/package/@kaleidorg/mind) and the `examples/node-minimal` and `examples/rgb-agent` folders in the [kaleido-mind repository](https://github.com/kaleidoswap/kaleido-mind) go further, with skills, recipes, and a larger model. A 0.6B model handles the fast path and the recipes well; for open-ended requests a larger model such as Qwen3 1.7B or 4B does noticeably better.
</Note>

## 5. Prompts to Try

Go read-only first, then receive, then spend.

| Prompt | What runs |
| - | - |
| `What RGB assets does my node hold, and how much of each?` | `wdk_list_assets`, `wdk_get_asset_balance` |
| `Show my BTC balance on-chain and in Lightning.` | `wdk_get_balances` |
| `Create an RGB invoice to receive 10 USDT, using transport endpoint rpcs://proxy.iriswallet.com/0.2/json-rpc.` | `wdk_create_rgb_invoice` |
| `Send 5 USDT to this RGB invoice: <invoice>` | `wdk_send_asset` 🔒 |
| `Quote 100000 sats of BTC over Lightning into USDT over RGB Lightning. Do not execute.` | `kaleidoswap_get_quote` |
| `Swap 100000 sats into USDT with an atomic swap.` | `kaleidoswap_get_quote` → `kaleidoswap_atomic_init` → `wdk_atomic_taker` → `kaleidoswap_atomic_execute` 🔒 → `kaleidoswap_atomic_status` |

KaleidoMind may call the legacy `rln_*` names for the same tools; `kaleido-mcp` serves both.

To try a send without a second wallet, ask a friend for an RGB invoice, or create one on a second node with `kaleido node create`.

<Warning>
  An atomic swap settles over Lightning, so the node needs a channel with the KaleidoSwap maker that carries the asset. The quickest way to get one on signet is to buy it from the LSP: `Buy a channel from the KaleidoSwap LSP preloaded with 10 USDT` runs `kaleidoswap_lsp_quote_asset_channel` and `kaleidoswap_lsp_create_asset_channel`, which you pay on-chain. Allow a few blocks for the channel to open before you swap.
</Warning>

## Mock Mode: No Node, No Funds

To build the agent logic before the node is ready, or in CI, swap the MCP source for the stateful mock wallet in `@kaleidorg/mind/testing`. It is bound to the same tool contract, so the code that drives it later drives a real node:

```js mock.mjs theme={null}
import { Funnel, confirmReadback } from '@kaleidorg/mind';
import { MockWallet, scriptedProvider } from '@kaleidorg/mind/testing';

const wallet = new MockWallet();
const funnel = new Funnel({ provider: scriptedProvider(), tools: wallet.registry() });

const out = await funnel.runTurn('what is my balance?', {
  onConfirm: async (call) => {
    console.log(confirmReadback(call));
    return { approved: true };
  },
});
console.log(out.text);
```

`scriptedProvider()` needs no model at all. Replace it with the QVAC provider from step 4 to test a real model against the mock wallet, then replace `wallet.registry()` with `new ToolRegistry([kaleido])` to go live.

## Troubleshooting

<AccordionGroup>
  <Accordion title="kaleido: command not found">
    The installer puts `kaleido` in a user script directory that may not be on your `PATH` yet. Open a new terminal, or follow the path the installer printed. See [CLI Installation](/cli/installation).
  </Accordion>

  <Accordion title="The agent cannot reach the node">
    Run `kaleido node info`. If it fails, start the containers with `kaleido node up` and unlock with `kaleido node unlock`; the wallet locks again on every restart. Then check that `RLN_NODE_URL` matches the URL that `kaleido node list` marks as active.
  </Accordion>

  <Accordion title="The faucet transfer never shows up">
    Run `kaleido asset refresh` and wait for a confirmation. If the node has no free UTXOs, the invoice cannot be created or settled: run `kaleido wallet create-utxos` again after funding with BTC.
  </Accordion>

  <Accordion title="The other side cannot pay my RGB invoice">
    The payer fetches the transfer data from an RGB proxy listed in the invoice. Create the invoice with `kaleido asset invoice`, which adds the default proxy, or name the proxy in your prompt as in the table above.
  </Accordion>

  <Accordion title="Quotes fail or point at mainnet">
    Confirm `kaleido-mcp` logged `network: signet`. An explicit `KALEIDOSWAP_API_URL` or `KALEIDO_API_URL` in your environment overrides the preset.
  </Accordion>

  <Accordion title="The swap never executes">
    Check `wdk_list_channels`: you need a usable channel with the maker that carries the asset you are buying or selling. Without one the quote works but settlement cannot.
  </Accordion>

  <Accordion title="The model calls the wrong tool or invents arguments">
    Small models are weak at open-ended planning. Phrase requests concretely, as in the prompts above, or load a larger QVAC model. KaleidoMind's recipes handle the multi-step flows deterministically so the model only fills slots.
  </Accordion>
</AccordionGroup>

More fixes are in [AI Tools Troubleshooting](/ai-tools/troubleshooting).

## Ideas for Hackathon Projects

<CardGroup cols={2}>
  <Card title="Voice wallet" icon="microphone">
    QVAC also runs speech-to-text and text-to-speech locally. `createQvacVoice` and `runVoiceAssistant` in `@kaleidorg/mind/qvac` give you a hands-free loop with a spoken confirmation before every spend.
  </Card>

  <Card title="An agent that pays for APIs" icon="key">
    Let the agent find a paid API with `search_paid_apis`, then pay it per call over Lightning with the `mpp_*` and `l402_*` tools. No signups, no API keys.
  </Card>

  <Card title="Autonomous swap bot" icon="arrows-rotate">
    Watch prices with `l402_get_price` and `kaleidoswap_get_spreads`, and rebalance between BTC and USDT with atomic swaps. Keep the confirmation gate on until the decisions look right.
  </Card>

  <Card title="RGB issuance" icon="coins">
    Issue a ticket or loyalty token as a new RGB asset. Today this works from the CLI (`kaleido asset issue nia`) and against KaleidoMind's mock wallet; `kaleido-mcp` does not expose an issuance tool yet.
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.