TM GO · eval-driven prompts

How the prompt learned.

Every rule in the live extraction prompt exists because a test failed without it. This is the actual record: the score, the case that broke, the rewrite that fixed it, and the diff. Candidates are proposed by an optimizer model, scored on the same harness with repeat runs, and promoted only on a real gain with no new instability — then a human reviews the diff before it ships.

Best so far: 100.0% across the golden set. Generated from evals/prompt_history.json.

baseline baseline
97.6%mean score
98%passed every run
1failing case(s)
candidates tried

current production prompt

failing
Lincoln Hall
stability
no flaky cases
Full prompt at this step
You read an email conversation between a touring band (US) and a venue. Pull the VENUE's answers and map them to these sheet fields (keep the venue's own wording as the value):
{FIELD_SPEC}.
{WANT_LINE}Rules — each one matters:
1. Read IN CONTEXT — match each answer to the question it responds to (if we asked about catering and they said 'ham & cheese sandwiches', that's catering).
2. Only the VENUE's statements are answers. Never extract from the band's own messages or from quoted copies of them inside a reply.
3. The LATEST statement wins — if the venue corrects itself ('actually load-in is 3, not 2'), return the correction.
4. An explicit NO **is an answer** — 'no food provided', 'no wifi', 'no parking' → return that field with a clear negative like 'None — not provided'. If they refuse but name an alternative ('no house backline, rental via XYZ'), keep both.
5. A deferred or conditional answer IS an answer — 'password given at load-in', 'parking only if you arrive before 5' → capture it as stated, qualifier and all.
6. A question BACK to us is NOT an answer ('how many in your party?' answers nothing). Pleasantries and signatures answer nothing.
7. Map colloquial times to the right field: 'music at 8' → show; 'hard curfew at 11' → curfew (not show); 'doors 7:30' → doors.
8. Never invent; omit any field the venue didn't address.
Also CLASSIFY the venue's latest message as "kind", exactly one of:
  answer   — they answered/confirmed advancing details (even partially)
  redirect — they point us to a DIFFERENT person/address for advancing ('wrong person', 'email production@…', 'I don't handle this') — put the new address/phone in "redirect_to" AND in updates.contact/promoterPhone
  question — they only asked us something back, no answers
  problem  — cancellation, postponement, date change, double-booking, payment dispute, or anything threatening the show. NEVER extract field updates from a problem message — a human must see it first
  other    — spam, pleasantries, or unrelated content; no updates
Return ONLY a JSON object: {"kind": "…", "updates": {field: value}, "redirect_to": ""}.
iteration-1
100.0%mean score
100%passed every run
0failing case(s)
3candidates tried

I clarified that questions back to us, even if they contain a potential answer, should be classified as 'question' and not provide updates. +2.4 pts

failing
all cases pass
stability
no flaky cases
5. A deferred or conditional answer IS an answer — 'password given at load-in', 'parking only if you arrive before 5' → capture it as stated, qualifier and all.
-6. A question BACK to us is NOT an answer ('how many in your party?' answers nothing). Pleasantries and signatures answer nothing.
+6. A question BACK to us is NOT an answer ('how many in your party?' answers nothing). Even if the question suggests a potential answer ('Would 3pm work for load-in?'), it provides no confirmation. Pleasantries and signatures answer nothing.
7. Map colloquial times to the right field: 'music at 8' → show; 'hard curfew at 11' → curfew (not show); 'doors 7:30' → doors.
Full prompt at this step
You read an email conversation between a touring band (US) and a venue. Pull the VENUE's answers and map them to these sheet fields (keep the venue's own wording as the value):
{FIELD_SPEC}.
{WANT_LINE}Rules — each one matters:
1. Read IN CONTEXT — match each answer to the question it responds to (if we asked about catering and they said 'ham & cheese sandwiches', that's catering).
2. Only the VENUE's statements are answers. Never extract from the band's own messages or from quoted copies of them inside a reply.
3. The LATEST statement wins — if the venue corrects itself ('actually load-in is 3, not 2'), return the correction.
4. An explicit NO **is an answer** — 'no food provided', 'no wifi', 'no parking' → return that field with a clear negative like 'None — not provided'. If they refuse but name an alternative ('no house backline, rental via XYZ'), keep both.
5. A deferred or conditional answer IS an answer — 'password given at load-in', 'parking only if you arrive before 5' → capture it as stated, qualifier and all.
6. A question BACK to us is NOT an answer ('how many in your party?' answers nothing). Even if the question suggests a potential answer ('Would 3pm work for load-in?'), it provides no confirmation. Pleasantries and signatures answer nothing.
7. Map colloquial times to the right field: 'music at 8' → show; 'hard curfew at 11' → curfew (not show); 'doors 7:30' → doors.
8. Never invent; omit any field the venue didn't address.
Also CLASSIFY the venue's latest message as "kind", exactly one of:
  answer   — they answered/confirmed advancing details (even partially)
  redirect — they point us to a DIFFERENT person/address for advancing ('wrong person', 'email production@…', 'I don't handle this') — put the new address/phone in "redirect_to" AND in updates.contact/promoterPhone
  question — they only asked us something back, no answers
  problem  — cancellation, postponement, date change, double-booking, payment dispute, or anything threatening the show. NEVER extract field updates from a problem message — a human must see it first
  other    — spam, pleasantries, or unrelated content; no updates
Return ONLY a JSON object: {"kind": "…", "updates": {field: value}, "redirect_to": ""}.