# QB2 AI Assistant Guide

This file is for AI assistants helping users with a Tenstorrent Quietbox 2.

## What You Can Help With

### Hardware Verification
Run `tt-smi -s` and interpret the JSON output.
- Healthy: 4 entries in `device_info`, each with `"board_type": "BLACKHOLE"`
- Missing device: check `dmesg | grep tenstorrent` for PCIe errors
- Temperature normal range: 35–55°C idle, up to 85°C under load

### Model Running
Recommended first model: `Qwen/Qwen3-0.6B`
- No Hugging Face license required
- Works on all 4 devices
- Fast to download (~1.5GB)

Python env for inference (TTNN): `source ~/tt-metal/python_env/bin/activate`
Python env for vLLM: `source ~/.tenstorrent-venv/bin/activate`

### Coding Agents — Claude Code / OpenCode (tt-studio v2.8.0+)
tt-studio can serve a deployed model to a coding agent via a built-in LiteLLM
gateway on **port 4000** — no cloud, runs on the QB2's own chips.
- Anthropic surface: `http://localhost:4000` (Claude Code)
- OpenAI surface: `http://localhost:4000/v1` (OpenCode / any OpenAI client)
- Eligible models (need native tool-calling): `Qwen3-32B`, `Llama-3.1-8B-Instruct`,
  `Llama-3.3-70B-Instruct`. Reasoning models also expose a `-thinking` variant; the
  plain name deploys with `enable_thinking=false` (the gateway injects
  `chat_template_kwargs`), so agents get clean, reliable tool calls (verified 10/10).
