AI agents

Synthetic Tasks: Generating Cases You Have No Logs For

Antonio Evans9 min read

A workbench covered with two piles of index cards.
Key points

Key points

  1. 1Synthetic tasks are generated evaluation examples you write to cover intents and behaviors your logs do not supply enough of.
  2. 2Each gap gets a task spec stating the intent, the context, the expected behavior and at least one hard constraint.
  3. 3Generated candidates pass four filters (rules, real-log pattern checks, human review on a sample, and a score comparison against a held-out real set) before they join the golden set.
  4. 4Synthetic items never replace real ones in the headline score; they sit in a clearly labeled synthetic segment that is reported separately.

Why long tails break your golden set first

A golden dataset is a curated set of examples with human-validated labels that you use as ground truth to measure a model, not to train it Innodata. Its job is to catch drifting accuracy and inconsistent outputs early, which only works if the set actually contains the cases that break DAC.digital. Guidance on dataset curation is explicit that you should include diverse real-world inputs, varying complexity and edge cases, precisely because that is what challenges the system DeepEval.

The problem is arithmetic. Rare intents and high-frustration interactions are, by definition, rare. If 0.3 percent of sessions are someone demanding a refund in anger after three failed attempts, a 500-example golden set sampled from production will hold one or two such cases, and one or two cases cannot distinguish a prompt change from noise. Typical sizing advice puts simple applications at 10 to 20 examples and more intricate ones at 100 to 200 diverse examples, which does not leave room for slicing out a long tail Innodata.

There is a second trap: observability pipelines sample and filter logs to control cost and ingestion load, so the tail can be systematically under-collected before it ever reaches your dataset, not just undersized after sampling groundcover. The logs you have are not a neutral census of user behavior.

Synthetic tasks exist to fix coverage. They do not fix realism, and the whole discipline of this article is about keeping the two apart.

Step 1: Mine production traffic for underrepresented slices

Before generating anything, produce a short list of slices with counts. Pull traces over a fixed window, tag each session with your intent classifier or a human-assigned label, and count. Then sort by two numbers: volume and coverage in the golden set.

Intent or sliceSessions in windowGolden-set itemsDecision
Cancel subscription (calm)4,12038Leave alone
Cancel subscription after failed payment2603Needs synthetic coverage
Angry refund demand, 3+ turns1801Needs synthetic coverage
Data export request (GDPR)400Needs coverage, check policy
Agent escalation request6109Borderline, add 10 to 15

The decision rule: if a slice has fewer than roughly 20 items in the golden set, you cannot compute a per-slice score with any confidence, so it needs synthetic items. If it already has 20 to 40, prefer real items, because real logs carry the mess you cannot invent.

Two practical notes. First, for agentic systems, count steps and tool calls, not just final answers, because a single request can trigger dozens of internal decisions and the interesting failure lives in the middle of the trajectory LangChain. Second, include an "angry customer" slice even if your classifier does not have it: sentiment is often a separate signal from intent, and frustration is exactly where policy compliance and tone both get tested at once MLflow.

Step 2: Write a task spec per gap

A spec is the difference between a synthetic task and a synthetic sentence. It is a small structured record, not free text, because downstream rule filters need fields to check. Write one per gap, and keep it under 15 lines.

{
  "spec_id": "refund-angry-003",
  "intent": "cancel_subscription",
  "sub_intent": "refund_after_failed_payment",
  "context": {
    "customer_tenure_months": 14,
    "payment_failures_in_30d": 2,
    "prior_agent_turns": 3,
    "sentiment": "angry",
    "channel": "chat"
  },
  "expected_behavior": "Acknowledge frustration, confirm the two failed charges, offer refund of the last charge only, state the refund timeline, offer a human handoff.",
  "hard_constraints": [
    "must not promise a refund beyond 30 days",
    "must not blame the payment provider by name",
    "must include a human handoff offer"
  ],
  "must_not": ["apologize more than twice", "ask the user to repeat account details"],
  "difficulty": "medium",
  "source_pattern_ref": "trace_id:8f3a21c"
}

The expected_behavior field is your definition of success. Google's agent evaluation guidance makes the point that vague goals like "the agent should be helpful" lead nowhere, while a specific measurable statement of success converts directly into metrics Google Cloud. A spec per gap forces you to write that statement before you see any generated text, which stops you from rationalizing whatever the model produces.

Keep source_pattern_ref pointing at at least one real trace that resembles the gap. You are not copying it; you are anchoring the spec to something that actually happened, which is what makes the later real-log pattern check meaningful.

Step 3: Generate candidates

Generate 5 to 10 candidates per spec, not one. Diversity within a spec is what stops you from trading one kind of overfitting for another, and it gives the filters something to reject.

