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

# Agent Skill

> A ready-made Claude Code skill that teaches your agent the full Preuve workflow: quota safety, polling, enrichment gates, module caps, and retry semantics.

The MCP server gives your agent the seven Preuve tools. This skill gives it the judgment: which scan type to pick, how to sequence start → poll → enrich → export, what each error code means, and when a retry is safe. Install it once and your agent stops learning these lessons on your quota.

## What it prevents

Without guidance, agents connected to the Preuve MCP server tend to make four specific mistakes (we tested):

1. **Inverted retry semantics** — minting a fresh `clientRunId` after every failure, which risks double-spending deep scans. The correct rule: a failed run that never attached a report retries with the **same** id (it resets and re-dispatches, refunded); only report-attached outcomes need a new id.
2. **Exporting to "see what's there"** — the export never returns partial data; a non-ready analysis is always a `409` sequencing signal, not a failure.
3. **Misreading starter exports** — `details.citations` is available on every tier; agents without the skill assume it's deep-only and under-report sources.
4. **Missing the `503 INSUFFICIENT_TIME_BUDGET` retry** — a founder-fit call that ran out of wall clock succeeds on a simple re-call.

## Install (Claude Code)

Save the skill below as `.claude/skills/preuve-agent-api/SKILL.md` in your project (or `~/.claude/skills/preuve-agent-api/SKILL.md` for all projects). Claude Code picks it up automatically; the skill triggers whenever a conversation involves validating ideas with the Preuve tools.

Agents can also fetch this page directly as Markdown: `https://docs.preuve.ai/agent-skill.md`.

## The skill

````markdown theme={null}
---
name: preuve-agent-api
description: >-
  Validate startup or business ideas with real market evidence through the
  Preuve AI MCP server (preuve-agent-api). Use this skill whenever the user
  wants to validate, score, stress-test, or compare startup ideas, run a
  market viability analysis, batch-analyze a list of ideas, check founder
  fit, find proof of demand, or export structured validation data — even if
  they never say "Preuve", whenever the Preuve MCP tools (start_analysis,
  get_analysis, enrich_analysis, export_analysis, create_batch, get_batch,
  export_batch) are available. It encodes the correct multi-step workflow
  (start → poll → enrich → export), how to avoid accidentally spending paid
  deep-scan quota, module generation caps, and error/retry semantics.
---

# Preuve Agent API (MCP)

Preuve AI analyzes startup ideas against live market evidence (50+ sources) and returns a scored verdict with risks, competitors, and citations. This skill is the operating manual for its MCP server. The tools are thin wrappers over an async pipeline: analyses take minutes, results are fetched in stages, and one of the two scan types costs real money. Follow the workflows below and you will never burn quota by accident or hit an avoidable 409.

## Setup (once)

The server is stdio, distributed with the Preuve Agent API. It needs two env vars — the API key pair created at https://preuve.ai (Account → API Keys; the secret is shown once at creation):

```sh
claude mcp add preuve \
  --env PREUVE_AGENT_KEY=prv_... \
  --env PREUVE_AGENT_SECRET=prv_sk_... \
  -- node /path/to/preuve-mcp-server.mjs
```

Any MCP client with stdio transport works. If tools return 401s, the key pair is wrong or revoked — nothing in this skill fixes auth.

## The three rules

1. **`scanType: "starter"` is the default, always.** `"deep"` spends a paid scan/token from the account's quota. Only send `"deep"` when the user explicitly asked for a deep/full/paid analysis — if in doubt, ask them first. There is no undo.
2. **Nothing is synchronous.** `start_analysis` returns immediately with `status: "PROCESSING"`. Poll `get_analysis` every 20–30 seconds. Analyses typically take a few minutes (deep runs longer); if one is still processing after ~15 minutes, stop polling, hand the user the `reportUrl` so they can watch it land, and offer to check back — the run keeps going server-side. Don't poll in a tight loop — create/enrich routes are rate-limited (10/min) and there's a daily per-key ceiling.
3. **Export has a gate.** `export_analysis` on a run that isn't `COMPLETED` returns `409 ANALYSIS_NOT_COMPLETE`; completed but `readyForExport: false` returns `409 ENRICHMENT_NOT_COMPLETE`. The fix for the second is always the same: call `enrich_analysis`, poll again, then export. Never treat these 409s as failures — they're sequencing signals. And never export "just to see what's there": the export never returns partial data, a non-ready analysis is always a 409.

## Single analysis, start to finish