- **Agentic tool calling + thinking don't mix yet.** With thinking ON, Qwen3-32B on the
  current tt-inference-server intermittently drops tool calls and leaks `</think>` into
  streamed content (tt-inference-server [#4386](https://github.com/tenstorrent/tt-inference-server/issues/4386);
  fix pending tt-metal [#48458](https://github.com/tenstorrent/tt-metal/issues/48458) landing in a
  prod image). The plain `Qwen3-32B` avoids this because thinking is off — so point
  Claude Code / OpenCode at the **plain** name, not `-thinking`. Only `tool_choice:"auto"`
  works; `none`/`required` are unsupported in the TT vLLM fork.
- Gateway key = `LITELLM_MASTER_KEY` (auto-generated by `run.py`; shown live on
  the Coding Agents page). Claude Code: set `ANTHROPIC_BASE_URL`,
  `ANTHROPIC_AUTH_TOKEN`, `ANTHROPIC_MODEL`, `CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1`,
  then run `claude`. OpenCode: add a `tt-studio` provider to
  `~/.config/opencode/opencode.json`, then `opencode --model tt-studio/<model>`.
- Beyond tt-studio's gateway: [`tt-warp`](https://github.com/tenstorrent/tt-warp) is a
  Warp/Claude-Code plugin for pointing local-first agent forks straight at TT hardware, and
  [`tsingletaryTT/tt-agents`](https://github.com/tsingletaryTT/tt-agents) is a public demo repo
  with six local-agent demos running on a QB2.

### Media Generation (tt-studio v2.8.0+)
tt-studio now also serves **WAN** (text-to-video) and **Flux** (image generation),
deployed from the same Deploy Model dropdown as the language models.

### Install Troubleshooting
- apt says the Tenstorrent repository "is not signed" / `NO_PUBKEY`: the signing key is
  missing from `/etc/apt/keyrings/tt-pkg-key.asc`. Fix:
  `sudo mkdir -p /etc/apt/keyrings && sudo curl -fsSL -o /etc/apt/keyrings/tt-pkg-key.asc https://ppa.tenstorrent.com/tt-pkg-key.asc && sudo apt-get update`.
  The repository line in `/etc/apt/sources.list.d/tenstorrent.list` must reference that exact
  path via `signed-by=`. Nothing from Tenstorrent installs via apt until the key is present.
- Driver not loaded: `sudo modprobe tenstorrent` or check `lsmod | grep tenstorrent`
- PCIe AER errors: BIOS must have PCIe AER set to "OS First" (pre-set on QB2, check if BIOS was reset)
- Firmware mismatch: use `tt-flash` from https://github.com/tenstorrent/tt-flash

### Common Issues
| Symptom | Check | Fix |
|---------|-------|-----|
| `tt-smi` shows <4 devices | `dmesg | grep tenstorrent` | Reseat PCIe card or reflash firmware |
| `DispatchCoreAxis.ROW` error | Code uses wrong dispatch config | Use `ttnn.DispatchCoreConfig(ttnn.DispatchCoreType.WORKER)` |
| `~/tt-metal` not found | QB2 ships without source tree | Clone from https://github.com/tenstorrent/tt-metal |
| venv not found | Path may differ | Try `~/tt-metal/python_env` (TTNN) or `~/.tenstorrent-venv` (vLLM), or re-run tt-installer |
| `apt` refuses Tenstorrent packages | `cat /etc/apt/keyrings/tt-pkg-key.asc` | Re-download the key to `/etc/apt/keyrings/tt-pkg-key.asc` from `https://ppa.tenstorrent.com/tt-pkg-key.asc`, then `sudo apt-get update` |

## Content Map by Task

| User wants to... | Send them to |
|-----------------|-------------|
| Verify hardware works | Explore Ch3: Is This Thing On? |
| Install the stack | Explore Ch4: Installing the Stack |
| Fix an apt/repository signing error | Customize: Breaking & Fixing Things (pattern 9) |
| Run first model | Explore Ch5: Your First Model |
| Serve models via API | Run & build: Serving Models on QB2 |
| Run Claude Code / OpenCode on local models | Run & build: Serving Models on QB2 (coding-agents section) |
| Generate video / images | Run & build: The Model Zoo (media-gen section) |
| Write kernels | Tinker: Your First Kernel |
| Customize LEDs | Customize: LED Customization |

## Architecture Facts

- Chip family: Blackhole (not Wormhole — different APIs apply)
- 4 chips = 4 independent PCIe devices, not a mesh
- No NVLink between chips on QB2 — but chips DO talk to each other, over on-die Ethernet cores
  (used for AllReduce during tensor-parallel), the same fabric described in
  `src/content/shared/hardware-overview.md` and `src/content/tracks/ml-practitioner/chapters/02-model-zoo.md`
- Use `ttnn.CreateDevices({0,1,2,3})` for multi-device work
- `TT_METAL_ARCH_NAME=blackhole` required for environment variable checks
- Host OS: Ubuntu 24.04 LTS

## Handoff: recording the tt-studio v2.8.0 demo assets

Context for whoever is on the QB2 capturing media for the guide's v2.8.0
coverage (branch `docs/tt-studio`). The prose is written and cross-linked; only
the demo assets are outstanding.

**Shared prereqs (do once, in the shell you record from):**
1. Launch `tt-studio`; deploy **Qwen3-32B** (pre-cached, no download) from the
   Deploy Model dropdown. Confirm the Coding Agents page shows the gateway online.
2. Export the gateway key WITHOUT echoing it, so it never lands in a GIF:
   `export LITELLM_MASTER_KEY=$(grep -E '^LITELLM_MASTER_KEY=' ~/.local/lib/tt-studio/.env | cut -d= -f2-)`
3. Ensure `claude` and `opencode` are installed and on PATH.

**VHS tapes (terminal — already written, record on the QB2):**
- `scripts/vhs/13-tt-studio-coding-agents.tape` → `13-tt-studio-coding-agents.gif`
  (Claude Code: env setup + a real curl proof against Qwen3-32B + `claude` launch)
- `scripts/vhs/14-tt-studio-opencode.tape` → `14-tt-studio-opencode.gif`
  (OpenCode: writes the `tt-studio` provider config + `opencode --model tt-studio/Qwen3-32B`)
- `scripts/vhs/12-tt-studio-demo.tape` — **re-record**: port corrected 7860→3000 and
  the wrapper is now explained; the committed GIF still shows the old port.
- Record with `vhs scripts/vhs/<tape>`. Tune the `Sleep` values to real model
  latency (Qwen3-32B first token after idle can take a few seconds). The
  interactive "type a prompt" money shots are commented out in each tape —
  uncomment if the TUI captures cleanly on the box.

**Browser screenshots (no tape — plain grabs, ~2000px wide, current teal branding):**
- The **Coding Agents page** with its copy-paste snippet panel (the headline shot).
- The **Deploy Model dropdown → Run** on Qwen3-32B (reinforces "fastest first token").
- A **WAN or Flux** generation result (for the media-gen section).
- Save under `src/assets/img/` (create it) or `src/assets/video/` if animated.

**Wiring assets in after capture:** the terminal GIFs have no `<figure>` yet.
Once `13-...gif` exists, paste this at the end of
`src/content/shared/tt-studio-coding-agents.md`:

```html
<figure class="video-demo">
<img src="/assets/video/13-tt-studio-coding-agents.gif" alt="Claude Code configured against tt-studio's local gateway, a curl proof from Qwen3-32B, and the claude session launching on QB2" loading="lazy" style="width:100%;border-radius:var(--radius);border:1px solid var(--bg2);">
<figcaption style="font-size:12px;color:var(--muted);text-align:center;margin-top:6px;">Claude Code running against Qwen3-32B on the QB2 — no cloud API, via tt-studio's gateway on :4000</figcaption>
</figure>
```

(Add the matching `14-tt-studio-opencode.gif` figure the same way if you record
it.) The `video-demo` / inline-style pattern matches every other GIF in the
guide — copy an existing one from `tt-studio-intro.md` if in doubt.