Practical settings that matter more than the model choice:

  • Temperature around 0.8 to 1.0 for candidate variety. You want the model reaching for different phrasings of anger, not the same sentence five ways.
  • A generation prompt that receives the spec as data and is told to vary phrasing, length, typos, lowercase, and slang while preserving every hard constraint.
  • Batch by spec rather than by intent, so each call has one behavior to satisfy.
  • Log the generation prompt version with every candidate. When a filter starts rejecting 60 percent of output, you need to know which prompt produced it.

If you are generating and evaluating across several model families, running them behind one key removes a whole class of plumbing work; Quanta Inference puts text, image, video, audio and embedding models behind a single OpenAI-compatible endpoint (https://quantaintelligence.ai/inference).

One caution on multi-turn candidates. If the spec involves a conversation, generate turns rather than a single message, and store them as a scenario plus expected outcome, the way conversational goldens are defined, so that evaluation can simulate the dialogue rather than match one string DeepEval.

Step 4: Verify before anything counts

Verification is the part people skip, and skipping it is how synthetic tasks corrupt scores. Four checks, in this order, each cheaper than the next.

CheckCost per itemCatchesCannot catch
Rule filters (code, regex, schema)Near zeroPlaceholders, leaked spec language, banned phrases, broken JSON, wrong lengthUnrealistic tone, wrong policy
Real-log pattern checksLowVocabulary drift, impossible context, lengths and sentiment outside observed rangesSubtle policy errors
Human review on a sampleHighEverything the first two miss, including unverifiable commitmentsRare reviewer disagreement
Score comparison on held-out real setMediumBias that inflates or deflates the trained system's scoreIndividual bad items

Rule filters first. Deterministic checks belong in code, not in a model: valid schema, no leftover template tokens, the hard constraints present as substrings or regexes, sentence length within the range you observe in real traffic. Google's framework calls code-based evaluations the cheapest and most deterministic layer and recommends them for exactly this kind of checkable failure Google Cloud. Expect this step alone to reject a meaningful share of raw candidates, mostly for missing a constraint clause.

Then real-log pattern checks. This is the step that separates synthetic tasks you can trust from synthetic tasks that read like a language model wrote them. Compare each surviving candidate against the distribution of the real slice it is meant to represent: average message length, punctuation habits, presence of filler words, how often the customer mentions an order number, how often anger shows up as profanity versus clipped sentences versus threats to leave. If your fake angry customers all write complete grammatical sentences with an exclamation mark, and your real ones write three words in lowercase, the model will learn nothing useful and the slice score will be meaningless. A simple check: embed candidates and real items, and flag any candidate whose nearest real neighbor is farther away than the 95th percentile real-to-real distance.

Then human review on a sample. Sample 20 to 30 verified candidates per slice and have a domain expert label them as realistic or not, and as correctly specified or not. This is where you find the subtle killer: a candidate that satisfies your stated policy but makes a commitment your business would never honor. LLM judges agree with human reviewers about 85 percent of the time, which is good for monitoring at scale, but that also means roughly one in seven judgments disagrees with a careful human, so a judge alone is not a sufficient gate for admitting new golden items Confident AI. Use the judge to triage volume and humans to settle the boundary.

Then the score comparison. This is the decisive test and it is the one most teams never run. Take your held-out real set (real items, never used in tuning, never touched by generation). Score your system twice: once on real-only items, once on a combined set that includes the new synthetic items. If the combined score moves by more than a couple of points in either direction, your synthetic items are not neutral replacements for the real slice. They are easier, or harder, or they encode the generation model's stylistic biases. Investigate before admitting them.

A worked example with numbers makes the risk concrete. Say your real-only golden set scores 0.82 on your correctness judge. After adding 120 synthetic items for angry refunds, the combined set scores 0.61. That 21-point drop is not new information about your system; your system did not change. It is a measurement artifact: the synthetic angry cases, generated from complete specs with explicit hard constraints, are systematically harder than the real angry cases in your logs, which were often vague and quickly resolved. Admitting them into the headline score would make every future release look like a regression.

Keep synthetic and real scores separate

The operational rule: never blend. Report the headline score on real items only, and report synthetic segments as their own rows with the count visible. When a synthetic segment and a real segment disagree, that disagreement is the finding.

Keep an explicit quarantine: if an item later gets a real-log twin, prefer the real item and retire the synthetic one. Track provenance on every golden so that a future reviewer can see where each item came from and which generation prompt version produced it. Without provenance, a synthetic set degrades into an unattributable pile within a few quarters, and nobody can tell which items were ever reviewed.

For agents specifically, add trajectory-level checks to the advisory sample: did the agent pick the right tool at the right step, and did it reach a correct answer through a defensible path. A correct final answer can hide broken reasoning, and that hidden failure is invisible to output-only scoring LangChain. An agent-as-a-judge setup, where the evaluator can inspect intermediate steps rather than only the final message, is the natural fit when your synthetic tasks describe multi-step behavior arXiv.

Calibrate judges on the same items

Synthetic tasks and LLM judges have the same failure mode: both are generated by a model and both can drift away from your domain. The defense is the same too. Build the judge against a benchmark set you have annotated by hand, measure the judge against that ground truth, and iterate the judge prompt until it clears your threshold DeepEval. MLflow's guidance is that judges should be aligned with human feedback so automated scores stay calibrated to your team's standards MLflow, and Evidently's guide covers the prompt and scoring choices that keep a judge from drifting, including chain-of-thought and reference-based scoring Evidently AI.

Calibrating a judge on synthetic angry-customer items is circular: the judge and the items share a generator's biases. Calibrate on your reviewed sample, which contains both real and verified synthetic items, and report agreement separately for each group. If the judge agrees with humans on 90 percent of real items and 70 percent of synthetic ones, either the judge or the synthetic set is wrong, and that gap is worth a week of work.

One more calibration habit: hold the judge to a stated threshold before you use it to admit items. A judge that agrees with humans on only three of four boundary cases is fine for monitoring trends and not fine for signing off on new golden items, so keep a fixed review backlog of disagreements and revisit it when the judge prompt changes Google Cloud.

For teams running evaluation across many model providers, a single endpoint for both the system under test and the judge reduces the chance that the judge's provider bias leaks into the score (https://quantaintelligence.ai/inference).

FAQ

FAQ

How many synthetic tasks should a golden set contain?

Keep synthetic items a minority of the total and never let any single slice be synthetic-only if real items exist. A practical target is enough synthetic items to bring each underserved slice to about 20 to 30 items, with at least a third of that slice drawn from real logs. Report slice scores separately so the ratio is always visible to whoever reads the numbers.

Do synthetic tasks leak into model training?

They can, and that is the main way they corrupt measurement. Treat the synthetic set as evaluation data with the same access controls as your real held-out set, and never let it into fine-tuning or prompt-optimization loops. If your pipeline pulls "all goldens" as few-shot examples for a judge or a prompt, exclude synthetic items by the provenance field.

Can an LLM judge replace human review of generated tasks?

No, and the numbers say why. LLM judges reach roughly 85 percent agreement with human reviewers, so a judge will admit or reject a meaningful share of items a careful human would decide differently Confident AI. Use the judge to triage volume, and reserve humans for the boundary cases and for the sampled audit that keeps the judge honest.

What does an angry-customer task spec look like in practice?

It states the sentiment and its cause, the prior turns, and the exact behaviors that must appear, plus the ones that must not. The important part is negative constraints: what the agent must never promise, must never blame, and how many times it may apologize. Without those, generated angry cases test tone only and never test policy compliance, which is where real failures cluster.

When should I stop generating and go collect real data instead?

Stop when your real-log pattern check starts rejecting most candidates, which usually means your generator does not know your domain well enough to fake it. At that point, the honest move is targeted collection: instrument the rare path, add a feedback widget, or have support agents flag these sessions. Synthetic tasks are a bridge over a gap, not a substitute for traffic you can go and capture.

When the gap is in how you evaluate agents and models rather than in the data itself, a specialist can pick up the design and hand back a working harness; that is what Quanta does (https://quantaintelligence.ai/).

Sources

Sources

  1. What are Golden Datasets? LLM & AI Evaluation Guide - Innodata
  2. What Is a Golden Dataset in AI and Why Does It Matter?
  3. Datasets | DeepEval - The LLM Evaluation Framework
  4. Log Sampling: Techniques, Challenges & Best Practices
  5. LLM Evaluation Framework: Trajectories vs. Outputs - LangChain
  6. LLM-as-a-Judge Evaluation for LLMs & Agents - MLflow
  7. A methodical approach to agent evaluation | Google Cloud Blog
  8. LLM-as-a-Judge Simply Explained: The Complete Guide ... - Confident AI
  9. The Rise of Agent-as-a-Judge Evaluation for LLMs - arXiv
  10. LLM-as-a-judge: a complete guide to using LLMs for evaluations
About the author

About the author

Antonio Evans
Antonio Evans

Antonio Evans is the founder of Quanta Intelligence and a fractional CTO who builds HIPAA-ready AI systems for health and life-science companies. Before that he was technical co-founder of FriendsEAT for twenty years, CEO of Socialdraft, and a data engineer at IBM. Antonio lives with his dog Santino in Lisbon, Portugal.

All articles