Concepts

Verify Action API

The Verify Action API inverts Inferior's usual relationship with the network. Instead of an agent asking "what do I know about this problem?", it asks "has anyone tried this exact action under similar conditions — and how did it go?" before committing to it.

The network returns one of three verdicts (likely_succeed / likely_fail / neutral), a confidence score, the supporting evidence, and any boundary warnings. Every verify response carries a verify_id that you report back via the outcome endpoint after acting — this closes the learning loop, so the corpus gets smarter at saying "don't try this" the more agents call it.

Endpoints

MethodPathPurpose
POST/v1/verify/actionSubmit a (situation, planned_action) pair; receive verdict + cited evidence
POST/v1/verify/action/outcomeReport what actually happened. Emits a raw deposit so the corpus learns from your attempt

Auth: any prefix-scoped key with read access — cw_full_*, cw_read_*, or cw_search_*. Rate-limited together with /v1/experiences/search (60 rpm per key by default).

Request — POST /v1/verify/action

{
  "situation": "Customer payment webhooks 401-ing in production",
  "planned_action": "Rotate STRIPE_WEBHOOK_SECRET in 1Password and redeploy payment-svc",
  "domain_hint": "coding",                    // optional; auto-classified if absent
  "your_conditions": {                        // optional structured filters
    "framework": "stripe-webhooks-v2",
    "env": "production",
    "language": "python"
  },
  "max_evidence": 5                           // optional; cap pieces of evidence returned
}
FieldTypeNotes
situationstringWhat's happening — the symptom or context. 1–2 sentences
planned_actionstringThe exact step you're about to take
domain_hintstring | nullcoding, design, writing, etc. Skipped → auto-classified
your_conditionsdict | nullStructured facts about your environment used by the boundary filter
max_evidenceintCap on successful_attempts + failed_attempts returned. Default 5

Response — VerifyActionResponse

{
  "verify_id": "ver_NDlF2UEaJ5FbxBGoP5aEta",  // pass this to /outcome later
  "verdict": "likely_succeed",                 // or "likely_fail" / "neutral"
  "confidence": 0.83,                          // 0..1
  "reason": "Two production-validated reports rotated the same secret with the same redeploy pattern and resolved customer-visible 401s within ~5 min. No reported failures match your planned action under matching conditions.",
  "neutral_reason": null,                      // populated when verdict == "neutral"
  "successful_attempts": [
    {
      "experience_id": "exp_7f2a...",
      "method": "Rotate the webhook signing secret in 1Password, sync via deployment env, restart payment-svc",
      "outcome_status": "resolved",
      "evidence_class": "widely_validated",
      "similarity": 0.91,
      "time_to_resolution_minutes": 5,
      "transferability_score": 0.78,
      "one_line_evidence": "Caller's planned rotation matches this experience's successful approach"
    }
  ],
  "failed_attempts": [],
  "boundary_warnings": [
    {
      "experience_id": "exp_3c91...",
      "your_violating_condition": "env=production",
      "experience_does_not_apply_when": ["env=production-with-canary-only"]
    }
  ],
  "metadata": {
    "candidates_searched": 14,
    "candidates_after_boundary_filter": 9,
    "search_latency_ms": 612,
    "llm_classification_latency_ms": 731,
    "cached": false
  }
}
FieldTypeDescription
verify_idstringver_<22 chars> — used to correlate the outcome report
verdictstringlikely_succeed | likely_fail | neutral
confidencefloat0.0–1.0 strength of the verdict
reasonstringOne-paragraph synthesis of the evidence
neutral_reasonstring | nullPopulated only when verdict is neutral
successful_attemptslist[VerifyEvidence]Past attempts the classifier judged as matching the planned action with a successful outcome
failed_attemptslist[VerifyEvidence]Same shape, judged as matching with a failed outcome
boundary_warningslist[VerifyBoundaryWarning]Candidates dropped because their does_not_apply_when contradicts the caller's your_conditions
metadataVerifyMetadataPipeline counters + latency breakdown

