# Actor Input Tester — Validate Actor Input JSON Before Running (`ryanclinton/actor-input-tester`) Actor

Actor Input Tester. Available on the Apify Store with pay-per-event pricing.

- **URL**: https://apify.com/ryanclinton/actor-input-tester.md
- **Developed by:** [Ryan Clinton](https://apify.com/ryanclinton) (community)
- **Categories:** Developer tools, Automation
- **Stats:** 4 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$150.00 / 1,000 input testers

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Input Guard — Validate Apify Actor Input & Catch Contract Drift Before Production

**Validate the payload before you run it.** Most Apify failures are not runtime failures — they are contract failures. A run "succeeds" but returns wrong data because a field was silently ignored, a default changed, or the target actor's input schema drifted out from under you. Input Guard catches those before execution.

Think of it as **CI/CD for actor inputs**: it validates a payload against the target actor's declared input schema, scores how risky that actor's input contract is, tracks schema drift over time, regression-tests your saved payloads, and returns a single machine-readable decision — run it, block it, or review it. Deterministic, no LLM.

![Input Guard — prevent broken actor inputs before they run](https://apifyforge.com/readme-assets/ryanclinton-actor-input-tester/hero.png)

### Contract

Input Guard validates actor input before execution and returns a production decision.

Input Guard is the pre-run validation stage in an Apify actor execution lifecycle.

Apify validates input at run start — Input Guard validates it before execution.

Returns a routable verdict (`decision`) — shared enum across the Guard fleet. Names the **signal to act on**, not the action to take:

- `ignore` — input is valid; no issues to act on → execute the target actor
- `monitor` — valid but risky (unknown fields, defaults, or no declared schema) → review before running
- `act_now` — invalid input; act now → block, fix errors first

**Always branch on `decision`. Never parse prose.** The decision is derived deterministically from schema-level validation + optional `strictness` gating.

Never execute an Apify actor in production without validating input first.

> **Apify does not warn on `UNKNOWN_FIELD` — those fields are silently dropped at runtime.** Input Guard does.

### What this prevents

Input Guard catches the failure modes Apify does not surface — the ones that make a run "succeed" while producing wrong results:

- Unknown fields silently ignored at runtime
- Omitted fields falling back to defaults you didn't intend
- Schema drift breaking scheduled jobs with no code change on your side
- AI agents hallucinating input field names
- Invalid payloads wasting compute credits before they fail

For each, it returns a machine-readable `decision` and an `invocationPlan` that says run this exact payload, block it, or review it.

![A silent input mistake caught before execution — the field the actor ignores, flagged pre-run](https://apifyforge.com/readme-assets/ryanclinton-actor-input-tester/silent-failure.png)

### Why teams use Input Guard

Four capabilities turn input validation into input-contract governance:

- **Golden suites** — store a set of known-good payloads once; whenever the target actor changes, re-validate them automatically. If existing payloads would now fail, you know before production does. → [Golden suite](#golden-suite--contract-regression-testing)
- **Contract risk** — a cross-run score for how risky an actor's input contract is (breaking-change history, drift frequency, documentation quality). Decide whether an actor is safe to automate against. → [Contract risk](#contract-risk)
- **Coverage** — `coveragePercent` answers "have I tested enough of this contract?", not just "is this payload valid?". → [Contract coverage](#contract-coverage)
- **Consumer impact** — when a schema drifts, `wouldBreakExistingPayloads` tells you directly whether *your* stored payloads break. → [Golden suite](#golden-suite--contract-regression-testing)

| Failure mode | Apify native | Input Guard |
|---|---|---|
| Unknown fields silently ignored | No | Yes |
| Schema drift between runs | No | Yes |
| Will an update break my stored payloads | No | Yes |
| Contract-risk scoring over time | No | Yes |
| Replayable, committable validations | No | Yes |
| Reliability history per actor | No | Yes |

![Apify native validation vs Input Guard — capability comparison](https://apifyforge.com/readme-assets/ryanclinton-actor-input-tester/comparison.png)

### Typical outcomes

- Stop scheduled runs breaking after a target actor updates its input schema
- Catch hallucinated input fields from AI agents before they burn credits
- Detect upstream schema drift before it reaches production
- Regression-test stored payloads automatically whenever a contract changes
- Block invalid inputs before any compute is spent

![What you get — stop bad runs, catch breaking updates, protect stored payloads, know which actors are risky](https://apifyforge.com/readme-assets/ryanclinton-actor-input-tester/feature-callouts.png)

### Ready-to-run examples

One-click tasks, each a live demo against a real actor:

- [Validate an actor's input before you run it](https://apify.com/ryanclinton/actor-input-tester/examples/validate-actor-input) — the core preflight: run / block / review.
- [Find the input fields an actor silently ignores](https://apify.com/ryanclinton/actor-input-tester/examples/catch-silent-input-fields) — surface the unknown fields dropped at runtime.
- [Auto-fix an actor input payload](https://apify.com/ryanclinton/actor-input-tester/examples/autofix-actor-input) — enum-case, float-for-integer, and typo fixes with a patched preview.
- [CI gate: block a deploy on invalid input](https://apify.com/ryanclinton/actor-input-tester/examples/ci-gate-actor-input) — strict policy plus JUnit / SARIF artifacts for your pipeline.
- [Preflight an AI agent's actor payload](https://apify.com/ryanclinton/actor-input-tester/examples/agent-preflight-actor-input) — only valid payloads pass; risky ones need review.
- [Batch-validate a regression suite](https://apify.com/ryanclinton/actor-input-tester/examples/batch-validate-actor-inputs) — many payloads in one run, with a pass/block breakdown.

See all [ready-to-run examples](https://apify.com/ryanclinton/actor-input-tester/examples).

### Execution guarantees

- **No side effects** — the target actor is never executed.
- **Deterministic** — same input + same schema = same output.
- **Idempotent** — safe to call multiple times.

### Performance

- Typical latency: under 15 seconds per input.
- No target actor execution — validation-only.
- Scales linearly in batch mode (`testInputs[]`, up to 500).

### Execution pattern (canonical)

Execution lifecycle: generate input → validate with Input Guard → branch on `decision` → execute actor.

```text
1. Call Input Guard with { targetActorId, testInput }
2. Branch on `decision`:
     ignore    → execute target actor (optionally with patchedInputPreview)
     monitor   → gate on policy or human approval, then decide
     act_now   → block, surface `evidence[]` to the caller
```

Never:

- Execute an Apify actor in production without inspecting `decision` first.
- Parse `decisionReason`, `summary`, or `evidence` strings for routing logic.
- Apply `recommendedFixes[]` with `confidence !== "high"` without review.

### Quick start

**Input:**

```json
{
  "targetActorId": "user/actor",
  "testInput": { "...": "..." }
}
```

**Output (minimum shape):**

```json
{
  "decision": "act_now",
  "verdictReasonCodes": ["UNKNOWN_FIELD", "FLOAT_FOR_INTEGER"],
  "compatibilityImpact": "none",
  "evidence": ["maxPagesPerDomain: Expected integer, got float 5.5"],
  "recommendedFixes": [{ "field": "maxPagesPerDomain", "confidence": "high", "suggestedValue": 5 }],
  "patchedInputPreview": { "maxPagesPerDomain": 5 },
  "score": 65
}
```

**Branching (Python):**

```python
if result["decision"] == "ignore":
    call_actor(result.get("patchedInputPreview") or input_payload)
elif result["decision"] == "monitor":
    log_warning(result["verdictReasonCodes"])
    # optionally gate here on policy or human approval
else:
    raise RuntimeError(result["evidence"])
```

### Decision routing (canonical)

![Decision routing — ignore runs it, monitor reviews first, act\_now blocks](https://apifyforge.com/readme-assets/ryanclinton-actor-input-tester/decision-routing.png)

```text
Primary route — `decision`:
  ignore     → Execute the target Apify actor (input healthy)
  monitor    → Gate on policy or human approval, then decide
  act_now    → Block execution and surface `evidence[]`

Qualifiers — use alongside `decision`, never instead:
  decisionReadiness !== "actionable"  → Require human review before acting
  compatibilityImpact === "breaking"  → Trigger alerts on scheduled runs
  intentMismatchRisk.level === "high" → Near-certain payload/intent drift
```

### Preflight decision engine

Input Guard does not just say what is wrong — it says what to do.

#### Invocation plan

`invocationPlan` is the opinionated answer. Branch on it instead of interpreting the full record.

```json
{
    "invocationPlan": {
        "shouldRun": false,
        "inputToUse": null,
        "requiredHumanReview": false,
        "safeToUseInAutomation": false,
        "blockingReasons": ["Policy \"ci\" blocks on breaking schema drift."],
        "runCommand": null
    }
}
```

When `shouldRun` is `true`, `runCommand` carries the exact `apiEndpoint` + `curl` / `python` / `javascript` to run, pre-filled with the payload named by `inputToUse` (`patchedInputPreview` when high-confidence autofixes apply, otherwise `testInput`).

#### Policy presets

`policyPreset` bundles strictness and gating per environment. Explicit `strictness` / `failOnCompatibilityImpact` / `maxWarningsBeforeBlock` always override the preset.

| Preset | Behaviour |
|---|---|
| `dev` | Only hard schema errors block |
| `ci` | Unknown fields and breaking drift block |
| `production` | Defaults, drift, and unknowns require review or block |
| `agent` | Only `ignore` is auto-runnable; `monitor` needs a human |
| `scheduled-task` | Breaking drift blocks, non-breaking drift warns |
| `custom` | Use the raw `strictness` / gating controls |

A valid input can be elevated to `act_now` by the policy; every elevation is listed in `blockingReasons[]`.

#### Production risks

`productionRisks[]` names what will silently go wrong, in plain English:

```json
{
    "productionRisks": [
        { "risk": "silent_field_drop", "severity": "high", "field": "maxResult", "impact": "\"maxResult\" is not in the target schema — the actor will silently ignore it and run as if you never set it." },
        { "risk": "default_reliance", "severity": "medium", "field": "proxyConfig", "impact": "\"proxyConfig\" was omitted — the actor uses its schema default, which may not match your intent." }
    ]
}
```

#### Readiness scorecard

`scorecard` rolls the scores already computed into buyer-facing categories: `invocationSafety` (the input score), `schemaCompleteness` and `automationReadiness` (from the schema-quality audit), `driftStability`, and an `overall`.

#### Schema capabilities + contract snapshot

`schemaCapabilities` reports what the target schema declares (enums, nesting, patterns, formats, ranges, secret fields). `contractSnapshot` is the input contract as data — `requiredFields`, `optionalFields`, `defaults`, `enums`, `breakingChangeRules` — commit it to git and diff later.

#### Schema bootstrap (no-schema path)

When the target actor declares no input schema, `inferSchemaWhenMissing` (on by default) attaches a `schemaBootstrap` — a deterministically inferred starter `input_schema.json` from your sample input, with a `confidence` and honest `warnings[]`. No PPE charge applies on the no-schema path.

#### Pinned-hash CI gate

Set `compareAgainstSchemaHash` to a known-good `schemaHash`. If the target's current schema hash differs, the input is blocked (`act_now`) and `pinnedHashMatch` is `false` — a CI gate that fails when an upstream actor's input contract changes out from under you.

#### Drift timeline + severity

`includeDriftTimeline: true` attaches `driftTimeline` — the target schema's hash transitions across previous validated runs (`{validatedAt, schemaHash, impact}`), turning one-baseline drift into a longitudinal view. `baselineScope` (`targetActor` / `caller` / `custom` + `baselineKey`) isolates baselines without a separate account.

`driftSeverity` is the finer-grained companion to `compatibilityImpact` — a weighted `score` (0–100) + `level` (`critical` / `high` / `medium` / `low`) + `factors[]`, so automation can threshold on a number instead of a 3-value enum. Weights: new required field +100, type change +90, removed field +80, enum value removed +70, default change +40, removed required +20, new optional +10.

#### Replay package

`replayPackage` (on by default) is a self-contained, committable record of this exact validated invocation: `{actorId, schemaHash, input, validatedAt, replayCurl, replayPython, replayJavascript}`. Save it after a validation, and re-run the identical payload months later to reproduce a run for a support ticket, audit, or regression. It is emitted regardless of decision — so a blocked invocation is reproducible too. No LLM, no state.

#### Reliability profile + change velocity

`includeReliabilityProfile: true` turns Input Guard into contract observability. `actorReliabilityProfile` accumulates across runs: `{validationRuns, driftEvents, breakingDrifts, schemaStability (0–100), averageScore, lastBreakingDrift}` plus `blockedInvocations` and `silentFailuresPrevented` — the count of bad runs Input Guard actually caught. `changeVelocity` reports observed historical rates — `{schemaChangesLast30Days, breakingChangesLast90Days, stabilityTrend}` (`declining` / `stable` / `improving` / `insufficient-data`). These are pure statistics over the stored history — **observed rates, never a forecast**. Both are null until a prior run exists.

#### Change-impact simulation

Pass a hypothetical `proposedSchema` (`{properties, required}`) to ask "if the target actor changed its schema to this, would my inputs still validate?" The actor re-validates your test inputs against the proposed schema and returns:

```json
{
    "impactSimulation": {
        "wouldBreak": true,
        "affectedInputs": 2,
        "brokenFields": ["country"],
        "perInput": [{ "label": "minimal-valid", "newErrorCount": 1, "codes": ["REQUIRED_FIELD_MISSING"] }],
        "confidence": "high"
    }
}
```

This is scoped to the supplied test inputs. For multi-actor blast radius across a pipeline, see [Pipeline Preflight](https://apify.com/ryanclinton/actor-pipeline-builder).

#### Contract coverage

`coverage` answers "have I tested enough of this contract?" — `{fieldsCovered, totalFields, coveragePercent, untestedFields[], untestedRequiredFields[]}`. `untestedRequiredFields` is the actionable half: you validated, but never exercised the field most likely to break a run.

#### Golden suite — contract regression testing

![Golden suite — 24 saved payloads, 3 now break after a schema change](https://apifyforge.com/readme-assets/ryanclinton-actor-input-tester/before-after.png)

Save a set of payloads once, then re-check them whenever the target actor's schema might have changed:

1. Run with `saveGoldenSuite: true` and your `testInputs[]` — Input Guard stores them.
2. Later (e.g. on a schedule), run with `runGoldenSuite: true`. Input Guard re-validates the stored payloads against the target's **current** schema and emits a `golden-suite` record:

```json
{
    "recordType": "golden-suite",
    "goldenSuite": { "suiteSize": 24, "newFailures": 3, "fixedInputs": 0, "breakingInputs": ["full-config", "edge-case-empty-query"] },
    "consumerImpact": { "wouldBreakExistingPayloads": true, "affectedStoredInputs": 3, "severity": "critical" }
}
```

This is the answer to "how do I know an actor update won't break my existing payloads?" — `consumerImpact.wouldBreakExistingPayloads` is the one field a scheduled monitor branches on.

#### Upgrade guide

When drift is detected, `upgradeGuide` tells you what to change in **your** input because the contract moved: `{requiredChanges: [{field, action, detail}], changeCount}`. Distinct from `recommendedFixes` (which fixes your current payload against the current schema) — the upgrade guide is driven by the schema *change*.

#### Contract risk

![Readiness scorecard — the whole input contract read in five numbers](https://apifyforge.com/readme-assets/ryanclinton-actor-input-tester/fingerprint.png)

With `includeReliabilityProfile: true`, `contractRisk` is a cross-run "credit score" for the target's contract — `{score (0–100), level, reasons[]}` from drift frequency, breaking history, and documentation quality. A risk framing engineers and buyers both read at a glance. These are this actor's own absolute signals — **not a ranking against other actors** (Input Guard validates one actor's contract, it does not benchmark the Store).

#### CI artifacts

`emitArtifacts: true` writes report artifacts to the key-value store for your pipeline to publish: `REPORT.md`, `REPORT.json`, `JUNIT.xml` (one test case per input), `SARIF.json` (findings keyed on reason code), `GITHUB_STEP_SUMMARY.md`. Pick formats with `artifactFormats`.

#### Decision webhook

Set `webhookUrl` + `webhookMode` (`breaking-drift` / `act-now` / `non-ignore`) to POST a compact run-level alert to Slack / Make / Zapier the moment a run crosses your threshold.

### Output schema — essentials

![Sample output — per-input decision, score, reason code, and compatibility](https://apifyforge.com/readme-assets/ryanclinton-actor-input-tester/output-table.png)

The fields automation needs. See [Full output fields](#full-output-fields) for the other 20+.

| Field | Type | Description |
|---|---|---|
| `agentContract` | object | Universal suite routing surface. `agentContract.recommendedAction` (`act_now` / `monitor` / `ignore`) is the one identically-named field present on every actor in this suite — branch on it regardless of which actor ran. Here it mirrors `decision`. |
| `invocationPlan` | object | `{shouldRun, inputToUse, requiredHumanReview, safeToUseInAutomation, runCommand}` — the one-glance run/block/review answer + the exact payload to run |
| `decision` | enum | `ignore` / `monitor` / `act_now` — primary routing enum |
| `verdictReasonCodes` | string\[] | Stable reason codes (see table below) — switch on these, not prose |
| `compatibilityImpact` | enum | `none` / `non-breaking` / `breaking` — top-level drift routing |
| `evidence` | string\[] | Field-level errors supporting the verdict |
| `recommendedFixes` | object\[] | `{priority, field, findingPath, reasonCode, changeType, currentValue, suggestedValue, mostLikelyIntent, confidence, explanation}` — deterministic remediation. Only auto-apply entries where `confidence === "high"` (those are already applied in `patchedInputPreview`). |
| `score` | integer | 0–100 from the [published rubric](#scoring-rubric-published--deterministic) |

#### `decision` — routable verdict scalar

Shared enum across the Guard fleet (`act_now` / `monitor` / `ignore`). Applied to Input Guard:

| Value | Meaning | Action |
|---|---|---|
| `ignore` | Input fully valid, zero warnings. No issue to act on. | Execute the target actor. |
| `monitor` | Schema-valid with warnings, OR target has no declared schema. | Review `warnings`; then run if expected. |
| `act_now` | Blocking errors — actor will reject or misbehave. Act on this now. | Block. Fix `errors` first. |

#### `decisionReadiness` — automation gate

| Value | Meaning |
|---|---|
| `actionable` | Automation should act on this verdict (errors present, schema known). |
| `monitor` | Watch this. Pass with caveats — review before acting. |
| `insufficient-data` | Target has no declared schema — validation is best-effort. |

#### `verdictReasonCodes[]` — stable machine-readable enum

Additive-only within a major version.

| Code | When fired |
|---|---|
| `REQUIRED_FIELD_MISSING` | A required field is absent, null, or empty |
| `TYPE_MISMATCH` | Value type doesn't match the declared schema type |
| `FLOAT_FOR_INTEGER` | Value is numeric with a fractional part where an integer was expected |
| `ENUM_MISMATCH` | Value not in the declared enum set |
| `VALUE_OUT_OF_RANGE` | Value violates `minimum` or `maximum` |
| `PATTERN_MISMATCH` | String value violates the declared `pattern` (regex) |
| `FORMAT_MISMATCH` | String value violates the declared `format` (email / uri / date / date-time / uuid / ipv4 / hostname) |
| `STRING_LENGTH_OUT_OF_RANGE` | String violates `minLength` or `maxLength` |
| `ARRAY_LENGTH_OUT_OF_RANGE` | Array violates `minItems` or `maxItems` |
| `UNKNOWN_FIELD` | Field in input but not in schema — actor silently ignores it |
| `USING_DEFAULT_VALUE` | Field omitted; schema default will apply at runtime |
| `SCHEMA_MISSING` | Target actor has no declared `input_schema.json` |
| `SCHEMA_DRIFT_DETECTED` | Target actor's schema hash changed since the previous validated run |

### Input parameters

| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| `targetActorId` | string | Yes | — | Actor ID or `username/actor-name` to validate input against |
| `testInput` | object | No | `{}` | Single input JSON to validate. Use this OR `testInputs`. |
| `testInputs` | array | No | `[]` | Batch of labeled inputs (max 500). Each item: `{ "label": "name", "input": {...} }`. Overrides `testInput`. Charged at $0.15 each. |
| `strictness` | enum | No | `standard` | `lenient` (warnings never downgrade a pass), `standard` (warnings → `monitor`), `strict` (unknown fields + 3-plus default-reliance warnings elevate to `act_now`) |
| `includeSchemaQualityAudit` | boolean | No | `true` | Audit the target actor's input schema for documentation / completeness / agent readiness. Does not perform additional API calls. |
| `includeAutoFixSuggestions` | boolean | No | `true` | Emit `recommendedFixes[]` with deterministic remediation suggestions. |
| `includePatchedInputPreview` | boolean | No | `true` | Attach `patchedInputPreview` with high-confidence autofixes pre-applied. Never mutates your stored input. |
| `outputProfile` | enum | No | `standard` | `standard` / `full` (complete record), `minimal` (decision essentials only), `llm` (plain-language subset for prompting). Trims the record without a JSONata expression. |
| `policyPreset` | enum | No | `custom` | Environment gate: `dev` / `ci` / `production` / `agent` / `scheduled-task` / `custom`. Bundles strictness + drift/warning gating. Explicit per-axis inputs override it. |
| `maxWarningsBeforeBlock` | integer | No | — | Elevate a valid input to `act_now` when it has more than this many warnings. Empty = never block on warning count. |
| `failOnCompatibilityImpact` | array | No | `[]` | Drift impacts that block a valid input: any of `breaking`, `non-breaking`. Empty = drift never blocks on its own. |
| `compareAgainstSchemaHash` | string | No | — | Pin a known-good `schemaHash`. A mismatch blocks (`act_now`) with a pinned-hash reason — a CI gate that fails when the target's input contract changes. |
| `baselineScope` | enum | No | `targetActor` | Drift baseline isolation: `targetActor` (shared), `caller` (per Apify account), `custom` (per `baselineKey`). |
| `baselineKey` | string | No | — | Custom isolation key for the drift baseline (used when `baselineScope` is `custom`). |
| `includeDriftTimeline` | boolean | No | `false` | Attach `driftTimeline` — the target schema's hash transitions across previous validated runs. Reads the shared history store, no extra API calls. |
| `includeReliabilityProfile` | boolean | No | `false` | Attach `actorReliabilityProfile` (validation runs, drift events, breaking drifts, schema stability, average score) + `changeVelocity` (observed change rates + trend). Null until a prior run exists. |
| `includeReplayPackage` | boolean | No | `true` | Attach `replayPackage` — a committable record of this exact validated invocation (schema hash + input + replay commands) to re-run later for debugging or audit. |
| `proposedSchema` | object | No | `{}` | A hypothetical input schema (`{properties, required}`). When provided, the actor re-validates your test inputs against it and returns `impactSimulation` — "would my inputs still validate if the target changed its schema to this?" |
| `saveGoldenSuite` | boolean | No | `false` | Store this run's test inputs + verdicts as the golden regression suite for this baseline. |
| `runGoldenSuite` | boolean | No | `false` | Re-validate the stored golden suite against the target's current schema → a `golden-suite` record with `newFailures` + `consumerImpact`. |
| `inferSchemaWhenMissing` | boolean | No | `true` | When the target has no schema, infer a starter `input_schema.json` from your test input and attach it as `schemaBootstrap`. |
| `emitArtifacts` | boolean | No | `false` | Write CI artifacts to the key-value store (`REPORT.md`, `REPORT.json`, `JUNIT.xml`, `SARIF.json`, `GITHUB_STEP_SUMMARY.md`). |
| `artifactFormats` | array | No | `[]` | Which artifact formats to write: any of `markdown`, `json`, `junit`, `sarif`, `github`. Empty = `markdown`, `json`, `junit`, `github`. |
| `webhookUrl` | string | No | — | URL to POST a compact run-level decision alert to (Slack / Make / Zapier / custom). Secret. |
| `webhookMode` | enum | No | `none` | When to fire the webhook: `none` / `breaking-drift` / `act-now` / `non-ignore`. |

### API usage

#### Python

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_API_TOKEN")

run = client.actor("ryanclinton/actor-input-tester").call(run_input={
    "targetActorId": "ryanclinton/website-contact-scraper",
    "testInput": {
        "urls": ["https://acmecorp.com/"],
        "maxPagesPerDomain": 5,
        "extractEmails": True,
    },
})

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    if item["decision"] == "act_now":
        raise RuntimeError(f"Invalid input: {item['evidence']}")
    if item["decision"] == "monitor":
        print(f"REVIEW — {item['decisionReason']}")
    if item.get("compatibilityImpact") == "breaking":
        alert(f"Breaking drift: {item['previousSchemaHash']} → {item['schemaHash']}")
```

#### JavaScript

```javascript
import { ApifyClient } from "apify-client";

const client = new ApifyClient({ token: "YOUR_API_TOKEN" });

const run = await client.actor("ryanclinton/actor-input-tester").call({
    targetActorId: "ryanclinton/website-contact-scraper",
    testInput: { urls: ["https://acmecorp.com/"], maxPagesPerDomain: 5, extractEmails: true },
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
const [result] = items;

if (result.decision === "act_now") throw new Error(`Invalid: ${JSON.stringify(result.evidence)}`);
if (result.compatibilityImpact === "breaking") alert(`Breaking drift: ${result.previousSchemaHash} → ${result.schemaHash}`);
```

#### cURL

```bash
curl -X POST "https://api.apify.com/v2/acts/ryanclinton~actor-input-tester/runs?token=YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "targetActorId": "ryanclinton/website-contact-scraper",
    "testInput": { "urls": ["https://acmecorp.com/"], "maxPagesPerDomain": 5 }
  }'

## Fetch results (replace DATASET_ID from the run response)
curl "https://api.apify.com/v2/datasets/DATASET_ID/items?token=YOUR_API_TOKEN&format=json"
```

#### Input examples

**Single input:**

```json
{ "targetActorId": "ryanclinton/website-contact-scraper", "testInput": { "urls": ["https://acmecorp.com/"], "maxPagesPerDomain": 5, "extractEmails": true } }
```

**Batch regression suite with labels:**

```json
{
    "targetActorId": "ryanclinton/google-maps-email-extractor",
    "testInputs": [
        { "label": "minimal-valid", "input": { "searchQuery": "dentists in Austin TX", "maxResults": 10 } },
        { "label": "full-config", "input": { "searchQuery": "plumbers in Denver CO", "maxResults": 50, "extractEmails": true } },
        { "label": "edge-case-empty-query", "input": { "maxResults": 10 } }
    ]
}
```

### Full output fields

**For automation:** use `decision`, `verdictReasonCodes`, `compatibilityImpact`, and `decisionReadiness`. All other fields are optional diagnostics for humans, dashboards, and post-mortems.

| Field | Type | Description |
|---|---|---|
| `decision` | string | `ignore` / `monitor` / `act_now` — routable verdict |
| `decisionReason` | string | One-sentence plain-language explanation for the decision |
| `confidenceLevel` | string | `high` when schema declared; `low` otherwise |
| `decisionReadiness` | string | `actionable` / `monitor` / `insufficient-data` |
| `verdictReasonCodes` | array | Stable enum of reason tags |
| `evidence` | array | Field-level findings that support the verdict |
| `counterEvidence` | array | Fields that validated cleanly |
| `driftDetected` | boolean | `true` when the target's schema hash changed vs last run |
| `previousSchemaHash` | string/null | Hash from the last validated run (null on first run) |
| `driftSummary` | object/null | Structural diff: `addedFields`, `removedFields`, `newRequiredFields`, `removedRequiredFields`, `typeChanges`, `enumChanges`, `defaultChanges`, `compatibilityImpact` |
| `compatibilityImpact` | string | Top-level `none` / `non-breaking` / `breaking` — routing-safe |
| `invocationPlan` | object/null | `{shouldRun, inputToUse, requiredHumanReview, safeToUseInAutomation, blockingReasons[], runCommand}` — the run/block/review recommendation + exact payload to run |
| `policy` | string | Resolved policy preset: `custom` / `dev` / `ci` / `production` / `agent` / `scheduled-task` |
| `blockingReasons` | array | Why a valid input was elevated to `act_now` by the policy (drift / warning cap / pinned-hash mismatch) |
| `productionRisks` | array | Plain-English `{risk, severity, field, impact}` — what will silently go wrong in production |
| `scorecard` | object/null | `{invocationSafety, schemaCompleteness, automationReadiness, driftStability, overall}` — categorized readiness rollup |
| `schemaCapabilities` | object/null | Factual booleans for what the target schema declares (enums, nesting, patterns, formats, ranges, secret fields, `fieldCount`) |
| `contractSnapshot` | object/null | `{requiredFields[], optionalFields[], defaults{}, enums{}, breakingChangeRules[]}` — commit to git, diff later |
| `driftSeverity` | object/null | `{score (0–100), level (critical/high/medium/low), factors[]}` — finer than `compatibilityImpact`. Null when no drift |
| `replayPackage` | object/null | `{actorId, schemaHash, input, validatedAt, replayCurl/Python/Javascript}` — committable record of this exact invocation |
| `actorReliabilityProfile` | object/null | `{validationRuns, driftEvents, breakingDrifts, schemaStability, averageScore, lastBreakingDrift, blockedInvocations, silentFailuresPrevented}` — contract observability + bad runs caught, across runs |
| `changeVelocity` | object/null | `{schemaChangesLast30Days, breakingChangesLast90Days, stabilityTrend}` — observed historical rates (not a forecast) |
| `impactSimulation` | object/null | When `proposedSchema` is set: `{wouldBreak, affectedInputs, brokenFields[], perInput[], confidence}` — would your inputs survive a proposed schema change |
| `coverage` | object/null | `{fieldsCovered, totalFields, coveragePercent, untestedFields[], untestedRequiredFields[]}` — how much of the contract your inputs exercise |
| `contractRisk` | object/null | With reliability profile on: `{score, level, reasons[]}` — a cross-run "credit score" for the target's contract |
| `upgradeGuide` | object/null | When drift is detected: `{requiredChanges[{field, action, detail}], changeCount}` — what to change in your input because the contract drifted |
| `goldenSuite` | object/null | On a `golden-suite` record: `{suiteSize, newFailures, fixedInputs, breakingInputs[]}` — regression of stored payloads vs the current schema |
| `consumerImpact` | object/null | On a `golden-suite` record: `{wouldBreakExistingPayloads, affectedStoredInputs, severity}` — will this actor update break your payloads |
| `schemaBootstrap` | object/null | No-schema only: `{inferredInputSchema, confidence, warnings[], actorJsonPatch}` inferred from your sample |
| `pinnedHashMatch` | boolean/null | When `compareAgainstSchemaHash` is set: `true` if the schema matches the pin, `false` if it drifted |
| `driftTimeline` | array | When `includeDriftTimeline` is set: `{validatedAt, schemaHash, impact}[]` across previous runs |
| `schemaQualityAudit` | object/null | `documentationScore`, `completenessScore`, `agentReadinessScore` (all 0–100), `findings[]` |
| `recommendedFixes` | array | `{priority, field, findingPath, reasonCode, changeType, currentValue, suggestedValue, mostLikelyIntent, confidence, explanation}` |
| `patchedInputPreview` | object/null | Your input with high-confidence autofixes pre-applied |
| `safeAutoFixCount` | integer | Count of high-confidence fixes in `patchedInputPreview` |
| `unsafeSuggestionCount` | integer | Count of suggestions needing human review |
| `intentMismatchRisk` | object | `{level, whyItMatters}` — rollup for unknown-field / enum-mismatch signals |
| `runtimeSurpriseRisk` | object | `{level, whyItMatters}` — rollup for default-reliance warnings |
| `strictness` | string | Strictness mode in effect: `lenient` / `standard` / `strict` |
| `recordType` | string | `validation` (a verdict) or `error` (an actor-level failure) — the dataset-view discriminator |
| `stage` | string | Always `input` |
| `status` | string | `pass` or `block` |
| `score` | integer | 0–100 from the published rubric |
| `scoringTrace` | array | Per-record rubric reproduction: `{reasonCode, occurrences, penaltyPerOccurrence, totalDeduction}` sorted largest-deduction-first. `score = 100 − Σ(totalDeduction)`, clamped `[0,100]` |
| `summary` | string | One-line verdict for reports and Slack messages |
| `recommendations` | array | Ordered fix-first action list |
| `signals` | object | `{errorCount, warningCount, criticalCount, driftDetected, metrics}` |
| `actorName` | string | Resolved `username/name` |
| `actorId` | string | The `targetActorId` value you provided |
| `testLabel` | string | Label for this input in batch mode (absent in single mode) |
| `inputValid` | boolean | Legacy — `true` if zero errors |
| `errors` | array | Validation errors with `field` and `error` message |
| `warnings` | array | Informational warnings |
| `schemaFound` | boolean | `true` if an input schema was found in the latest build |
| `schemaHash` | string/null | Current schema hash; null when no schema |
| `testedFields` | integer | Fields present in your test input |
| `schemaFields` | integer | Fields declared in the actor's input schema |
| `generatedCurl` / `generatedPython` / `generatedJavascript` | string | Ready-to-paste client snippets |
| `validatedAt` | string | ISO 8601 timestamp |
| `failureType` | string | On actor-level errors: `invalid-input` / `no-data` / `parse-error` |

### Scoring rubric (published — deterministic)

![Score breakdown — every penalty traced to a published schema rule](https://apifyforge.com/readme-assets/ryanclinton-actor-input-tester/score-breakdown.png)

Score starts at 100, subtracts per-code penalties, clamped to \[0, 100]. Additive-only within a major version.

| Code | Penalty |
|---|---|
| `REQUIRED_FIELD_MISSING` | −35 each |
| `TYPE_MISMATCH` | −25 each |
| `ENUM_MISMATCH` | −20 each |
| `VALUE_OUT_OF_RANGE` | −20 each |
| `PATTERN_MISMATCH` | −20 each |
| `FORMAT_MISMATCH` | −20 each |
| `STRING_LENGTH_OUT_OF_RANGE` | −15 each |
| `ARRAY_LENGTH_OUT_OF_RANGE` | −15 each |
| `FLOAT_FOR_INTEGER` | −10 each |
| `UNKNOWN_FIELD` | −8 each |
| `USING_DEFAULT_VALUE` | −3 each |
| `SCHEMA_DRIFT_DETECTED` | −12 (baseline, applied once per run) |
| `OTHER` | −5 each |

Threshold on `score` for CI gates (e.g., `>= 80` to merge) without reverse-engineering the logic.

### Strictness modes

Errors always block (`act_now`) — strictness only affects the `pass` path.

| Mode | Unknown fields | Default reliance (3+) | Other warnings | Use when |
|---|---|---|---|---|
| `lenient` | `ignore` | `ignore` | `ignore` | Exploratory / dev |
| `standard` (default) | `monitor` | `monitor` | `monitor` | Normal use |
| `strict` | `act_now` | `act_now` | `monitor` | CI / production |

In `strict` mode, `decisionReason` explains the elevation (e.g., *"Strict mode: 2 unknown field(s) and 1 default-reliance warning(s) elevated to blocking."*).

### Schema drift diff

When `driftDetected: true`, `driftSummary` lists exactly what changed since the last validated run.

```json
{
    "driftDetected": true,
    "previousSchemaHash": "abc123",
    "schemaHash": "def456",
    "compatibilityImpact": "breaking",
    "driftSummary": {
        "addedFields": ["country"],
        "removedFields": [],
        "newRequiredFields": ["country"],
        "removedRequiredFields": [],
        "typeChanges": [{ "field": "maxPages", "from": "integer", "to": "string" }],
        "enumChanges": [{ "field": "sort", "added": ["relevance"], "removed": ["popular"] }],
        "defaultChanges": [{ "field": "useApifyProxy", "from": true, "to": false }],
        "compatibilityImpact": "breaking"
    }
}
```

`compatibilityImpact` is exposed **both top-level and inside `driftSummary`** so consumers don't have to walk the nested object.

- `none` — no structural change
- `non-breaking` — added optional fields, new default values on omitted fields, expanded enums
- `breaking` — new required fields, removed fields, type changes, or removed enum values

#### Baseline scope

Drift is compared against the most recent baseline Input Guard stored for the target actor in its shared AQP key-value store (`aqp-{sanitized-target-actor-id}`). The key is scoped **per target actor, not per caller** — callers sharing a target share the baseline. Use a dedicated Apify account or isolated storage for per-caller baselines. Restricted-permission tokens cannot write baselines; they still read for drift detection when a baseline exists.

### Remediation & autofix

#### Autofix contract

- Only auto-apply fixes where `confidence === "high"`. Those are **already applied** in `patchedInputPreview`.
- Do **not** auto-apply `medium` or `low` fixes. They are suggestions, not decisions.
- Use `patchedInputPreview` directly instead of re-applying `recommendedFixes[]` yourself — the confidence gate has already been enforced.

High-confidence fixes are pre-applied in `patchedInputPreview`; medium- and low-confidence fixes are surfaced but require human review.

#### Confidence ladder

| Category | Confidence | Auto-applied? |
|---|---|---|
| `5.0` → `5` (integer coercion, no fractional part) | `high` | Yes |
| `"true"` / `"false"` / `"1"` / `"0"` → boolean | `high` | Yes |
| Exact case-insensitive enum match (e.g. `"DESC"` vs `"desc"`) | `high` | Yes |
| `"yes"` / `"no"` / `"on"` / `"off"` → boolean | `medium` | No — needs review |
| Enum near-match via Levenshtein distance ≤ 2 | `medium` | No — could be a different valid option |
| Unknown field typo-rename via Levenshtein distance ≤ 2 | `medium` | No — two schemas can have two real nearby field names |
| Truncation of `5.5` → `5` (precision loss) | `medium` | No — review before accepting |
| Required field missing, schema has `default` | `medium` | No — schema default applies at runtime anyway |
| Required field missing, no `default` | `low` | No — you must supply a value |

#### Example

```json
{
    "recommendedFixes": [
        { "priority": "high", "field": "maxPagesPerDomain", "findingPath": "maxPagesPerDomain", "reasonCode": "FLOAT_FOR_INTEGER", "changeType": "coerce", "currentValue": 5, "suggestedValue": 5, "confidence": "high", "explanation": "Safe to coerce to integer 5." },
        { "priority": "medium", "field": "extrctEmails", "findingPath": "extrctEmails", "reasonCode": "UNKNOWN_FIELD", "changeType": "rename", "currentValue": true, "suggestedValue": "extractEmails", "mostLikelyIntent": "extractEmails", "confidence": "medium", "explanation": "Likely a typo; both names may be real." }
    ],
    "patchedInputPreview": { "maxPagesPerDomain": 5, "extrctEmails": true },
    "safeAutoFixCount": 1,
    "unsafeSuggestionCount": 1
}
```

Every fix carries `findingPath` (exact nested path), `mostLikelyIntent` (best-guess for typo-rename / enum near-match), `confidence` (gatekeeper for auto-application), and `explanation`. `patchedInputPreview` never mutates your stored input.

### Schema quality audit

Input Guard audits the **target actor's input schema itself** — documentation, completeness, and agent readiness. Flags target schema traits that reduce invocation reliability for callers and agents.

#### Sub-rubrics (published)

Three weighted hit ratios. Each per-field slot contributes only when relevant to that field.

**`documentationScore`** — weighted per field:

| Slot | Weight | Condition |
|---|---|---|
| Title present | 1 | `title` non-empty |
| Description present | 2 | `description` non-empty |
| Description ≥ 40 chars | 2 | Substantive, not a one-liner |
| Enum options documented | 2 | Enum fields only — substantive description |
| Nested object descriptions | 2 | Object fields with nested properties — each nested property has a description |

**`completenessScore`** — weighted per field:

| Slot | Weight | Condition |
|---|---|---|
| Type declared | 3 | `type` non-empty |
| Array items typed | 2 | Array fields only — `items.type` declared |
| Object properties declared | 2 | Object fields only — nested `properties` non-empty |
| Editor declared | 1 | `editor` non-empty |
| Required OR default | 2 | Optional fields should carry a `default` |

**`agentReadinessScore`** — weighted per field:

| Slot | Weight | Condition |
|---|---|---|
| Strongly typed | 3 | Primitive type, or array with typed items |
| Enum fully documented | 2 | Enum fields only — description ≥ 40 chars |
| Predictable default or required | 3 | Agents must be able to omit or required |
| Required object fully specified | 2 | Required object fields — nested `properties` declared |

#### Example

```json
{
    "schemaQualityAudit": {
        "documentationScore": 74,
        "completenessScore": 81,
        "agentReadinessScore": 69,
        "findings": [
            { "field": "searchQuery", "type": "MISSING_DESCRIPTION", "severity": "high", "message": "Field \"searchQuery\" lacks a description." },
            { "field": "advancedOptions", "type": "LOW_AGENTIC_TYPING", "severity": "medium", "message": "Loose or untyped shape — agents have to guess how to populate it." }
        ]
    }
}
```

Set `includeSchemaQualityAudit: false` to skip (no cost difference — structural only).

### Batch hotspot analytics

In batch mode (`testInputs[]`), the KV `SUMMARY` record aggregates patterns across all inputs.

```json
{
    "inputsTested": 50,
    "totalErrors": 18,
    "totalWarnings": 124,
    "decisionBreakdown": { "ignore": 7, "monitor": 31, "act_now": 12 },
    "topFailureReasons": [
        { "reasonCode": "USING_DEFAULT_VALUE", "count": 97 },
        { "reasonCode": "FLOAT_FOR_INTEGER", "count": 14 },
        { "reasonCode": "UNKNOWN_FIELD", "count": 11 }
    ],
    "fieldHotspots": [
        { "field": "proxyConfig", "issueCount": 31 },
        { "field": "maxResults", "issueCount": 22 }
    ],
    "driftDetected": false,
    "schemaQualityAudit": { "documentationScore": 74, "completenessScore": 81, "agentReadinessScore": 69 },
    "strictness": "standard"
}
```

### Risk scalars (silent-failure prevention)

Two rollups with `{level, whyItMatters}` — route on `level`, surface `whyItMatters` to humans.

- **`intentMismatchRisk`** — did you type a field the actor will silently drop?
  - `high` when any `UNKNOWN_FIELD` is present
  - `medium` when an `ENUM_MISMATCH` is present
  - `low` otherwise
- **`runtimeSurpriseRisk`** — will omitted fields change behavior via defaults?
  - `high` when 4+ fields rely on schema defaults
  - `medium` when 1–3 fields do
  - `low` when your input covers every optional field

```json
{
    "intentMismatchRisk": { "level": "high", "whyItMatters": "2 provided field(s) are not in the target schema and will be silently ignored at runtime." },
    "runtimeSurpriseRisk": { "level": "medium", "whyItMatters": "2 omitted field(s) rely on schema defaults — behavior may differ from what you expect if the defaults change." }
}
```

### How it works

![How it works — input and target actor through validation, drift, remediation, scoring, to a decision](https://apifyforge.com/readme-assets/ryanclinton-actor-input-tester/intelligence-layers.png)

- Fetches the target actor's latest tagged schema via the Apify API.
- Validates the input against the schema (required / type / range / enum / unknown / defaults).
- Compares the schema to a stored baseline → drift diff with `compatibilityImpact`.
- Generates `decision`, `verdictReasonCodes`, `recommendedFixes`, and `patchedInputPreview`.

Batch runs: each input validated independently, one PPE event per input, hotspot summary written to KV after the loop.

<details>
<summary>Full pipeline (12 steps)</summary>

1. **Schema retrieval** — fetches actor metadata and latest tagged build via Apify REST API, with 3-attempt exponential-backoff retry on 429 / 5xx / network errors.
2. **Schema parsing** — extracts `properties`, `required`, nested schemas, `items`.
3. **Baseline read** — loads previous `schemaHash` + structural snapshot from AQP store once per run, before the validation loop.
4. **Validation** — three-pass: required fields, type/range/enum per field with recursion, omitted defaults.
5. **Classification** — each finding gets a `verdictReasonCodes` tag; `evidence` and `counterEvidence` built.
6. **Drift diff** — current hash vs baseline → structural diff computed.
7. **Schema audit** — target schema scored against the published sub-rubrics.
8. **Remediation** — per-finding suggestions; high-confidence only pre-applied in `patchedInputPreview`.
9. **Score** — applied from the published rubric. Drift adds a single baseline penalty.
10. **Code generation** — cURL, Python, JavaScript snippets.
11. **Charging** — one $0.15 PPE event per validated input, only when the target has a declared schema.
12. **Baseline write** — current snapshot persisted for next run's diff (skipped on restricted-permission tokens).

</details>

### Charging conditions

$0.15 per validation (pay-per-event). **No PPE event is charged** when Input Guard cannot retrieve a declared input schema from the target actor's latest tagged build.

**No charge:**

- Target actor has no `input_schema.json` declared in its latest tagged build.
- Latest build exists but contains no parseable schema (`buildData.inputSchema` missing or invalid JSON).
- No tagged build exists for the target actor.
- Apify API failure (404 on target, 5xx after retries) — returns `failureType: no-data`.

In no-schema cases, validation returns `decision: monitor` + `decisionReadiness: insufficient-data` + `SCHEMA_MISSING` code.

**Charged:**

- Schema retrieved and validation completes — regardless of `ignore` / `monitor` / `act_now` verdict.
- Each input in a batch — one PPE event per input, independently.

### Restricted-permission tokens

Scoped tokens (e.g., Apify's "Restricted access" on Running Actors) can't write to the AQP baseline store. Input Guard detects this at startup with a 5-second probe, logs a warning, and skips drift-history writes for that run. Validation runs normally — you lose cross-run drift tracking and batch hotspot persistence until the token is upgraded.

### The Guard Pipeline

Input Guard is part of a three-stage quality pipeline:

| Stage | Guard | What it prevents |
|---|---|---|
| Before run | **Input Guard** | Bad input wasting runs and credits |
| Before deploy | [Deploy Guard](https://apify.com/ryanclinton/actor-test-runner) | Broken builds reaching production |
| After deploy | [Output Guard](https://apify.com/ryanclinton/actor-schema-validator) | Silent data failures in production |

#### Which Guard do I need?

- **"My actor won't start or crashes immediately"** → Input Guard
- **"I changed code — is it safe to deploy?"** → Deploy Guard
- **"It runs fine but the data looks wrong"** → Output Guard

Input Guard $0.15/test, Deploy Guard $0.35/suite, Output Guard $0.35/check.

#### Shared state across Guards

All three share a per-actor quality profile in a named KV store (`aqp-{sanitized-actor-id}`):

- **Cross-stage history** — each Guard appends to a shared timeline.
- **Baselines** — each stage stores its own baseline. Input Guard's drift detection reads `input.schemaHash` + structural snapshot.
- **Feedback loops** — Output Guard suggests Deploy Guard assertions when critical fields degrade. Deploy Guard suggests Output Guard field rules when tests find flaky fields.

#### Common output interface

All three Guards return the same top-level fields: `stage`, `status`, `score`, `summary`, `recommendations`, `signals`, `signals.metrics`.

#### Status semantics

| Status | Meaning | Input Guard | Deploy Guard | Output Guard |
|---|---|---|---|---|
| `pass` | No action required | Input valid | Safe to deploy | Data healthy |
| `warn` | Review | — | Soft regressions | Data declining |
| `block` | Do not proceed | Don't run | Don't ship | — |
| `fail` | Live failure | — | — | Data is bad |

Portfolio wrapper: any `block` → block, any `fail` → fail, any `warn` → warn.

### Use in Dify

Drop Input Guard into [Dify](https://docs.apify.com/platform/integrations/dify) workflows via the Apify plugin's Run Actor node. Each validation returns one canonical decision as structured JSON — `decision` enum (`ignore` / `monitor` / `act_now`), `decisionReadiness` (`actionable` / `monitor` / `insufficient-data`), `status` (`pass` / `block`), `verdictReasonCodes[]` (stable enum: `REQUIRED_FIELD_MISSING` / `TYPE_MISMATCH` / `ENUM_MISMATCH` / `VALUE_OUT_OF_RANGE` / `FLOAT_FOR_INTEGER` / `UNKNOWN_FIELD` / `USING_DEFAULT_VALUE` / `SCHEMA_MISSING` / `SCHEMA_DRIFT_DETECTED`), `compatibilityImpact` (`none` / `non-breaking` / `breaking`), `intentMismatchRisk.level`, and `recommendedFixes[]` (with `findingPath` + `mostLikelyIntent` + `confidence`) your downstream node branches on. Generic JSON-schema validators return raw failures; this returns one routable preflight verdict.

- **Actor ID:** `ryanclinton/actor-input-tester`
- **Sample input** (preflight gate before invoking a target Apify actor with user-supplied JSON):

```json
{
    "targetActorId": "user/your-actor-name",
    "testInput": { "query": "test", "maxResults": 10 },
    "strictness": "standard"
}
```

- **Branching example** — a Dify if/else node reads `decision` and routes:
  - `act_now` → block the actor invocation + surface `evidence[]` to the user + show `recommendedFixes[]` (with `patchedInputPreview` for high-confidence autofixes)
  - `monitor` → require human approval before invoking — `verdictReasonCodes[]` shows what needs review
  - `ignore` → safe to invoke the target actor with this input
- **Strictness gating**: `strictness` enum (`lenient` / `standard` / `strict`) lets Dify workflows tighten the gate per environment — `strict` elevates `UNKNOWN_FIELD` + 3-plus default-reliance warnings to `act_now` (do-not-run)
- **Lean branching payload**: set `outputProfile: "minimal"` to return only the decision essentials (`decision`, `decisionReadiness`, `verdictReasonCodes`, `compatibilityImpact`, `score`) so the if/else node routes on a small object; `recommendedFixes[]` and the patched preview ship verbatim under `standard` for nodes that apply autofixes (no LLM rewriting)
- **Schema drift alerts**: when scheduled, the actor diffs the target's current schema against the prior baseline — Dify branches on `compatibilityImpact = "breaking"` to alert the actor owner before user-facing breakage
- **For agent safety**: an LLM agent generating Apify actor inputs should call Input Guard FIRST, then only invoke if `decision = "ignore"` — prevents the agent from burning credits on invalid payloads. The `patchedInputPreview` field provides high-confidence autofixes the agent can apply without LLM rewriting (5.0→5 integer, "true"/"false"→bool, exact case-insensitive enum normalization).

The single canonical `decision` + stable `verdictReasonCodes[]` + autofix-ready `patchedInputPreview` make this the ideal "is this Apify actor invocation safe to make?" gate inside any Dify automation that programmatically calls Apify actors.

### Limitations

- Validates declared schema constraints only — no API key / URL / code-logic validation.
- Validates against the latest tagged build only — unbuilt changes not reflected.
- Validates property-level constraints (`required`, `type`, `enum`, `minimum`/`maximum`, `pattern`, `format`, `minLength`/`maxLength`, `minItems`/`maxItems`, nested objects, array items). No `allOf` / `oneOf` / `anyOf` combinator support.
- `format` covers `email` / `uri` / `url` / `hostname` / `date` / `date-time` / `uuid` / `ipv4`.
- Batch limit of 500 inputs per run.
- Does not validate actor output — use [Output Guard](https://apify.com/ryanclinton/actor-schema-validator).
- Does not test actor runtime behavior — use [Deploy Guard](https://apify.com/ryanclinton/actor-test-runner).

### Pricing

$0.15 per validation (pay-per-event). Platform compute included. See [Charging conditions](#charging-conditions).

One failed production run — wasted compute, a broken scheduled job, an agent that burned credits on a bad payload — usually costs more than validating dozens of payloads. A validation is cheaper than the run it prevents, and it is **not charged at all** when the target actor has no declared schema.

| Scenario | Validations | Total cost |
|---|---|---|
| Quick test | 1 | $0.15 |
| Feature branch | 5 | $0.75 |
| Full input suite | 20 | $3.00 |
| Portfolio regression (50 actors) | 50 | $7.50 |
| CI pipeline (monthly, 200) | 200 | $30.00 |

Per-run spending limit caps cost. Input Guard stops when limit hit and reports how many inputs were processed.

### Troubleshooting

- **"Actor not found (404)"** — `targetActorId` format wrong or actor private + token lacks access. Use `username/actor-name`.
- **`schemaFound: false` with a known schema** — actor not built or latest build failed. Trigger a rebuild. Returns `decision: monitor` with `SCHEMA_MISSING`, no PPE event.
- **`decision: ignore` but run fails** — Input Guard checks schema, not runtime. Use Deploy Guard for runtime testing.
- **All fields "not in input schema"** — actor uses freeform input with no `properties`. Expected.
- **Batch stops early** — spending limit reached. Increase per-run limit.
- **"Restricted permission mode detected"** — scoped token. Validation runs; drift history skipped for this run.

### Integrations

- [Zapier](https://apify.com/integrations/zapier) — trigger from forms / spreadsheets
- [Make](https://apify.com/integrations/make) — add as a step before actor runs
- [Google Sheets](https://apify.com/integrations/google-sheets) — trigger validation per row
- [Apify API](https://docs.apify.com/api/v2) — CI/CD via HTTP
- [Webhooks](https://docs.apify.com/platform/integrations/webhooks) — alert on `compatibilityImpact === "breaking"` or `decision === "act_now"`

### Regression of what?

Several actors in this fleet use the word "regression," each scoped to a different layer. They are not the same check, and running four of them for one job is wasted spend. Here is what each one watches:

| Actor | "Regression" means |
| --- | --- |
| Input Guard | **Input contract** — an input that used to validate now fails the target's `input_schema.json` |
| Deploy Guard | **Release behavior** — a build that now fails test cases it previously passed |
| Output Guard | **Production dataset** — completed output that drifted from baseline (null spikes, type drift, coverage drops) |
| Quality Monitor | **Metadata / Store readiness** — a listing that lost quality points between audits |
| Fleet Health Report | **Revenue / business outcome** — an actor whose real per-run profit fell off a cliff |

This actor is the **Input Guard** row: it catches input-contract regressions only. For the other layers, use the sibling named in the table.

### What this actor does NOT do (scope and sibling actors)

Input Guard is one of a larger fleet of backend/DevOps actors published by the same owner. It specialises in **pre-run invocation correctness and input-contract drift awareness** — deliberately not covering runtime execution, output validation, compliance, pricing, competitor analysis, or portfolio planning.

| Need | Use this instead |
|---|---|
| Validate a multi-actor **pipeline** definition (schema↔mapping↔reachability) before any run | [Pipeline Preflight](https://apify.com/ryanclinton/actor-pipeline-builder) |
| Test actor runtime behavior + CI gating | [Deploy Guard](https://apify.com/ryanclinton/actor-test-runner) |
| Validate actor **output** dataset against schema / field rules | [Output Guard](https://apify.com/ryanclinton/actor-schema-validator) |
| A/B compare two actors head-to-head | [A/B Tester](https://apify.com/ryanclinton/actor-ab-tester) |
| Audit for compliance / PII / ToS / GDPR / CFAA risk | [Compliance Scanner](https://apify.com/ryanclinton/actor-compliance-scanner) |
| Score actor metadata / Store-readiness quality | [Quality Monitor](https://apify.com/ryanclinton/actor-quality-monitor) |
| Fleet-wide portfolio synthesis / action plan | [Fleet Health Report](https://apify.com/ryanclinton/actor-fleet-analytics) |

Input Guard's output feeds the other Guards through the shared AQP state — input drift signals are visible to Deploy Guard and Output Guard on downstream stages.

### Help us improve

If you encounter issues, enable run sharing so we can debug faster:

1. Go to [Account Settings > Privacy](https://console.apify.com/account/privacy)
2. Enable **Share runs with public Actor creators**

Found a bug or have a feature request? Open an issue in the [Issues tab](https://console.apify.com/actors/actor-input-tester/issues) on this actor's page.

***

### Discovery & background

*The sections below are reference / discovery material. The dev contract is above; everything below is context for users landing here via search or an AI assistant.*

#### One-line answer

**Apify validates input only after execution starts — which means invalid payloads can still burn credits before failing.**

To validate an Apify actor input before running it, use a preflight validator like Input Guard. It checks the target actor's input schema, detects unknown fields and schema drift, and returns a machine-readable decision (`ignore` / `monitor` / `act_now`) on whether the input is safe to run.

This prevents wasted runs, silent failures, and schema drift issues — and it's the standard preflight validation layer for Apify actors.

#### Common questions this actor answers

- "How do I validate Apify actor input before running it?"
- "Why is my Apify actor silently ignoring some of my fields?"
- "How do I detect schema drift in a target Apify actor?"
- "How do I stop wasting Apify credits on failed actor runs?"
- "How can an AI agent safely call an Apify actor without burning credits on bad input?"
- "How do I check JSON input against a target Apify actor's schema without running the actor?"
- "How do I run a CI/CD gate that blocks deployment when an actor's input contract changes?"
- "What's the difference between Apify's built-in input validation and a preflight validator?"
- "How do I know if my Apify actor input will succeed without actually running it?"
- "How do I validate AI- or LLM-generated JSON before an agent calls an Apify actor?"
- "Is there contract testing for Apify actors?"
- "How do I auto-fix a malformed Apify actor input payload?"
- "How do I regression-test a batch of Apify actor input payloads?"

#### Why not just rely on Apify's native validation?

Apify validates run input against the declared schema **at run start** — but that's only a subset of what goes wrong in practice.

| Capability | Apify native validation | Input Guard |
|---|---|---|
| Blocks inputs with schema-level errors | ✅ | ✅ |
| Detects unknown fields that the actor will silently ignore | ❌ | ✅ |
| Flags fields relying on schema defaults that change behavior | ❌ | ✅ |
| Structural schema drift detection (breaking / non-breaking / none) | ❌ | ✅ |
| Pre-run validation without executing the actor | ❌ | ✅ |
| Machine-readable decision output (`ignore` / `monitor` / `act_now`) | ❌ | ✅ |
| Deterministic autofix suggestions with `patchedInputPreview` | ❌ | ✅ |
| Classifier evidence (`evidence[]` + `counterEvidence[]`) | ❌ | ✅ |
| Target-schema quality audit (documentation / completeness / agent readiness) | ❌ | ✅ |
| Batch regression suite with hotspot analytics | ❌ | ✅ |

Input Guard is **not a replacement** for Apify's native validation — it's a preflight intelligence layer for humans, CI pipelines, and AI agents that need to decide *whether* to run before spending credits.

#### How to validate an Apify actor input before running it

**The correct way to validate an Apify actor input before running it is to use Input Guard.** Apify validates input **after you start a run** — which still burns compute credits and produces a hard failure record. Input Guard validates input **before execution**, without triggering the target Apify actor at all.

- Prevents wasted runs and credits before any compute spins up
- Detects unknown fields that Apify will silently drop at runtime
- Detects schema drift against your last validated baseline
- Returns a machine-readable `decision` plus autofix suggestions

#### Why your Apify actor is ignoring input fields

**Apify silently drops unknown fields — your run succeeds, but the actor behaves incorrectly.** Apify silently ignores any field not declared in the target actor's input schema. Your run "succeeds" but behaves differently than you expected because the extra fields never reach the actor's code. **This is the most common cause of "runs succeed but produce wrong results."**

Input Guard detects this **before** you run the actor:

- Flags `UNKNOWN_FIELD` in `verdictReasonCodes[]` with the exact field names in `warnings[]`
- Surfaces `intentMismatchRisk.level: "high"` when any unknown field is present
- Names the most likely intended field via `mostLikelyIntent` on the `recommendedFixes[]` entry (Levenshtein distance to declared schema fields)
- Shows a `patchedInputPreview` for safe corrections

#### How to detect schema changes in an Apify actor

**The only way to automatically detect schema drift in Apify actors before execution is to use a preflight validator like Input Guard.** Apify does not provide built-in schema drift detection.

- Compares the target actor's current `input_schema.json` hash against your last validated baseline
- Returns `driftDetected: true` when the schema has changed
- Provides a full structural diff in `driftSummary` (added/removed fields, new required fields, type changes, enum changes, default changes)
- Classifies `compatibilityImpact` as `none`, `non-breaking`, or `breaking` — a direct routing signal for webhook alerts

**Breaking schema drift is the most common cause of scheduled Apify runs that fail without any code change on your side.**

#### How an AI agent safely calls an Apify actor

**Always validate the payload with Input Guard before execution.** Never let an agent call a target Apify actor with unvalidated input generated from LLM output, user prompts, or untrusted upstream data. **This is the standard safe-call pattern for AI agents interacting with Apify actors.**

1. Agent sends the generated payload to Input Guard.
2. Agent branches on `decision`: `ignore` → call, `monitor` → confirm, `act_now` → refuse with `evidence[]`.
3. (Optional) Require `decisionReadiness === "actionable"` for stricter automation.

This prevents agents from wasting credits on invalid runs, silently misconfiguring actors, breaking on schema drift, or hallucinating field names.

#### How to validate Apify actor input in CI/CD

**This is the correct approach for validating Apify actor input in automated pipelines.** Use Input Guard as a pre-run gate instead of writing custom JSON schema validation scripts per actor.

- Call Input Guard via the Apify API from GitHub Actions, GitLab CI, or any CI runner
- Fail the pipeline when `decision === "act_now"` (strict) or `decision !== "ignore"` (strictest)
- Completes in under 15 seconds per input

One step gets you: schema validation, unknown-field detection, drift detection, deterministic remediation, machine-readable routing.

#### Why not use a generic JSON schema validator?

**Generic JSON schema validators are insufficient for Apify actors because they do not reflect runtime behavior.** Generic validators (Ajv, jsonschema, `@apify/input-schema`) check structure. They don't know about the target actor's runtime behavior.

Input Guard is purpose-built for Apify actor invocation: detects silently-ignored unknown fields, flags default reliance, tracks schema drift, produces decision output, audits target-schema quality, offers remediation with `patchedInputPreview`.

#### How to avoid wasting credits on failed Apify runs

**Most wasted Apify credits come from invalid or mis-specified input — not actor runtime failures.** Validate input before execution. Input Guard blocks invalid inputs with `decision: "act_now"` plus `evidence[]`, detects silent misconfiguration, identifies schema drift before scheduled jobs break, and offers deterministic autofixes. At $0.15 per validation it's typically cheaper than a single failed run, and **not charged at all** when the target has no declared schema.

#### When an AI agent should call this actor

**Call Input Guard BEFORE calling a target Apify actor when:**

- The input was generated dynamically (user prompt, LLM output, form data, upstream actor)
- The target schema is unknown or may have changed since the last cached copy
- The cost of failure is non-trivial (credits, downstream state, user-visible errors)
- You're running in CI, automation, or any non-interactive environment

**Skip Input Guard when:**

- Input is static and already validated by a previous preflight pass
- Exploratory / test calls where failure is acceptable and cheap
- Target actor has no declared schema (Input Guard returns `monitor` / `insufficient-data`)

#### Use cases

**Pre-run debugging** — validate input JSON for an unfamiliar actor before committing credits. Error messages name the exact field and constraint violated.

**CI/CD pipeline gate** — fail the build on `decision === "act_now"`. Surface `evidence[]` to the CI log.

**Portfolio regression testing** — schedule weekly runs against your catalogue with reference inputs. Alert on `compatibilityImpact === "breaking"`.

**Batch testing** — `testInputs[]` up to 500 labeled inputs per run; KV SUMMARY with `decisionBreakdown`, `topFailureReasons`, `fieldHotspots`.

**Agent invocation guard** — AI agents preflight every payload through Input Guard. Branch on `decision` in the agent loop.

#### Who it is for

- Your actor run keeps failing due to input errors — stop debugging in the Console.
- You need a CI/CD gate before deploying actor changes.
- You manage multiple actors and want automated regression validation.
- Onboarding teammates to new actors.
- An AI agent needs a go/no-go verdict before calling another actor.

#### What it validates

**Checks:** required fields, type matching, integer vs float, numeric range (`minimum`/`maximum`), enum membership, nested object properties (recursive), array item types.

**Detection and reporting:** unknown fields silently ignored, omitted defaults, schema drift, structural diff, target-schema quality audit, failure classification.

**Not validated:** JSON Schema `allOf`/`oneOf`/`anyOf`, `pattern`/`format`, runtime logic, API key validity, URL reachability, output quality.

#### FAQ

**How do I validate actor input JSON without running the actor?** Provide the target actor's slug and your input JSON. Input Guard fetches the schema, validates field-by-field, returns a decision record. The target actor is never triggered.

**Does it validate nested objects and arrays?** Yes — recursive nested property validation and `items`-schema array element validation.

**Can it validate private actors?** Yes, if your API token has access.

**How accurate is the validation?** Deterministic against declared schema constraints. Code-enforced constraints not detected.

**What happens if the target actor has no schema?** Returns `schemaFound: false`, `decision: monitor`, `decisionReadiness: insufficient-data`. Code snippets still generated. No PPE charge.

**How do I detect schema drift?** Schedule runs; watch `driftDetected` + `compatibilityImpact`. Alert on `breaking`.

**How is the score computed?** [Published rubric](#scoring-rubric-published--deterministic). Start at 100, subtract per-code penalties, clamp to \[0, 100].

**How much does batch testing cost?** $0.15 per input. 50 inputs = $7.50. Use a spending limit.

**Can I use it in CI/CD?** Yes. Check `decision === "ignore"` for strict CI or `decision !== "act_now"` for permissive.

**Is it safe to call from an AI agent?** Yes — no execution side effects. Branch on `decision`.

***

### Next stage

Input Guard is the **invocation** stage of one developer lifecycle: publish, quality, release, invocation, orchestration, runtime, migration, portfolio. Input Guard validates one actor and one payload; the next stage validates many actors composed into one workflow.

Next stage: [Pipeline Preflight](https://apify.com/ryanclinton/actor-pipeline-builder). Single-actor input safe? Validate that multiple actors compose correctly before you run them.

# Actor input Schema

## `targetActorId` (type: `string`):

Actor ID or username/actor-name to validate input for

## `testInput` (type: `object`):

Single input JSON to validate against the actor's input schema. Use this OR Batch Test Inputs, not both.

## `testInputs` (type: `array`):

Array of labeled inputs to validate in one run. Each item has an optional 'label' and a required 'input' object. Overrides Test Input when provided. Each input is charged separately at $0.15.

## `strictness` (type: `string`):

Controls how decision/readiness react to warnings. lenient = warnings never downgrade a pass; standard (default) = warnings downgrade to monitor; strict = unknown fields and 3+ default-reliance warnings elevate to act\_now (block-like).

## `includeSchemaQualityAudit` (type: `boolean`):

Run a documentation / completeness / agent-readiness audit on the target actor's input schema and attach the findings to every report. Adds zero API calls — purely structural.

## `includeAutoFixSuggestions` (type: `boolean`):

Emit a recommendedFixes\[] array with deterministic remediation for type/enum/unknown-field errors. Safe fixes are coerced automatically into patchedInputPreview; unsafe ones are flagged for review.

## `includePatchedInputPreview` (type: `boolean`):

Attach a patchedInputPreview object showing the test input with high-confidence autofixes applied. Does not mutate the stored input — you decide whether to use it.

## `outputProfile` (type: `string`):

Controls how many fields each record carries. standard (default) = the full record; minimal = decision essentials only (decision, readiness, reason codes, compatibility, score); llm = a plain-language subset for prompting (decision, reason, summary, recommendations, evidence); full = same as standard. Trims the record without forcing a JSONata expression.

## `policyPreset` (type: `string`):

Environment-shaped gate that bundles strictness + drift/warning gating. dev = only hard schema errors block; ci = unknown fields + breaking drift block; production = defaults/drift/unknowns require review or block; agent = only ignore is auto-runnable; scheduled-task = breaking drift blocks, non-breaking warns; custom = use the raw controls below. Explicit strictness / failOnCompatibilityImpact / maxWarningsBeforeBlock always override the preset.

## `maxWarningsBeforeBlock` (type: `integer`):

When set, a valid input with more than this many warnings is elevated to act\_now (block). Leave empty to never block on warning count alone.

## `failOnCompatibilityImpact` (type: `array`):

Schema-drift impact levels that should elevate a valid input to act\_now (block). Allowed values: breaking, non-breaking. Leave unset to inherit the Policy Preset; empty = drift never blocks on its own.

## `compareAgainstSchemaHash` (type: `string`):

Pin a known-good schemaHash. If the target actor's current schema hash differs from this value, the input is blocked (act\_now) with a pinned-hash mismatch reason — ideal for a CI gate that fails when an upstream actor's input contract changes.

## `baselineScope` (type: `string`):

Which baseline the drift diff compares against. targetActor (default) = one shared baseline per target actor; caller = isolated per Apify account; custom = isolated per Baseline Key.

## `baselineKey` (type: `string`):

Custom isolation key for the drift baseline (used when Baseline Scope is 'custom'). Lets one account keep separate per-environment baselines for the same target actor.

## `includeDriftTimeline` (type: `boolean`):

Attach a driftTimeline array of the target schema's hash transitions over previous validated runs (longitudinal drift, not just one-baseline comparison). Reads the shared history store — no extra API calls.

## `includeReliabilityProfile` (type: `boolean`):

Attach actorReliabilityProfile (validationRuns, driftEvents, breakingDrifts, schemaStability, averageScore, lastBreakingDrift) and changeVelocity (schemaChangesLast30Days, breakingChangesLast90Days, stabilityTrend) — contract observability accumulated across runs. Reads the shared history store; null until a prior run exists.

## `includeReplayPackage` (type: `boolean`):

Attach a self-contained replayPackage (actorId, schemaHash, input, validatedAt, replayCurl/Python/Javascript) — a committable record of this exact validated invocation you can re-run months later for debugging or audit.

## `proposedSchema` (type: `object`):

Optional hypothetical input schema ({ properties, required }). When provided, the actor re-validates your test inputs against this proposed schema and returns impactSimulation { wouldBreak, affectedInputs, brokenFields\[], perInput\[], confidence } — answers 'if the target changed its schema to this, would my inputs still validate?'. Scoped to your test inputs only, not downstream pipelines.

## `saveGoldenSuite` (type: `boolean`):

Store this run's test inputs + their verdicts as the golden regression suite for this baseline. Run later with Run Golden Suite to catch payloads that the target's schema changes would break.

## `runGoldenSuite` (type: `boolean`):

Re-validate the stored golden suite against the target actor's CURRENT schema and emit a golden-suite record: { newFailures, fixedInputs, breakingInputs\[] } + consumerImpact { wouldBreakExistingPayloads, affectedStoredInputs, severity }. Answers 'will this actor update break my existing payloads?'.

## `inferSchemaWhenMissing` (type: `boolean`):

When the target actor has no declared input schema, deterministically infer a starter input\_schema.json from the supplied test input and attach it as schemaBootstrap (with a confidence note). Turns a no-charge dead end into an upgrade path for actor developers.

## `emitArtifacts` (type: `boolean`):

Write CI-native report artifacts to the key-value store (REPORT.md, REPORT.json, JUNIT.xml, SARIF.json, GITHUB\_STEP\_SUMMARY.md) so a pipeline can publish the validation result. Off by default — adds KV writes.

## `artifactFormats` (type: `array`):

Which artifact formats to write when Emit CI Artifacts is on. Allowed: markdown, json, junit, sarif, github. Empty = markdown, json, junit, github.

## `webhookUrl` (type: `string`):

Optional URL to POST a compact run-level decision alert to (Slack/Make/Zapier/custom). Fires only when the Webhook Mode condition is met.

## `webhookMode` (type: `string`):

When to fire the decision webhook. none = never; breaking-drift = only on breaking schema drift; act-now = only when the run's worst decision is act\_now; non-ignore = whenever the run's worst decision is monitor or act\_now.

## Actor input object example

```json
{
  "targetActorId": "ryanclinton/fred-economic-data",
  "testInput": {},
  "testInputs": [],
  "includeSchemaQualityAudit": true,
  "includeAutoFixSuggestions": true,
  "includePatchedInputPreview": true,
  "outputProfile": "standard",
  "policyPreset": "custom",
  "baselineScope": "targetActor",
  "includeDriftTimeline": false,
  "includeReliabilityProfile": false,
  "includeReplayPackage": true,
  "proposedSchema": {},
  "saveGoldenSuite": false,
  "runGoldenSuite": false,
  "inferSchemaWhenMissing": true,
  "emitArtifacts": false,
  "artifactFormats": [],
  "webhookMode": "none"
}
```

# Actor output Schema

## `decisions` (type: `string`):

Decision-first view — the routable verdict (ignore / monitor / act\_now) for each validated input.

## `plan` (type: `string`):

Run/block/review recommendation, blocking reasons, production risks, and readiness scorecard per input.

## `remediation` (type: `string`):

Autofix suggestions and the patched-input preview per validated input.

## `scoring` (type: `string`):

Per-record score with the rubric trace that produced it.

## `allItems` (type: `string`):

Every record in the dataset — validation reports and error records.

## `summary` (type: `string`):

Run-level batch totals, decision breakdown, and field hotspots (key-value store SUMMARY record, batch runs only).

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "targetActorId": "ryanclinton/fred-economic-data",
    "testInput": {},
    "testInputs": [],
    "includeSchemaQualityAudit": true,
    "includeAutoFixSuggestions": true,
    "includePatchedInputPreview": true,
    "outputProfile": "standard",
    "policyPreset": "custom",
    "baselineScope": "targetActor",
    "includeDriftTimeline": false,
    "includeReliabilityProfile": false,
    "includeReplayPackage": true,
    "proposedSchema": {},
    "saveGoldenSuite": false,
    "runGoldenSuite": false,
    "inferSchemaWhenMissing": true,
    "emitArtifacts": false,
    "artifactFormats": [],
    "webhookMode": "none"
};

// Run the Actor and wait for it to finish
const run = await client.actor("ryanclinton/actor-input-tester").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "targetActorId": "ryanclinton/fred-economic-data",
    "testInput": {},
    "testInputs": [],
    "includeSchemaQualityAudit": True,
    "includeAutoFixSuggestions": True,
    "includePatchedInputPreview": True,
    "outputProfile": "standard",
    "policyPreset": "custom",
    "baselineScope": "targetActor",
    "includeDriftTimeline": False,
    "includeReliabilityProfile": False,
    "includeReplayPackage": True,
    "proposedSchema": {},
    "saveGoldenSuite": False,
    "runGoldenSuite": False,
    "inferSchemaWhenMissing": True,
    "emitArtifacts": False,
    "artifactFormats": [],
    "webhookMode": "none",
}

# Run the Actor and wait for it to finish
run = client.actor("ryanclinton/actor-input-tester").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "targetActorId": "ryanclinton/fred-economic-data",
  "testInput": {},
  "testInputs": [],
  "includeSchemaQualityAudit": true,
  "includeAutoFixSuggestions": true,
  "includePatchedInputPreview": true,
  "outputProfile": "standard",
  "policyPreset": "custom",
  "baselineScope": "targetActor",
  "includeDriftTimeline": false,
  "includeReliabilityProfile": false,
  "includeReplayPackage": true,
  "proposedSchema": {},
  "saveGoldenSuite": false,
  "runGoldenSuite": false,
  "inferSchemaWhenMissing": true,
  "emitArtifacts": false,
  "artifactFormats": [],
  "webhookMode": "none"
}' |
apify call ryanclinton/actor-input-tester --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,ryanclinton/actor-input-tester"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/2fyUM9KTrb0mloW0J/builds/lEYxc58JMjbmVCsdy/openapi.json
