LizzyDocs
Docs navigation Rewards

Stage 03 · Rewards

Define and test rewards

Create deterministic, judged, webhook, or feedback rewards, test them on real cases, and select their IDs in the recipe proposal.

Owner and boundary

A reward turns product success into a score that evaluation or reinforcement stages can consume. Lizzy stores the reward definition separately from a recipe so you can test and revise the signal before spending compute. Reward IDs are mode-isolated.

Pilot can create and test non-secret rewards. Webhook secrets are write-only and should be supplied by a human or trusted server. A judge test may call a real model and consume judge tokens; a verifier runs locally and is the clearest diagnostic starting point.

Choose the narrowest signal that matches the job

Deterministic

Verifier

Checks JSON shape, tool choice, arguments, exact text, regex, or boxed answers. Fast and explainable.

Best default
Model-based

Judge

Scores a rubric when quality cannot be reduced to syntax. Review rubric ambiguity and token cost.

Use for semantics
Your scorer

Webhook

Sends candidates to your HTTPS scorer. Treat its signing secret, latency, and availability as production dependencies.

Write-only secret
Observed outcomes

Feedback RM

Uses enough labeled calls to learn from product feedback. Diagnose label balance before trusting it.

Needs production-like labels
json_schema_validValidate output JSON against a supplied schema.
tool_choice_matchRequire the expected tool or sequence of tools.
args_matchCompare structured tool arguments with tolerance or key controls.
exact_matchCompare candidate and reference after configured normalization.
regexSearch or full-match a pattern with optional flags.
boxed_matchCompare boxed mathematical answers.

Create an explainable verifier

This example requires valid JSON with answer and confidence. Persist the returned reward ID, not only its display name. The create call honors an idempotency key.

cURLexample
curl -sS -X POST "https://lizzy.albinilabs.com/v1/distill/rewards" \
  -H "Authorization: Bearer $LIZZY_API_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: reward-valid-ticket-json-v1" \
  --data '{"name":"valid-ticket-json","kind":"verifier","config":{"check":"json_schema_valid","schema":{"type":"object","required":["answer","confidence"],"properties":{"answer":{"type":"string"},"confidence":{"type":"number","minimum":0,"maximum":1}}}}}'
json201 response
{
  "id": "rwd_01K...",
  "object": "distill_reward",
  "name": "valid-ticket-json",
  "kind": "verifier",
  "status": "active",
  "config": {
    "check": "json_schema_valid",
    "schema": {"type": "object", "required": ["answer", "confidence"]}
  },
  "livemode": true
}

Test passing, failing, and malformed candidates

A test accepts exactly one mode: an inline candidate, one capturedcall, or a recent sample count from 1 to 25. Inline mode may also include prompt and reference. Testing a judge can incur token cost; testing a webhook exposes scorer availability errors instead of silently skipping them.

bashpassing case
TEST_BODY=$(jq -nc   --arg candidate '{"answer":"Open Order details before dispatch.","confidence":0.92}'   '{candidate:$candidate}')
curl --fail-with-body -sS -X POST "https://lizzy.albinilabs.com/v1/distill/rewards/rwd_REPLACE_ME/test" \
  -H "Authorization: Bearer $LIZZY_API_TOKEN" \
  -H "Content-Type: application/json" \
  --data "$TEST_BODY"
bashfailing case
curl --fail-with-body -sS -X POST "https://lizzy.albinilabs.com/v1/distill/rewards/rwd_REPLACE_ME/test" \
  -H "Authorization: Bearer $LIZZY_API_TOKEN" \
  -H "Content-Type: application/json" \
  --data '{"candidate":"not json"}'
jsonexample response
{
  "object": "distill_reward_test",
  "reward": "rwd_01K...",
  "results": [
    {
      "call": null,
      "status": "scored",
      "score": 0,
      "explanation": null,
      "detail": {
        "errors": [{"path": "$", "message": "output is not valid JSON"}]
      }
    }
  ],
  "mean_score": 0,
  "duration_ms": 1
}
  1. 1

    Prove the positive case

    A valid answer should score as expected for the intended reason.

  2. 2

    Prove the negative case

    A plausible but wrong answer must fail. A reward that accepts everything cannot guide training.

  3. 3

    Probe malformed and edge cases

    Exercise empty text, unexpected tool calls, schema extras, boundary values, and missing references.

  4. 4

    Inspect score distribution

    If almost every test case gets the same score, revise the signal or the dataset before training.

List reward IDs in every proposal

The three request shapes below have intentionally different meanings:

"rewards":["rwd_..."]Use exactly those reward IDs.
"rewards":[]Request a supervised-only plan with no reward stage.
field omittedCurrent runtime auto-selects up to four active verifier or judge rewards. Avoid this in reproducible integrations.
jsonrecipe proposal fragment
{
  "dataset_version": "dsv_01K...",
  "objective": "quality",
  "max_cost_usd": 25,
  "rewards": ["rwd_01K..."],
  "outcome": "deployable_student"
}

deployable_student asks the proposal to include a publish stage. Areport outcome evaluates but does not guarantee that a student model will be registered for serving.

Diagnose the signal before blaming training

invalid_reward_configCheck kind-specific fields and exact verifier names such as json_schema_valid. Fix the configuration; do not retry unchanged.
reward_disabledRe-enable intentionally or select another reward. A retry cannot change status.
body_expiredThe selected captured call no longer has a body. Use an inline case or another stored call.
reward_webhook_failedInspect your scorer's TLS, status, timeout, and response shape. Reward tests surface this as 502.
Flat scoresThe endpoint succeeded, but the signal carries little ranking information. Review cases and rewrite it.
Unexpected auto-selectionSend the rewards field. Omission is not equivalent to an empty array.
GET/v1/distill/rewards/{reward_id}

Confirm the exact persisted kind, config, status, and mode before comparing test or run behavior.