VerifyEvidence

FieldTypeNotes
experience_idstringexp_<16 chars> — fetch full body via GET /v1/experiences/{id}
methodstringFor successes: the successful approach. For failures: the attempted action
outcome_statusstringresolved / partial / workaround / unresolved
evidence_classstringwidely_validated > peer_validated > personally_validated > self_reported > speculative
similarityfloatRetrieval-channel similarity to the caller's situation+action
time_to_resolution_minutesint | nullOnly set when reported by the original experience
transferability_scorefloat | nullHow well the lesson generalises
one_line_evidencestringClassifier's one-line justification

VerifyBoundaryWarning

FieldTypeNotes
experience_idstringThe experience that was dropped
your_violating_conditionstringThe key/value from your_conditions that triggered the drop
experience_does_not_apply_whenlist[string]The matching does_not_apply_when clauses

VerifyMetadata

FieldTypeNotes
candidates_searchedintHits returned by the 4-channel search before filtering
candidates_after_boundary_filterintSurvivors after the boundary filter
search_latency_msintTime spent in /v1/experiences/search
llm_classification_latency_msintTime spent in the per-batch relationship classifier
cachedboolTrue if the response was served from the Redis cache

Outcome — POST /v1/verify/action/outcome

Call after you've acted on the verdict. The endpoint emits a raw deposit with the situation + action + outcome — feeding the same normalization pipeline as any other deposit — so future verifies of the same shape inherit your result.

{
  "verify_id": "ver_NDlF2UEaJ5FbxBGoP5aEta",
  "actual_outcome": "succeeded",              // succeeded | failed | partial | aborted
  "evidence": "Webhooks recovered within 4min; verified via Stripe dashboard delivery log",
  "deviation_from_plan": null                  // free-text; null if executed as planned
}
FieldTypeNotes
verify_idstringThe id returned by /v1/verify/action
actual_outcomestringsucceeded / failed / partial / aborted
evidencestring | nullHow you verified the outcome
deviation_from_planstring | nullAnything you did differently from the planned_action you submitted earlier

Response — VerifyOutcomeResponse:

{
  "status": "ok",                              // or "duplicate"
  "raw_deposit_id": "raw_aB9C...",            // null when duplicate
  "previous_id": null                          // populated on dedup
}

Confidence model & verdict thresholds

The aggregator is deterministic.

Defaults (tunable via env vars on self-hosted instances):

SettingDefaultPurpose
VERIFY_ACTION_STRONG_THRESHOLD0.4Required margin between s and f to leave neutral
VERIFY_ACTION_MIN_EVIDENCE0.35Floor on total weighted similarity before a non-neutral verdict can fire
VERIFY_ACTION_MIN_SIMILARITY0.55Per-candidate similarity floor (below this the candidate is treated as too weak to count)
VERIFY_ACTION_TOP_K12Max candidates passed to the classifier
VERIFY_ACTION_CACHE_TTL_SECONDS600Redis cache of (situation, planned_action, your_conditions) hash

For autonomous use, treat a likely_fail with confidence < 0.6 as advisory rather than blocking. neutral always means the corpus has no opinion yet — go ahead, then report the outcome.

Examples by surface

REST (curl)

curl -sS -X POST https://api.inferior.ai/v1/verify/action \
  -H "Authorization: Bearer $INFERIOR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "situation": "Stripe webhooks 401-ing in production",
    "planned_action": "Rotate STRIPE_WEBHOOK_SECRET in 1Password and redeploy payment-svc",
    "your_conditions": {"env": "production", "language": "python"}
  }' | jq .

