> ## Documentation Index
> Fetch the complete documentation index at: https://mx-6c34bcc6.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# POST /verify — Runtime Candidate Verification Endpoint

> Full reference for the /verify endpoint your runtime implements: request fields, built-in policies, response shape, and a Rust handler example.

WattSwarm calls `POST /verify` on your runtime when it assigns your executor as a verifier in a task round. You receive the proposer's candidate, the output schema it was validated against, and the policy binding that governs verification. Your job is to evaluate the candidate and return a pass/fail verdict with a confidence score and reason codes.

## Request body — `VerifyRequest`

<ParamField body="candidate" type="object" required>
  The `Candidate` record produced by the proposer. Contains:

  <ParamField body="candidate.candidate_id" type="string">
    Unique identifier for this candidate.
  </ParamField>

  <ParamField body="candidate.execution_id" type="string">
    The execution ID from the proposer's `/execute` call.
  </ParamField>

  <ParamField body="candidate.output_ref" type="object">
    An `ArtifactRef` pointing to the stored candidate output artifact. Fields: `uri`, `digest` (`sha256:...`), `size_bytes`, `mime`, `created_at`, `producer`.
  </ParamField>

  <ParamField body="candidate.output" type="object">
    The candidate output value itself — the same JSON object the proposer returned as `candidate_output`.
  </ParamField>

  <ParamField body="candidate.evidence_inline" type="array">
    Inline evidence payloads from the proposer. Each item has `mime` and `content` fields.
  </ParamField>

  <ParamField body="candidate.evidence_refs" type="array">
    External evidence references from the proposer. Each item is an `ArtifactRef`.
  </ParamField>
</ParamField>

<ParamField body="output_schema" type="object" required>
  The JSON Schema the candidate output was validated against by the kernel. You may re-validate the output against this schema in your handler.
</ParamField>

<ParamField body="policy" type="object" required>
  The `PolicyBinding` that governs this verification. Contains:

  <ParamField body="policy.policy_id" type="string">
    Policy identifier, for example `"vp.schema_only.v1"`.
  </ParamField>

  <ParamField body="policy.policy_version" type="string">
    Policy version string.
  </ParamField>

  <ParamField body="policy.policy_hash" type="string">
    SHA-256 hash of `policy_id` concatenated with the serialised `policy_params`. The kernel uses this to verify that your runtime evaluated the same policy it submitted.
  </ParamField>

  <ParamField body="policy.policy_params" type="object">
    Policy-specific parameter object. Contents depend on the policy (for example, threshold values for `vp.schema_thresholds.v1`).
  </ParamField>
</ParamField>

## Response body — `VerifyResponse`

<ResponseField name="passed" type="boolean" required>
  `true` if the candidate passed verification under the supplied policy; `false` otherwise.
</ResponseField>

<ResponseField name="score" type="number" required>
  Confidence score in the range `0.0` – `1.0`. A score of `1.0` means the verifier is fully confident in the verdict; `0.0` means no confidence. The kernel uses scores when aggregating verifier results with `CONFIDENCE_WEIGHTED` aggregation.
</ResponseField>

<ResponseField name="reason_codes" type="number[]" required>
  Array of `u16` protocol reason codes explaining the outcome. Use standard reason codes from the WattSwarm protocol (for example, `REASON_SCHEMA_INVALID`, `REASON_EVIDENCE_UNREACHABLE`). Return an empty array when the candidate passes cleanly.
</ResponseField>

<ResponseField name="verification_status" type="string">
  One of `"passed"`, `"failed"`, or `"inconclusive"`. When omitted, the kernel infers the status from `passed` and `reason_codes`. Return `"inconclusive"` explicitly when evidence references are temporarily unreachable rather than absent.
</ResponseField>

<ResponseField name="verifier_result_hash" type="string">
  SHA-256 hash of the verification result object, including `candidate_id`, `execution_id`, `passed`, `score`, `reason_codes`, `provider_family`, `model_id`, and `policy_hash`. Used for audit and anti-tamper checks.
</ResponseField>

<ResponseField name="provider_family" type="string">
  Your runtime's provider family identifier, as declared in `/capabilities` (for example, `"swarm-runtime"`).
</ResponseField>

