Skip to main content

threadlight-local-test

Run a threadlight-designed PoC locally without `azd up`. Four patterns: (0) **Quickstart** — `python -m threadlight_quickstart` boots MAF Agent + SkillsProvider + stub tools + Streamlit UI on localhost:8501; one LLM dep (Foundry OR AOAI OR GitHub Models via GITHUB_TOKEN — zero Azure). (1) MCP-direct — local MCP at `~/.copilot/mcp.json`; (2) Smoke-client — `agent.run_async()` bypassing ResponsesHostServer; (3) Local-stack — docker-compose + Cosmos emulator (Linux/Win x86 only). USE FOR: local test, smoke test, run agent locally, dev loop, no azd, copilot cli mcp, faster iteration, prompt tuning, cowork iteration, demo rehearsal, screen-shareable PoC, streamlit demo, GitHub Models, boot Kratos export locally. DO NOT USE FOR: prod deployment (use threadlight-deploy), pre-pilot validation (use threadlight-safe-check), hosted-agent runtime testing in cloud (use foundry-evals).

Jump to install

Source facts

Repository
aiappsgbb/threadlight-skills
Last source activity
September 24, 2026 at 20:57
Detected SKILL.md language
English
Stars
1
Forks
5

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

File Explorer
34 files

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
threadlight-local-test
description
Run a threadlight-designed PoC locally without `azd up`. Four patterns: (0) **Quickstart** — `python -m threadlight_quickstart` boots MAF Agent + SkillsProvider + stub tools + Streamlit UI on localhost:8501; one LLM dep (Foundry OR AOAI OR GitHub Models via GITHUB_TOKEN — zero Azure). (1) MCP-direct — local MCP at `~/.copilot/mcp.json`; (2) Smoke-client — `agent.run_async()` bypassing ResponsesHostServer; (3) Local-stack — docker-compose + Cosmos emulator (Linux/Win x86 only). USE FOR: local test, smoke test, run agent locally, dev loop, no azd, copilot cli mcp, faster iteration, prompt tuning, cowork iteration, demo rehearsal, screen-shareable PoC, streamlit demo, GitHub Models, boot Kratos export locally. DO NOT USE FOR: prod deployment (use threadlight-deploy), pre-pilot validation (use threadlight-safe-check), hosted-agent runtime testing in cloud (use foundry-evals).
metadata
{"version":"1.3.2"}
# Threadlight — Local Test Loop (no azd up) ## Presenter-ready integration contract For the explicit [presenter-ready profile](../../docs/presenter-ready.md), exercise the **exact packaged SDK/framework, host/client and process adapter** selected in the process handoff. Cover response shapes (data-plane, not management-plane substitutes), legitimate metadata reads, real retry/dispatch, pending lifecycle, terminal stream errors, persistence, independent readback, reopening and recovery. Bind outputs to the dependency lock/source and record the layer actually run: offline, native, hosted and quality/human evidence are different. Pattern 0 remains a quick iteration option, not a universal runtime or durable result store. Its in-memory data resets on recreation and cannot satisfy promised save/reopen. Provisional stream text is not success before terminal validation; a late failure replaces successful-looking result text. Reuse valid focused evidence; no blanket SDK upgrade, broad rerun or business replay for screenshots. Run a generated PoC entirely on your dev box so you can iterate on **tools**, **prompts**, and **workspace UI** in seconds — not in the 20-30 min round-trip of `azd deploy`. Designed for use **inside** GitHub Copilot CLI, Cowork, or Clawpilot, where you want to hand the running agent / MCP server to the CLI itself for hands-on testing. > **What this skill is NOT.** This is not a "make Foundry run on > your laptop" skill — Foundry hosted-agent runtime stays in Azure. > What this skill *is* is the recipe for running the **same agent > code, the same MCP server code, the same workspace HTML** on > localhost so you can debug fast, then redeploy via > `threadlight-deploy` when you're happy. --- ## When to use which pattern | Pattern | What it runs | When to use | |---------|--------------|-------------| | **0. Quickstart** (default) | `python -m threadlight_quickstart` → MAF `Agent + SkillsProvider` + JSON stub tools + Streamlit UI on `localhost:8501` | **First reach-for after `threadlight-design`.** Closes the design → screen-shareable demo loop to <30 min. Zero Docker, zero MCP server boot, one LLM dep (Foundry project OR AOAI deployment OR GitHub Models via `GITHUB_TOKEN`). | | **1. MCP-direct** (CLI ↔ MCP) | Just the PoC's FastMCP server on `localhost:8000`; CLI calls tools natively | You're iterating on **MCP tool implementation** (DB queries, business rules, error handling). The CLI itself is the agent. | | **2. Smoke-client** (CLI → Python → Agent) | The PoC's `Agent + FoundryChatClient` invoked via `agent.run_async()` from a smoke script | You're iterating on the **prompt** or the **agent's tool-orchestration** behaviour. Skips the `ResponsesHostServer` HTTP layer. | | **3. Local-stack** (compose) ⚠️ | All of: MCP server + Cosmos emulator + workspace UI on nginx + (optional) Search mock | End-to-end smoke before redeploying. **Linux / Windows x86 only** — Cosmos emulator container is fragile on macOS ARM; use Pattern 0 there. | Reach for **Pattern 0** first. Drop to **Pattern 1** when you need to iterate on the real MCP server. Use **Pattern 2** for headless prompt tuning that needs to be driven from the CLI. **Pattern 3** is a pre-deploy parity check on platforms where the Cosmos emulator container actually works. --- ## Pattern 0 — Quickstart (default) The new default for "I just finished `threadlight-design`, now I want to see it run." Consumes what design already emits — `specs/sample-data/`, `src/agent/skills/<name>/SKILL.md` — and gives you a MAF agent + a chat UI on `localhost:8501` without ever touching Docker, the MCP server, or a real Cosmos. > **Kratos-export mode.** Pattern 0 also boots a **Kratos-exported project** > (`src/hosted-agent/` + `use-cases/<x>/` — see > [`docs/KRATOS-BRIDGE.md`](../../docs/KRATOS-BRIDGE.md)) — the hosted-agent > contract is identical, so the same MAF `Agent + SkillsProvider` recipe applies. > Two path differences: load skills from the resolved skills root > `use-cases/<x>/skills/` (auto-detected; `--skills-root` to override) instead of > `src/agent/skills/`, and seed the in-memory store from the export's `mocks/` > directory in place of `specs/sample-data/`. The agent identity/system prompt > comes from `use-cases/<x>/SYSTEM_PROMPT.md`. No `azd up`, same fast loop. ### What you need | Need | Why | One-time? | |------|-----|-----------| | **Python ≥ 3.10** + `pip` (or `uv`) | Run the reference package | Yes | | **A threadlight-designed PoC** (the cwd at minimum has `specs/sample-data/*.json`) | Pattern 0 auto-discovers it | Per PoC | | **One LLM endpoint** — Foundry project URL **OR** Azure OpenAI deployment **OR** GitHub Models (zero Azure) | The only external dep | Per tenant (shared GBB sandbox is fine; or just `gh auth token` for GitHub Models) | | **Auth** — `az login` to the LLM tenant (Foundry/AOAI) **OR** `GITHUB_TOKEN` (GitHub Models) | Credential for the LLM call | Per tenant | > **No Docker. No Cosmos emulator. No MCP server boot.** Pattern 0 > replaces all three with an in-memory dict-of-records loaded from > `specs/sample-data/<entity>.json` and three CRUD tools per entity > (`list_<entity>`, `get_<entity>`, `update_<entity>`). ### The bootstrap (one-time per PoC) ```bash # 1) Install the quickstart package once (editable, from the catalog) pip install -e <awesome-gbb>/skills/threadlight-local-test/references/quickstart # 2) Drop the env template into the PoC and edit it cp <awesome-gbb>/skills/threadlight-local-test/references/quickstart/.env.local.example .env.local $EDITOR .env.local # set LLM_BACKEND: foundry (default), aoai, or copilot (GitHub Models, no Azure) echo .env.local >> .gitignore # 3) Sanity-check the wiring without a live LLM round-trip (<5s) python -m threadlight_quickstart --check ``` ### The loop (every time) ```bash az login --tenant <dev-tid> # per azure-tenant-isolation skill python -m threadlight_quickstart # Streamlit on http://localhost:8501 ``` Or with the demo-prompt pump pre-loaded so you can step through the prep-guide acts hands-free: ```bash python -m threadlight_quickstart --simulator ``` `--simulator` reads prompts in priority order from: 1. `<poc-root>/tests/demo-prompts.txt` (one prompt per line; `#` comments allowed) 2. `<poc-root>/specs/prep-guide.html` § *Demo Script* (regex on `<strong>Type this:</strong>` blocks) > **`.env.local` is auto-loaded.** The CLI parses `<poc-root>/.env.local` > on every launch and injects the keys into the process env (only ones > not already set in the shell). No need to `source` it manually. > Disable with `THREADLIGHT_QUICKSTART_NO_TRANSCRIPT=1` if you don't > want the side-effect. > **Every UI turn appends to `<poc-root>/tests/quickstart.jsonl`.** > Shape matches what [`foundry-evals`](https://github.com/aiappsgbb/awesome-gbb/blob/main/skills/foundry-evals/SKILL.md) > consumes — `{ts, query, response}` per row. Run a few Pattern 0 > demos, then promote the JSONL into your Foundry eval dataset > without reshaping. Disable with `THREADLIGHT_QUICKSTART_NO_TRANSCRIPT=1`. > Add `tests/quickstart.jsonl` to your PoC's `.gitignore` (it's local > demo state, not a fixture). ### How the tools come from your SPEC For every `specs/sample-data/<entity>.json` discovered, Pattern 0 registers three MAF `@tool`-decorated callables backed by an in-memory `InMemoryStore`: | Tool | Returns | Notes | |------|---------|-------| | `list_<entity>(filters=None)` | `list[dict]` | Equality match on each field in the filters object; no filter → all records | | `get_<entity>(id)` | `dict \| None` | Lookup by record id | | `update_<entity>(id, fields)` | `dict` | Explicit fields object; mutates the in-memory snapshot; **reset every launch** | The named object parameters are intentional: the actual native SDK schema omits arbitrary `**kwargs`, which otherwise silently drops filters and update fields. Existing Python store methods retain their keyword API; native tool callers use the explicit `filters` / `fields` objects. The agent's `SkillsProvider` discovers `src/agent/skills/<name>/SKILL.md` under `from_paths(skills_dir)` and loads bodies on demand. Follow the [autonomous MAF skill-read contract](../_shared/maf-skill-approval.md): only trusted local instructions/resources bypass the provider's read approval; scripts and other tools keep their policies. Unresolved native approvals raise `approval_required`, surfaced by the existing UI error path rather than an empty successful turn. This local configuration is not proof of hosted parity. ### Custom tools (when CRUD isn't enough) For cross-entity joins, derived fields, business rules — drop a `tests/quickstart_tools.py` next to the PoC, exposing: ```python def register(tools: list, stores: dict) -> list: """Return extra MAF tools to append to the auto-generated CRUD set.""" from agent_framework import tool @tool def reassign_urgent(assignee: str) -> int: urgent = stores["tickets"].list_all(severity="urgent") for row in urgent: stores["tickets"].update(row["id"], assignee=assignee) return len(urgent) return [reassign_urgent] ``` `agent_wiring` auto-discovers and calls `register(tools, stores)` after the CRUD triple is built. ### What ships in the reference package ``` references/quickstart/ ├── pyproject.toml # pip-installable; pins streamlit + agent-framework ├── threadlight_quickstart/ │ ├── __main__.py # `python -m threadlight_quickstart` │ ├── cli.py # argparse: --check, --info, --simulator, --port │ ├── discover.py # walks up cwd for the canonical PoC layout │ ├── agent_wiring.py # Agent + SkillsProvider + tool registration │ ├── stub_tools.py # InMemoryStore + CRUD tool factory │ ├── simulator.py # demo-prompt cursor │ └── ui_streamlit.py # the Streamlit chat page ├── .env.local.example # env-var template ├── Makefile.demo # drop-in for PoCs that want `make demo` ├── fixture-poc/ # 1-skill, 1-entity toy PoC (smoke target) └── tests/ # pytest against fixture-poc ``` ### When Pattern 0 is **not** the right answer - **You need the real React workspace UI render** → Pattern 1 + run the PoC's own `npm run dev:workspace` separately. Pattern 0 ships Streamlit only on purpose (zero Node toolchain). - **You're debugging the real MCP server** → Pattern 1. Pattern 0 bypasses the MCP layer entirely. - **You need real Cosmos / Search semantics** (ranking, partition keys, RU shape) → Pattern 3 on Linux/Windows x86, or `azd up` to a dev sub. - **You need multi-agent orchestration** → Pattern 2. --- ## Prerequisites (one-time, dev box) | Need | Why | Install | |------|-----|---------| | **Python 3.13** + `uv` | Run agent/MCP code | [uv install](https://docs.astral.sh/uv/) | | **Docker Desktop** (or Rancher) | Cosmos emulator + nginx | Standard install | | **Azure OpenAI deployment** of `gpt-5.4-mini` (or any model), **OR** GitHub Models via `GITHUB_TOKEN` | Agent needs a real LLM | Any AOAI account, or just a GitHub account for GitHub Models. **The skill does NOT require Foundry locally.** | | **`az` logged in** to the AOAI tenant | DefaultAzureCredential in the agent code resolves to your `az` token | `az login --tenant <tid>` (per `azure-tenant-isolation`) | | **GitHub Copilot CLI** ≥ 1.0.40 | For Pattern 1 (MCP-direct) | `gh extension install github/gh-copilot-cli` | > **Bring-Your-Own-Foundry option.** If you have a Foundry project, > Patterns 2 and 3 can use `FoundryChatClient(project_endpoint=...)` > exactly as in production. If you don't, swap to plain `OpenAIClient` > pointed at AOAI directly — the agent code is identical aside from > the client constructor. See `references/local-stack/local_smoke.py` > for both forms. --- ## Pattern 1 — MCP-direct (Copilot CLI ↔ local MCP) The cleanest dev loop for **tool development**. The CLI itself acts as the agent; you call tools natively from natural language. ### Setup (3 lines) ```powershell # 1. Run the PoC's MCP server locally cd <poc-root>/src/mcp_server uv run python main.py # binds to http://localhost:8000/mcp # 2. Register it with Copilot CLI (per-user; persists) copilot mcp add <poc-name>-local --url http://localhost:8000/mcp # 3. Restart the CLI session copilot ``` ### Iteration loop In the CLI, ask: `"call list_open_disputes; what do you see?"` → the CLI invokes the local tool directly, you see the JSON response, you tweak `mcp_server/main.py`, the dev-loop reload picks it up (FastMCP supports `--reload`), you re-ask the CLI. **Why this is fast:** zero LLM round-trips for the dev parts you don't care about (no agent prompt to debug here); the CLI's built-in agent calls your tool once, you read the JSON, you fix. > **Pitfall.** If your MCP server reads from Azure resources > (Cosmos, Search) using `DefaultAzureCredential`, the local > process needs to authenticate to those — either use the dev > stack from Pattern 3 (local Cosmos), or `az login` against the > tenant that owns the real cloud resources. See > `references/cli-integration/copilot_mcp_register.md` for the > full setup including a localhost MCP that reads from cloud > Cosmos via your `az` token. See `references/cli-integration/copilot_mcp_register.md`. --- ## Pattern 2 — Smoke-client (direct `agent.run_async()`) For **prompt tuning** and **agent-orchestration** debugging, skip the `ResponsesHostServer` HTTP layer entirely. Build the agent in-process and call `run_async()` directly. ### Worked example `tests/local_smoke.py` (template ships in `references/local-stack/local_smoke.py`): ```python import asyncio import os from agent.container import build_agent # PoC's existing factory async def main(): os.environ.setdefault("MCP_SERVER_FQDN", "localhost:8000") os.environ.setdefault("MODEL_DEPLOYMENT_NAME", "gpt-5.4-mini") os.environ.setdefault("FOUNDRY_PROJECT_ENDPOINT",
View on GitHub
This SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub