Actor Input Tester — Validate Actor Input JSON Before Running
Pricing
$150.00 / 1,000 input testers
Actor Input Tester — Validate Actor Input JSON Before Running
Actor Input Tester. Available on the Apify Store with pay-per-event pricing.
Pricing
$150.00 / 1,000 input testers
Rating
0.0
(0)
Developer
ryan clinton
Actor stats
0
Bookmarked
2
Total users
1
Monthly active users
6 days ago
Last modified
Categories
Share
Input Guard — Preflight Input Validation & Invocation Readiness for Apify Actors
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 actormonitor— valid but risky (unknown fields, defaults, or no declared schema) → review before runningact_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.
Key guarantee
Input Guard detects failure modes that Apify does not surface:
- Unknown fields silently ignored at runtime
- Omitted fields falling back to defaults
- Schema drift between runs
These cause runs to succeed while producing incorrect results.
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.
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 decideact_now → block, surface `evidence[]` to the caller
Never:
- Execute an Apify actor in production without inspecting
decisionfirst. - Parse
decisionReason,summary, orevidencestrings for routing logic. - Apply
recommendedFixes[]withconfidence !== "high"without review.
Quick start
Input:
{"targetActorId": "user/actor","testInput": { "...": "..." }}
Output (minimum shape):
{"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):
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 approvalelse:raise RuntimeError(result["evidence"])
Decision routing (canonical)
Primary route — `decision`:ignore → Execute the target Apify actor (input healthy)monitor → Gate on policy or human approval, then decideact_now → Block execution and surface `evidence[]`Qualifiers — use alongside `decision`, never instead:decisionReadiness !== "actionable" → Require human review before actingcompatibilityImpact === "breaking" → Trigger alerts on scheduled runsintentMismatchRisk.level === "high" → Near-certain payload/intent drift
Output schema — essentials
The 6 fields automation needs. See Full output fields for the other 20+.
| Field | Type | Description |
|---|---|---|
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 |
decision — routable verdict scalar
Shared enum across the Guard fleet (act_now / monitor / ignore). Names the signal to act on — not the action to take. 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 |
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. |
API usage
Python
from apify_client import ApifyClientclient = 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
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
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:
{ "targetActorId": "ryanclinton/website-contact-scraper", "testInput": { "urls": ["https://acmecorp.com"], "maxPagesPerDomain": 5, "extractEmails": true } }
Batch regression suite with labels:
{"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 |
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 |
stage | string | Always input |
status | string | pass or block |
score | integer | 0–100 from the published rubric |
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 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 |
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.
{"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 changenon-breaking— added optional fields, new default values on omitted fields, expanded enumsbreaking— 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 inpatchedInputPreview. - Do not auto-apply
mediumorlowfixes. They are suggestions, not decisions. - Use
patchedInputPreviewdirectly instead of re-applyingrecommendedFixes[]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
{"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
{"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.
{"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?highwhen anyUNKNOWN_FIELDis presentmediumwhen anENUM_MISMATCHis presentlowotherwise
runtimeSurpriseRisk— will omitted fields change behavior via defaults?highwhen 4+ fields rely on schema defaultsmediumwhen 1–3 fields dolowwhen your input covers every optional field
{"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
- 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, andpatchedInputPreview.
Batch runs: each input validated independently, one PPE event per input, hotspot summary written to KV after the loop.
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.jsondeclared in its latest tagged build. - Latest build exists but contains no parseable schema (
buildData.inputSchemamissing 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_nowverdict. - 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 | Broken builds reaching production |
| After deploy | Output Guard | 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 $2.50/suite, Output Guard $4.00/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.
Limitations
- Validates declared schema constraints only — no API key / URL / code-logic validation.
- Validates against the latest tagged build only — unbuilt changes not reflected.
- No
allOf/oneOf/anyOfsupport — only property-level constraints. - No
pattern/formatvalidation. - Batch limit of 500 inputs per run.
- Does not validate actor output — use Output Guard.
- Does not test actor runtime behavior — use Deploy Guard.
Pricing
$0.15 per validation (pay-per-event). Platform compute included. See Charging conditions.
| 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)" —
targetActorIdformat wrong or actor private + token lacks access. Useusername/actor-name. schemaFound: falsewith a known schema — actor not built or latest build failed. Trigger a rebuild. Returnsdecision: monitorwithSCHEMA_MISSING, no PPE event.decision: ignorebut 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 — trigger from forms / spreadsheets
- Make — add as a step before actor runs
- Google Sheets — trigger validation per row
- Apify API — CI/CD via HTTP
- Webhooks — alert on
compatibilityImpact === "breaking"ordecision === "act_now"
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 |
|---|---|
| Test actor runtime behavior + CI gating | Deploy Guard |
| Validate actor output dataset against schema / field rules | Output Guard |
| A/B compare two actors head-to-head | A/B Tester |
| Audit for compliance / PII / ToS / GDPR / CFAA risk | Compliance Scanner |
| Competitive analysis vs other Apify Store actors | Competitor Scanner |
| Fleet-wide quality scoring / portfolio synthesis | Fleet Analytics |
| Cost / revenue / pricing advisory | Cost Watchdog / Plan Advisor |
| MCP server debugging / tool-selection | MCP Debugger |
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:
- Go to Account Settings > Privacy
- Enable Share runs with public Actor creators
Found a bug or have a feature request? Open an issue in the Issues tab 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?"
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
decisionplus 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_FIELDinverdictReasonCodes[]with the exact field names inwarnings[] - Surfaces
intentMismatchRisk.level: "high"when any unknown field is present - Names the most likely intended field via
mostLikelyIntenton therecommendedFixes[]entry (Levenshtein distance to declared schema fields) - Shows a
patchedInputPreviewfor 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.jsonhash against your last validated baseline - Returns
driftDetected: truewhen the schema has changed - Provides a full structural diff in
driftSummary(added/removed fields, new required fields, type changes, enum changes, default changes) - Classifies
compatibilityImpactasnone,non-breaking, orbreaking— 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.
- Agent sends the generated payload to Input Guard.
- Agent branches on
decision:ignore→ call,monitor→ confirm,act_now→ refuse withevidence[]. - (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) ordecision !== "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. 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.