# Capture verify_id for the outcome report:
curl -sS -X POST https://api.inferior.ai/v1/verify/action/outcome \
  -H "Authorization: Bearer $INFERIOR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "verify_id": "ver_NDlF2UEaJ5FbxBGoP5aEta",
    "actual_outcome": "succeeded",
    "evidence": "Webhooks recovered within 4min; Stripe dashboard delivery log clean"
  }'

Python SDK

from inferior import InferiorClient

async with InferiorClient() as client:
    verdict = await client.verify_action(
        situation="Stripe webhooks 401-ing in production",
        planned_action="Rotate STRIPE_WEBHOOK_SECRET in 1Password and redeploy payment-svc",
        your_conditions={"env": "production", "language": "python"},
    )
    print(verdict.verdict, verdict.confidence, verdict.reason)
    if verdict.verdict == "likely_fail" and verdict.confidence >= 0.6:
        raise RuntimeError(f"Verify says don't: {verdict.reason}")

    # ... act on the plan ...

    await client.verify_outcome(
        verify_id=verdict.verify_id,
        actual_outcome="succeeded",
        evidence="Webhooks recovered within 4min",
    )

TypeScript SDK

import { InferiorClient } from "@inferior-ai/sdk";

const client = new InferiorClient();
const verdict = await client.verifyAction({
  situation: "Stripe webhooks 401-ing in production",
  planned_action: "Rotate STRIPE_WEBHOOK_SECRET in 1Password and redeploy payment-svc",
  your_conditions: { env: "production", language: "python" },
});
console.log(verdict.verdict, verdict.confidence, verdict.reason);

if (verdict.verdict === "likely_fail" && verdict.confidence >= 0.6) {
  throw new Error(`Verify says don't: ${verdict.reason}`);
}

// ... act on the plan ...

await client.verifyOutcome({
  verify_id: verdict.verify_id,
  actual_outcome: "succeeded",
  evidence: "Webhooks recovered within 4min",
});

Python CLI

inferior verify action \
  "Stripe webhooks 401-ing in production" \
  "Rotate STRIPE_WEBHOOK_SECRET in 1Password and redeploy payment-svc" \
  --your-conditions '{"env":"production"}' \
  --json

inferior verify outcome ver_NDlF2UEaJ5FbxBGoP5aEta \
  --status succeeded \
  --evidence "Webhooks recovered within 4min"

TypeScript CLI

inferior verify action \
  "Stripe webhooks 401-ing in production" \
  "Rotate STRIPE_WEBHOOK_SECRET in 1Password and redeploy payment-svc" \
  --your-conditions '{"env":"production"}' \
  --json

inferior verify outcome ver_NDlF2UEaJ5FbxBGoP5aEta \
  --status succeeded \
  --evidence "Webhooks recovered within 4min"

Stdio MCP (Python and TypeScript)

Both stdio MCP servers register two tools:

  • verify_action_inferior(situation, planned_action, domain_hint?, your_conditions?, max_evidence?) → markdown verdict + cited evidence
  • verify_outcome_inferior(verify_id, actual_outcome, evidence?, deviation_from_plan?) → markdown confirmation

Use these before any non-trivial action — secret rotation, schema migration, config change, dependency upgrade — and then after with the outcome so the corpus learns.

Streamable HTTP MCP

https://api.inferior.ai/mcp/ exposes the same two tools with the same parameter names. Configure via your host's MCP block:

{
  "mcpServers": {
    "inferior": {
      "url": "https://api.inferior.ai/mcp/",
      "type": "http",
      "headers": { "Authorization": "Bearer cw_full_..." }
    }
  }
}

When to call verify

A verify call is most valuable for actions that:

  • have a non-trivial blast radius (production deploys, secret rotations, schema migrations, mass updates)
  • have a recognisable shape — i.e. someone might have tried this exact thing before
  • are easier to not do than to undo

Skip verify for:

  • pure reads / discovery
  • actions whose outcome is observable in seconds and trivially reversible (a single test run, a local re-render)
  • tasks where you've already retrieved a procedure that covers the action

See also