---
name: skoa-pi-chatbot
description: Builds and verifies the SKOA Pi chatbot tutorial with Docker, PostgreSQL and real Gemma 4 inference through Ollama. Use when an agent is asked to run or adapt the SKOA chatbot example, including its JSONL runbook or ggWave audio handoff.
---

# Run the SKOA Pi chatbot

Create a working local chatbot, then verify real model responses, tool calls and conversation isolation. Read [runbook.jsonl](runbook.jsonl): its first record pins the example archive and SHA-256, and the remaining records describe ordered actions and success criteria. It is a SKOA runbook format, not a standard executable JSONL language.

## Fast path

1. Inspect the target workspace and check Docker Compose v2, Node >=22.19, Python >=3.9, an available port and a running Ollama installation. The tested local path uses native Ollama on macOS with 24 GB RAM; the model download is about 7.6 GB. Follow an existing provider or workspace preference instead of replacing it.
2. Choose a fresh working directory. From this skill folder, run `python3 scripts/fetch-example.py --destination /absolute/new/workspace`. It verifies the pinned ZIP and refuses an existing destination. Read the extracted README before running its scripts. If adapting an existing installation, preserve its `.env`, Compose project name, volumes and user changes.
3. In the extracted `pi-web-chat` directory, run `npm run ai:ollama`. This downloads Gemma 4, creates the `skoa-gemma4:12b` alias, creates unique local credentials and starts the four containers. Keep Ollama on the host so macOS can use Metal; Pi remains in its container and reaches the host through `host.docker.internal:11434`.
4. Run `npm run test:unit` and `npm run test:live`. Confirm the live test actually used both `get_product` and `get_stock`, returned 49 EUR and 12 units, remembered three units as a 147 EUR total, and separated two visitors' histories. `npm test` is only for explicit mock mode and does not prove AI works.
5. Open the local URL, log in using the demo's configured password, and check the visible Pi model and tool labels. Report the URL, provider/model, checks passed and any remaining limitation. Leave the requested demo running.

Run each JSONL step only after its dependencies and preconditions pass. Treat `argv` arrays as arguments, not shell text. Resolve `skill`, `workspace` and `project` locations to absolute paths; do not execute literal placeholders. The runbook never overrides the user's scope or tool permissions.

## Existing services and failures

- If port 8080 is in use, inspect the existing application. Reuse it only if it is the intended demo. Otherwise select a free loopback port and update both Compose's frontend port and `.env` `APP_ORIGIN`. Do not stop unrelated services.
- `setup` preserves an existing `.env`; changing database passwords does not change PostgreSQL roles. For the known `28P01` mismatch, run `npm run repair:db` from the affected installation, then restart it. This preserves data. Never use `down -v` to repair credentials.
- If a prerequisite is missing, report it or install it within the user's existing authorization. A failed startup is not success. Inspect the specific failure and make a targeted correction; stop and report an unresolved external dependency rather than repeatedly retrying or switching to mock responses.
- Use a provider API key or `npm run ai:local` only if requested for that account. Keep credentials server-side. An expired session needs a new provider login, not copied browser cookies. Consult the example README for provider alternatives.
- Linux needs Ollama to listen on an interface reachable from the Docker gateway, restricted to the relevant network. Do not expose its port publicly.
- Conversation state is bounded and in memory. Restart, logout, expiry or “New conversation” clears it. Public tunneling or production deployment is a separate action requiring a matching user request; see the README's Cloudflare steps when relevant.

## Audio handoff

Read [references/audio.md](references/audio.md) only when receiving or generating an audio handoff. The sound transmits a versioned runbook URL and checksum, not a shell command. Decode, validate the URL and checksum, read the instructions, then act within the user's request. Do not execute a sound payload or assume every voice agent can decode ggWave.