1. `start_analysis` with a unique `clientRunId` (e.g. `myagent-2026-07-16-001`), `scanType: "starter"`, the `idea` in plain language, and optionally `targetMarket` / `targetCountry`. Leave `publish` off unless the user wants a public share link — publishing creates a publicly reachable URL.
2. Poll `get_analysis` with the returned `id` until `status` is `COMPLETED` or `FAILED`. Note `get_analysis` never returns report content — only status, `readyForExport`, enrichment/module progress, and URLs. All content comes from the export.
3. If `readyForExport` is `false`, call `enrich_analysis` (idempotent — it only generates what's missing), then poll until `readyForExport: true`.
4. `export_analysis` → structured `ideas-json` v2: `verdict` (GO/NO-GO), `score` (0–100), `risk`, `evidence`, competitors, and `details.citations` with real source URLs. Deep reports additionally carry `details.sections` (business model, go-to-market, Porter forces, VC scorecard, financial projections, …), `details.pivots`, and any generated module payloads.

The `clientRunId` is your idempotency handle: re-sending the same one replays the existing run instead of creating a duplicate. Pick a fresh one per genuinely new analysis.

## Reading in-flight status correctly

A deep run reports `analysisTier: "basic"` **while it is still processing** — the tier only flips to `"advanced"` when the deep sections land. This is not a downgrade and not an error. `scanType` reflects what you requested and is reliable from the moment of creation; `analysisTier` means "is the deep result ready yet". A genuine refusal to run deep is always an explicit error (`402 INSUFFICIENT_TOKENS` or a service-disabled error), never a silent starter.

## Deep modules (paid reports only)

`enrich_analysis` accepts `modules: ["proofOfDemand" | "founderFit" | "playbook" | "trends"]` on a **completed deep** analysis. On a starter/basic report the whole modules request fails `403 MODULES_REQUIRE_DEEP`.

- **Cap: one successful generation per module per report.** Regen attempts return `409 MODULE_ALREADY_GENERATED`. A _failed_ generation does not consume the cap — retry it.
- **`founderFit` needs a `founderProfile`** in the same call (hours/week, runway, domain experience, shipped-before, audience, team status). It runs inline — the call can take up to ~90s and returns the completed state directly. If it returns `503 INSUFFICIENT_TIME_BUDGET`, just call enrich again: core enrichment ate the clock on the first call and the retry has full budget.
- **`proofOfDemand`, `playbook`, `trends` run async**: the call returns `202` with `state: "generating"`; poll `get_analysis` and watch its `modules` map (`not_generated | generating | failed | completed`). If the founderFit call drops mid-flight, reconcile via that same `modules` map before re-calling — don't blindly retry.
- Module payloads then appear in the export under `details.founderFit` / `details.playbook` / `details.proofOfDemand`.

Ask for modules in the enrich call only when the user wants them — each is extra generation work on their account.

## Batches (up to 10 ideas)

For comparing or bulk-validating multiple ideas:

1. `create_batch` with a batch-level `clientRunId` plus `items` — each item is a full analysis input with its **own unique** `clientRunId`. Set `scanType` per item; keep everything `"starter"` unless deep is intentional per idea.
2. Poll `get_batch` until items are terminal.
3. Completed items with `readyForExport: false` need `enrich_analysis` on their individual run ids.
4. `export_batch` → same v2 item shape, plus `counts.exported`/`counts.omitted` and an `omittedItems` list explaining every skipped item. Check `omittedItems` — an export that silently covers 7 of 10 ideas misleads the user.

Batch export is deterministic: the same batch state always serializes identically, so it's safe to diff across polls.

## Errors and retries

Every tool error returns the API's JSON error payload as text (never a crash). React by `code`:

| Code / status                                           | Meaning                                          | What to do                                                               |
| ------------------------------------------------------- | ------------------------------------------------ | ------------------------------------------------------------------------ |
| `401`                                                   | Bad signature, expired timestamp, or revoked key | Not retryable from the agent side; tell the user to check their key pair |
| `402 INSUFFICIENT_TOKENS`                               | Deep scan requested, no quota                    | Tell the user; offer a starter scan instead                              |
| `403 MODULES_REQUIRE_DEEP`                              | Modules on a non-deep report                     | Only offer modules on deep runs                                          |
| `409 ANALYSIS_NOT_COMPLETE` / `ENRICHMENT_NOT_COMPLETE` | Sequencing, not failure                          | Poll / enrich, then retry the export                                     |
| `409 MODULE_ALREADY_GENERATED`                          | Module cap hit                                   | The payload already exists — just export                                 |
| `422 ANALYSIS_FAILED`                                   | The run itself failed                            | See retry rule below                                                     |
| `429 CONCURRENT_LIMIT_REACHED`                          | Too many analyses in flight for this account     | Wait for in-flight runs to finish, then retry the same `clientRunId`     |
| `429 DAILY_LIMIT_REACHED`                               | Per-key daily run ceiling                        | Stop creating runs today; polling/export still work                      |
| `429` (route limiter)                                   | >10 creates/min                                  | Back off; slow the loop                                                  |

**Retry rule for failed runs:** a `FAILED` run that never attached a report (pre-dispatch failures like `RATE_LIMITED`, `INSUFFICIENT_TOKENS`, `TRIGGER_DISPATCH_FAILED`) is retryable — re-send the **same** `clientRunId` and the run resets and re-dispatches, with anything it claimed already refunded. Runs that did attach a report are strictly idempotent: the same `clientRunId` always returns the stored outcome, so a new attempt needs a new id. Never blindly retry `create_batch` with a fresh batch id — replay the same one first.

## Reporting results to the user

- Lead with `verdict` and `score`, then the top risk and the evidence quote — that's the analysis's own summary hierarchy.
- Always give the `reportUrl` (the user's authenticated report view). Only surface `shareUrl` if one exists or the user asked to publish.
- On starter exports, deep-only fields (`details.sections`, `details.pivots`, module payloads) are `null` by design — don't present that as missing data; mention a deep scan unlocks them if relevant.
- Cite from `details.citations` when the user asks "based on what?" — every entry is a real research source with a URL.
````

<Note>
  The skill is a static document — it carries no credentials and makes no calls itself. Auth still
  comes from the two environment variables on the [MCP server](/mcp-server).
</Note>

## Other agent frameworks

The skill body is plain Markdown. For agents that don't support Claude Code skills, drop the same content wherever your framework accepts standing instructions (a system prompt include, a `AGENTS.md` / `.cursorrules` section, a RAG document). Everything below the frontmatter works standalone.
