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

# Testing & debugging

> Verify like VoiceOS does — before your users do.

Every scaffolded folder ships with its own test harness. The loop is short:

```text theme={null}
edit → bun verify.ts → fix → Reload in VoiceOS
```

## `bun verify.ts`

The verifier speaks **real MCP over stdio** to your server, exactly the way
VoiceOS does — no mocks. It re-reads your manifest every run and checks that:

* the manifest and preview fixture are `schemaVersion: 1`;
* the MCP handshake succeeds;
* **the tools your server registers match the manifest exactly**, both
  directions — a drifted name is the classic silent failure;
* every tool has a model-facing description worth routing on;
* every tool, called with its preview-fixture args, returns text **and** 1–3
  glance blocks.

It exits non-zero on any failure, which makes it the feedback loop for AI coding
agents too — `AGENTS.md` in your folder tells them to run it after every change.

## Preview fixtures

`voiceos.integration.preview.json` holds **safe sample inputs** per tool:

```json theme={null}
{
  "schemaVersion": 1,
  "tools": {
    "log_coffee": { "args": { "drink": "flat white" }, "expectedGlanceBlocks": 2 }
  }
}
```

They're what `verify.ts` calls your tools with, and what the Integration Studio
uses to preview cards.

<Warning>
  Keep fixtures safe to execute. A fixture for an acting tool should point at a
  harmless target — it will really run.
</Warning>

In the Studio, fixtures self-heal: every real test-drive run overwrites them
with what the tool actually returned.

## Validating pieces in isolation

From the command line:

```bash theme={null}
bunx @voiceos/integration-sdk validate voiceos.integration.json
```

In tests, the SDK exports the same validators VoiceOS runs:

```ts theme={null}
import { validateManifest, validateView } from "@voiceos/integration-sdk";

const result = validateManifest(JSON.parse(manifestJson));
if (!result.ok) throw new Error(result.errors.join("\n"));
```

Errors come back as flat `path: message` strings — e.g.
`tools.0.name: tool name must be snake_case starting with a letter`.

## Testing in the app

<Steps>
  <Step title="Install from folder">
    **Settings → Agent Mode → Integrations → Install from folder**, then talk to the
    agent.
  </Step>

  <Step title="Reload after edits">
    Hit the integration's **Reload** — it re-reads the manifest and restarts your
    server. Tools update on the next turn.
  </Step>

  <Step title="Read the logs">
    Your server's `stderr` is the diagnostic channel. VoiceOS captures it and the
    integration's log view shows it. `console.error` freely — but never log secrets.
  </Step>

  <Step title="Test-drive in the Studio">
    For anything opened in the [Studio](/integrations/build-with-ai): real scoped
    agent turns against your draft. Click any tool row to stage its card, and fill
    **Required fields** to test key-gated paths.
  </Step>
</Steps>

## What to test before sharing

|                        |                                                                                                                                                                  |
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **The unhappy paths**  | Missing API key — does your error say where to get one? The external API down. Empty results — an honest empty card beats a blank one.                           |
| **Card budgets**       | Over-cap strings and off-schema blocks are *silently dropped* at render time. `verify.ts` plus a real install is how you catch a card that quietly lost a block. |
| **Confirmation edits** | Approve an acting tool *after* editing its arguments. Your handler should honor the edited values.                                                               |
| **A cold start**       | Delete `node_modules`, reinstall from the folder. That's the experience anyone you share it with gets.                                                           |