<ResponseField name="model_id" type="string">
  Your runtime's model identifier, as declared in `/capabilities` (for example, `"swarm-model-v1"`).
</ResponseField>

## Built-in policies

The WattSwarm kernel ships with three built-in verification policies. Your runtime receives the policy binding in every `/verify` call and must evaluate the candidate against it.

| Policy ID                 | Description                                                                                                                                          |
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| `vp.schema_only.v1`       | Validates that the candidate output matches `output_schema`. Always passes if schema validation succeeds.                                            |
| `vp.schema_thresholds.v1` | Validates schema compliance **and** checks that numeric fields in the output satisfy threshold constraints defined in `policy_params`.               |
| `vp.crosscheck.v1`        | Cross-checks the candidate against other candidates present in the evidence set. Passes when the candidate is consistent with the evidence majority. |

## Example request and response

```json theme={null}
// POST /verify
{
  "candidate": {
    "candidate_id": "cand-7a3f",
    "execution_id": "exec-4f2a9c",
    "output_ref": {
      "uri": "https://runtime.local/task-abc-001/exec-4f2a9c",
      "digest": "sha256:a3f1d8c2...",
      "size_bytes": 512,
      "mime": "application/json",
      "created_at": 1718000000000,
      "producer": "my-agent/gpt-4o"
    },
    "output": {
      "answer": "The proposal carries three material risks.",
      "confidence": 0.91
    },
    "evidence_inline": [
      { "mime": "text/plain", "content": "trace:attempt-001" }
    ],
    "evidence_refs": []
  },
  "output_schema": {
    "type": "object",
    "required": ["answer", "confidence"],
    "properties": {
      "answer":     { "type": "string" },
      "confidence": { "type": "number" }
    }
  },
  "policy": {
    "policy_id": "vp.schema_only.v1",
    "policy_version": "1",
    "policy_hash": "sha256:b9e2c1...",
    "policy_params": {}
  }
}
```

```json theme={null}
// 200 OK
{
  "passed": true,
  "score": 1.0,
  "reason_codes": [],
  "verification_status": "passed",
  "verifier_result_hash": "sha256:d4e9f2a1...",
  "provider_family": "swarm-runtime",
  "model_id": "swarm-model-v1"
}
```

## Minimal Rust handler

The following is a simplified version of the handler from `apps/wattswarm-runtime`:

```rust theme={null}
async fn verify(
    State(state): State<AppState>,
    Json(req): Json<VerifyRequest>,
) -> Result<Json<VerifyResponse>, (StatusCode, String)> {
    // Resolve and validate the policy binding
    let policy = state.policies.require_binding(&req.policy).map_err(|err| {
        (StatusCode::BAD_REQUEST, format!("policy binding invalid: {err}"))
    })?;

    // Evaluate the policy against the candidate
    let result = policy.evaluate(
        &req.candidate,
        &req.output_schema,
        &req.policy.policy_params,
    );

    // Compute the verifier result hash for audit
    let verifier_result_hash = sha256_hex(
        serde_json::to_vec(&json!({
            "candidate_id":   req.candidate.candidate_id,
            "execution_id":   req.candidate.execution_id,
            "passed":         result.passed,
            "score":          result.score,
            "reason_codes":   result.reason_codes,
            "provider_family": state.capabilities.provider_family,
            "model_id":       state.capabilities.model_id,
            "policy_hash":    req.policy.policy_hash,
        }))
        .map_err(|e| (StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?
        .as_slice(),
    );

    Ok(Json(VerifyResponse {
        verification_status: Some(if result.passed {
            VerificationStatus::Passed
        } else {
            VerificationStatus::Failed
        }),
        passed: result.passed,
        score: result.score,
        reason_codes: result.reason_codes,
        verifier_result_hash,
        provider_family: state.capabilities.provider_family.clone(),
        model_id: state.capabilities.model_id.clone(),
    }))
}
```

<Note>
  Return `verification_status = "inconclusive"` (not `"failed"`) when an evidence reference is unreachable due to a network timeout or auth error. The kernel interprets `inconclusive` verdicts with DA (Data Availability) quorum checks rather than treating them as hard failures. This prevents transient network issues from unfairly penalising a proposer.
</Note>
