Kapan Percobaan Ulang Membantu (dan Kapan Tidak)
Sangat baik untuk kesalahan format; tidak berguna untuk data yang hilang.
Kapan Percobaan Ulang Membantu (dan Kapan Tidak) adalah pelajaran Claude Architect gratis di CoddyKit. Ini adalah pelajaran 1 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar Claude Architect, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus Claude Architect mencakup 4 pelajaran total.
Bagian dari pelajaran ini belum diterjemahkan dan ditampilkan dalam bahasa Inggris.
The Retry Reflex
When a model's output fails validation, the tempting move is to just try again. Sometimes that works beautifully. Sometimes it burns tokens and latency for nothing.
As an architect, your job is to know which failure you are looking at before you wire up a retry loop. Retry is a precision tool, not a blanket safety net.
This lesson draws a hard line: retry is excellent for format and structural errors, and useless when the needed information is simply absent from the source.
Two Very Different Failures
Extraction and structured-output pipelines fail in two fundamentally different ways:
- Format / structural / arithmetic errors — the answer exists in the source, but the model rendered it wrong: invalid JSON, a missing required field it actually had data for, a total that doesn't add up.
- Absent information — the source document simply does not contain the value. There is nothing to extract.
Retry-with-feedback can fix the first class. It cannot conjure data that was never there. Confusing the two is a classic anti-pattern.
What Retry-With-Feedback Actually Sends
A good retry is not "run the same prompt again and hope." It is a corrective retry. You send the model three things:
- The original source document
- The wrong output it produced
- The exact validation error that was raised
This gives the model the specific signal it needs to self-correct. Vague feedback like "that was wrong, try harder" performs far worse than handing it the precise validator message.
def retry_with_feedback(client, source_doc, bad_output, validation_error):
return client.messages.create(
model="claude-sonnet-4-5",
max_tokens=1024,
messages=[
{"role": "user", "content": (
"Extract the invoice fields as JSON.\n\n"
f"SOURCE DOCUMENT:\n{source_doc}\n\n"
f"YOUR PREVIOUS OUTPUT (rejected):\n{bad_output}\n\n"
f"VALIDATION ERROR:\n{validation_error}\n\n"
"Fix only what the error names. Return corrected JSON."
)}
],
)Format Errors: Retry's Sweet Spot
Format and structural problems are exactly where retry shines, because the correct answer is recoverable from the same input:
- Malformed JSON or a stray trailing comma
- A field present in the doc but missing from the output
- Wrong enum casing or an unexpected key
- Arithmetic that doesn't reconcile
On the second pass, armed with the validator's message, the model almost always lands the corrected structure. Even better: enforce structure up front with tool_use + a JSON Schema so most syntax errors never happen at all.
Catching Arithmetic With Self-Correction
Arithmetic discrepancies are a format-class error retry can fix — but first you have to detect them. The technique: extract both the value the model computes and the value the document states, then compare.
Pull out calculated_total (sum of line items) AND stated_total (the printed total). If they diverge, you have a concrete, retryable validation error to feed back — not a vague hunch.
from pydantic import BaseModel, model_validator
class Invoice(BaseModel):
line_items: list[float]
calculated_total: float
stated_total: float
@model_validator(mode="after")
def totals_match(self):
if round(self.calculated_total, 2) != round(self.stated_total, 2):
raise ValueError(
f"calculated_total {self.calculated_total} != "
f"stated_total {self.stated_total}"
)
return selfWhere Retry Hits a Wall
Now the hard limit. If a field is not present in the source, retrying does nothing useful. The model has two bad options on each loop:
- Return the same "missing" result — wasted latency and cost.
- Fabricate a plausible-looking value to satisfy the validator — far worse, because now you've injected a hallucination into trusted data.
Retry pressure on absent data actively encourages invention. No amount of re-prompting extracts a value that was never written down.
The Schema Trap: Required Fields
This is where a subtle schema design choice bites. Mark a field required ONLY if it is always present. Never require a field that may be absent — the model will fabricate it to satisfy the schema, and your retry loop will keep accepting garbage.
For optional data, make the field optional and let the model report absence honestly. A retry can't rescue a schema that forces invention.
tax_id_tool = {
"name": "extract_vendor",
"description": "Extract vendor fields from an invoice.",
"input_schema": {
"type": "object",
"properties": {
"vendor_name": {"type": "string"},
# tax_id is OFTEN absent -> optional, never required
"tax_id": {"type": ["string", "null"]},
},
# require ONLY the always-present field
"required": ["vendor_name"],
},
}Make Absence a First-Class Result
The fix for absent data is not retry — it is letting the model say so explicitly. Distinguish a genuine access/format failure (maybe retryable) from a valid empty result (no value exists — stop, don't loop).
Use an enum with an "other"/"not_present" value plus a free-text detail field. That keeps the schema extensible and gives downstream code a clean signal to skip the field instead of triggering a doomed retry.
{
"properties": {
"discount_status": {
"type": "string",
"enum": ["applied", "none", "not_present", "other"]
},
"discount_detail": { "type": "string" }
},
"required": ["discount_status"]
}Route by Error Type, Not by Reflex
Mature pipelines branch on why validation failed. Structured errors enable this; generic ones ("Operation failed") block it.
- validation / format / arithmetic mismatch → retry-with-feedback.
- transient (timeout, rate limit) → retry locally, the value still exists.
- absent data / valid empty result → record "not present" and move on. Do NOT retry.
This mirrors structured MCP errors: an errorCategory and an isRetryable flag let your loop make an intelligent routing decision instead of blindly looping.
def handle(result):
if result.error_category in ("validation", "arithmetic"):
return "retry_with_feedback" # answer is recoverable
if result.error_category == "transient" and result.is_retryable:
return "retry_local" # network/rate-limit blip
if result.error_category == "absent":
return "record_not_present" # NEVER retry absent data
return "escalate"Cap the Loop, But Don't Lean on the Cap
Even for genuinely retryable format errors, bound the loop. A retry budget of 2–3 attempts is plenty — if a corrective retry hasn't converged by then, the problem usually isn't format; it's missing data or an over-strict schema.
Treat the cap as a safety net, never the primary stop mechanism. The real terminator is "validation passed." If you find yourself relying on the cap to exit, that's a signal you're retrying something retry can't fix.
def extract(client, doc, validate, max_attempts=3):
out = first_pass(client, doc)
for _ in range(max_attempts):
try:
return validate(out) # PRIMARY stop: it's valid
except ValidationError as e:
out = retry_with_feedback(client, doc, out, str(e))
# SAFETY NET only -- not the intended exit path
raise RuntimeError("unresolved after retries; likely absent data")When Even a Good Retry Won't Save You
Two more honest limits an architect must respect:
- A fresh, independent reviewer beats same-session self-review. An author retains its own reasoning and won't challenge itself — so for a true second opinion, validate with a fresh instance, not another turn of the same context.
- Blocking, time-sensitive checks belong inline. The Batch API is 50% cheaper but has no latency SLA and a window up to 24h — great for overnight audits, wrong for a pre-merge or real-time validation gate.
Retry tuning can't compensate for the wrong validation architecture underneath it.
Quick Check: Retry or Not?
A structured-extraction pipeline pulls fields from supplier invoices. The Pydantic validator rejects an output because the tax_id field is empty. On inspection, this particular invoice has no tax ID printed anywhere on it. What is the correct architecture?
Recap: Retry Is a Scalpel, Not a Hammer
Key takeaways:
- Retry fixes format, structural, and arithmetic errors — send the original doc + the wrong output + the exact validation error.
- Retry can't fix absent data. If it's not in the source, looping only wastes cost and invites fabrication.
- Never require a possibly-absent field — make it optional and let the model report "not present."
- Route by error type: validation/arithmetic → retry-with-feedback; transient → retry locally; absent → record and stop.
- Cap attempts (2–3) as a safety net; the primary stop is "validation passed."
- For true second opinions use a fresh instance; keep blocking checks inline, not on the Batch API.
Belajar Python dengan tutor AI — gratis
Tulis dan jalankan kode asli di browser kamu, dapatkan bantuan instan dari tutor AI 24/7, dan lanjutkan di mana kamu tinggalkan di web atau aplikasi.
- Kursus
- 26
- Pelajaran
- 104
Pertanyaan yang Sering Diajukan
Apakah pelajaran “Kapan Percobaan Ulang Membantu (dan Kapan Tidak)” gratis?
Ya — teks lengkap “Kapan Percobaan Ulang Membantu (dan Kapan Tidak)” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus Claude Architect, upgrade ke CoddyKit PRO. Kursus Claude Architect mencakup 4 pelajaran total.
Apa yang akan aku pelajari di “Kapan Percobaan Ulang Membantu (dan Kapan Tidak)”?
Sangat baik untuk kesalahan format; tidak berguna untuk data yang hilang. Kamu berlatih Claude Architect dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.
Apakah aku perlu pengalaman untuk memulai Claude Architect?
Tidak diperlukan pengalaman sebelumnya. Claude Architect di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 1 dari 4.
Berapa lama pelajaran “Kapan Percobaan Ulang Membantu (dan Kapan Tidak)” memakan waktu?
Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.
Bisakah aku menulis dan menjalankan kode dalam pelajaran Claude Architect ini?
Ya. Setiap pelajaran Claude Architect menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.
Semua pelajaran dalam kursus ini
- Kapan Percobaan Ulang Membantu (dan Kapan Tidak)
- Perintah Percobaan Ulang dengan Umpan Balik
- Koreksi Mandiri
- Lintasan Ganda dan Peninjauan Independen