Skip to main content
The verifier runs server-side after a human submits, before the task lands in COMPLETED. It does two things in one LLM call:
  1. Quality check — was the response acceptable per your instructions?
  2. NL parsing (optional) — if the human replied in free text (Slack thread, email body), extract structured data into the response schema.
If the verifier rejects, the task goes to REJECTED (non-terminal), the reason is shown to the reviewer, and they get to retry. After max_attempts, it’s VERIFICATION_EXHAUSTED (terminal) and the agent gets a typed error.

BYOK — bring your own key

The verifier LLM call runs server-side, not in your agent process. That has two consequences worth internalizing before you wire anything up:
  1. Your provider API key must live on the awaithumans server’s environment, not the agent’s. The agent process never sees the key, never sends it over the wire, and doesn’t need it installed.
  2. Your LLM provider bills you directly. awaithumans has no inference layer of its own — every verifier call goes from your server to Anthropic / OpenAI / Google / Azure, on your account, at provider list price. There’s no markup and no proxy.
Each provider needs two things on the server: the SDK extra installed, and the API key exported as an env var. Override the env var name with api_key_env= if you’d rather not use the default — e.g. claude_verifier(api_key_env="ACME_CLAUDE_KEY").
Forget this step and the first verifier call returns HTTP 500 VERIFIER_API_KEY_MISSING with a docs link to the troubleshooting page. Set the key, restart the server, the failed task can be resubmitted by the human — the verifier didn’t burn an attempt.

Quickstart

If the human submits with empty notes on a 1500refund,theverifierrejectswiththereason"Amountover1500 refund, the verifier rejects with the reason "Amount over 1000 requires notes.” The dashboard shows the reason; the reviewer fills the field and resubmits. Note that claude_verifier(...) doesn’t take an API key — it just declares the config. The agent ships that config to the server, and the server reads ANTHROPIC_API_KEY from its own env.

Other providers

All four return a VerifierConfig you pass to await_human(verifier=...).

NL parsing

When the human replies in free text (Slack thread reply, email body), the verifier extracts structured data into the response schema. No code changes — the server detects raw text vs. structured form, runs the verifier in NL-parsing mode. Operator’s instructions should anticipate the cases:
A reviewer can now reply to the Slack DM with “approve, looks legit” and the verifier turns that into {approved: true, notes: "looks legit"}.

redact_payload

If the task’s redact_payload=True, the verifier is skipped entirely. The operator marked the payload sensitive; we don’t ship it to a third-party LLM regardless of verifier config.
The task still works — the human reviews via dashboard, submits, the response is stored. Just no AI verification.

Error handling

Provider failures (vendor outage, missing API key, network blip) propagate as typed errors WITHOUT consuming a max_attempts slot. The human gets a fresh shot once the operator fixes config:
Each error has a docs URL the dashboard renders for the operator.

Best practices

  • Keep instructions narrow. “Reject if X” / “Require Y when Z” — not “be a good reviewer.” Narrow rules are easier to debug when the verifier rejects something you didn’t expect.
  • Set max_attempts low. Default is 3. For high-stakes decisions, lower (1) so a single rejection fails closed rather than letting the human grind through retries.
  • Test the prompt. Run a few representative submissions through it before relying on the verifier in production. The dashboard’s audit trail records every verifier verdict so you can inspect them.

Cost

The verifier fires on every submission. At ~1k input tokens + ~100 output per call:
  • Claude Sonnet: ~$0.005 / call
  • GPT-4o: ~$0.01 / call
  • Gemini 2.0 Flash: ~$0.0005 / call
For most workloads this is negligible. For very high-volume queues, consider gemini-2.0-flash.

Runnable examples

Both run against a real Claude verifier — drop in your ANTHROPIC_API_KEY, python refund.py (or npx tsx), and walk the dashboard through each path. A useful template for fixture-driven tests of your own verifier prompts.

Where to next

  • Testing — patterns for testing verifier paths in CI
  • Idempotency — what happens to in-flight tasks across verifier retries
  • Troubleshooting — every verifier error code with the matching fix