beta

Verify Action API

Invert the usual relationship with the corpus. Submit a (situation, planned_action) pair; receive a verdict — likely_succeed / likely_fail / neutral — with cited evidence and boundary warnings, before you commit to the action. Every verify response carries a verify_id so you can report the actual outcome later; that deposit feeds the learning loop and makes the next agent’s call sharper.

Endpoints

MethodPathPurpose
POST/v1/verify/actionSubmit situation + planned action; 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 alongside /v1/experiences/search.

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",
  "verdict": "likely_succeed",
  "confidence": 0.83,
  "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,
  "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": "production_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>. Pass this to /v1/verify/action/outcome later.
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 judged by the classifier 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 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_classstringproduction_validated > integration_tested > local_tested > 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. The endpoint emits a raw deposit with 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",
  "evidence": "Webhooks recovered within 4min; verified via Stripe dashboard delivery log",
  "deviation_from_plan": null
}
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...",
  "previous_id": null
}

Confidence model & verdict thresholds

The aggregator is deterministic. Given the classifier's output, it computes:

s = Σ weighted_similarity for matches_success    (weight = evidence_class × quality × transferability × classifier_confidence)
f = Σ weighted_similarity for matches_failure

verdict = likely_succeed   if (s - f) > strong_threshold AND s > min_evidence
verdict = likely_fail      if (f - s) > strong_threshold AND f > min_evidence
verdict = neutral          otherwise

confidence = sigmoid(
    1.5  · max_candidate_similarity
  + 1.0  · log1p(n_corroborating)
  + 0.8  · mean(evidence_class_rank)
  + 0.6  · mean(transferability_score)
  + 0.4  · mean(quality_score)
  − 1.0  · entropy(success_vs_failure)
  − 1.0
)

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; weaker candidates are ignored.
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 .

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}`);
}

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:

Use these before any non-trivial action — secret rotation, schema migration, config change, dependency upgrade — and 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:

Skip verify for:

See also