fh doctor
Diagnose a workspace before you blame the agent, covering tool wiring, configuration and live model connectivity.
fabric-harness doctor [--target node|temporal-worker|databricks-app|databricks-serving|buzz] [--model provider/model] [--getting-started] [--tools] [--workspace] [--live] [--json]fh doctor validates that your workspace is set up correctly and (optionally) that a real model can be invoked.
Options
| Flag | Description |
|---|---|
--target <node|temporal-worker|databricks-app|databricks-serving|buzz> | Validate the chosen run, deployment, or first-party integration target. |
--model <provider/model-id> | Probe a specific model (combine with --live). |
--getting-started | Check Node version, ESM package setup, Fabric dependencies, npm scripts, and .fabricharness/agents discovery. |
--tools | Enumerate built-in tools and required binaries (docker, gh, etc.). |
--workspace | Statically validate the workspace: skill and role references, target-incompatible imports, and files in agent directories that export no definition. |
--live | Make a bounded live model request, or run read-only relay and durable-state certification for --target buzz. |
--json | Emit a machine-readable report. |
Examples
Local readiness
fh doctor --getting-started --toolsLive model check
cp .env.example .env.local
# edit .env.local and set OPENAI_API_KEY=...
fh doctor --live --model openai/gpt-5.5Workspace validation
fh doctor --workspace
fh doctor --workspace --target cloudflareReads source without executing it, so it needs no credentials, no network, and doesn't import your agent modules. It reports:
| Code | Severity | Meaning |
|---|---|---|
skill-not-found | error | A session.skill('name') call whose name no skill defines, neither a .fabricharness/skills/ directory, a build-time SKILL.md import, nor a defineSkill() in the same file. |
role-not-found | error | An init({ role }) naming a role no file defines. |
target-incompatible-import | error | A Node built-in the chosen target's runtime does not provide. Only reported when --target names such a runtime. |
no-default-export | warning | A file in an agent directory exporting no default definition. |
Errors exit non-zero, so this composes into CI. Warnings don't.
Without --target, target-specific checks are skipped, a workspace that only
ever runs on Node should not be warned about its node:fs import.
Two checks are deliberately conservative, because a false positive on correct
code is worse than a missed finding. A skill imported from a package cannot be
resolved from source, so the skill check is suppressed for that file; and the
role check is scoped to init({ ... }) options, since role: is also the LLM
message discriminator.
Temporal target
fh doctor --target temporal-workerThe doctor checks Temporal connectivity using config/env defaults. Make sure FABRIC_TEMPORAL_ADDRESS and your task queue are correct.
Databricks App bindings
fh doctor --target databricks-app --json
fh doctor --target databricks-app --live --jsonEvery Databricks report includes a workspace-readiness section. It uses four intentionally narrow classifications:
| Classification | Meaning |
|---|---|
contract-supported | The installed Harness code has an offline-tested adapter. It says nothing about this workspace's grants or enrollment. |
live-certified-here | The installed package, declared cloud, and region exactly match retained public certification evidence. |
preview-enabled | A bounded read-only live probe reached that preview API in this workspace. |
not-established | The command cannot prove the claim. Treat it as unknown, not as disabled. |
Offline mode reports the configured host, inferred cloud/region, installed package version, exact
public certification relationship, and contract support for Apps, Unity Catalog/OBO, SQL, Genie,
Model Serving, AI Gateway, Lakebase, managed MCP, Supervisor Agents, and managed memory. --live
adds bounded read-only identity and service discovery probes. A successful service probe proves
reachability under the probing principal; it does not prove every end user's Unity Catalog grant.
The command never prints tokens or connection strings.
Set FABRIC_DATABRICKS_APP_CAPABILITIES to the comma-separated capabilities the App claims.
lakebase, genie, obo, and/or system-tables-cost. Doctor fails closed when a claim lacks its
required endpoint, database, Genie space, OBO opt-in, warehouse, or cost-scope binding. It never
prints credential values. The report also includes a redacted effective inventory:
- identity kind and credential source;
- enabled model-callable tools with effects and service names;
- static or input-bound governed resources;
- approval coverage;
- persistence, scheduler identity, lease, and catch-up modes; and
- unsupported or dynamically resolved capabilities.
Persistent-agent initializers are interaction-scoped, so doctor reports their tool inventory as dynamic instead of executing an initializer with a fabricated identity.
Buzz bridge
fh doctor --target buzz --json
fh doctor --target buzz --liveThe offline preflight validates Node 22/native WebSocket support, the relay and forwarding URLs, redacted Nostr-key and HMAC-secret shape, the server-owned community/channel allowlist, durable PostgreSQL or Lakebase configuration, and the current v2 generated recipe. It specifically rejects the old process-memory tail and recipes that omit decision-receipt or dead-letter wiring.
--live is a read-only certification profile. It performs a bounded NIP-11 probe, requires NIP-01
and NIP-42, signs NIP-98 queries with the configured adapter identity, verifies the returned NIP-01
event integrity, and requires that identity in both the authoritative relay roster and every
configured channel member list. It then connects to PostgreSQL or Databricks Lakebase with a
single-connection pool and reads only content-free operational evidence. Relay cursor lag,
cursor-update age, unresolved dead-letter depth, and prepared/published decision-card counts.
The default limits are 300 seconds of relay lag, 300 seconds since the cursor update, and zero
unresolved dead letters. Set BUZZ_MAX_RELAY_LAG_SECONDS, BUZZ_MAX_CURSOR_AGE_SECONDS, and
BUZZ_MAX_DEAD_LETTERS to explicit non-negative integers when the deployment SLO differs. The JSON
report is safe for CI evidence. It never includes event content, private keys, forwarding secrets,
database URLs, or database passwords. Relay and channel membership prove transport admission only;
they do not grant Fabric action authority.
What it checks
- Workspace root resolution.
- Agents discovered.
- Node/package/ESM/dependency setup (when
--getting-started). - Built-in tool schemas and binaries on PATH (when
--tools). - Model provider configuration.
- Optional live model round-trip when
--live. - Optional Temporal connectivity for
--target temporal-worker. - Databricks CLI, authentication, and claimed App bindings for Databricks deployment targets.
- Buzz bridge configuration, v2 durability wiring, and optional read-only relay/Lakebase certification.