Fix unasked pleasantries + callback re-asks (live call 2026-07-04 #3)

- PLEASANTRIES: the 8B parroted the verbatim example ("I'm doing well, thank
  you for asking") when the caller never asked how she was, then burned two
  more turns "starting fresh". Rule is now strictly conditional with no canned
  example: answer+ask-back only if the caller literally asks; never answer a
  question that wasn't asked.
- callstate: extraction now captures the CALLBACK request note ("are my
  glasses ready" -> "status of an order"), so the checklist stops the "what's
  the reason for your call?" re-ask; callback wrap-up wording now says STATE
  the caller-ID number, never ask for one (she asked "what's the best phone
  number" despite having it); first-name-only callbacks still ask the last name.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
tocmo0nlord
2026-07-04 03:58:15 +00:00
parent 94e2ca1902
commit 54d707ceac
2 changed files with 22 additions and 9 deletions

View File

@@ -37,9 +37,11 @@ _STATE_INSTRUCTIONS = (
' "call_type": "booking" (wants to schedule a visit), "callback" (wants something staff '
"must check off-phone: order/frames/lens/prescription status, billing, account lookup, "
'reach a person), "question" (just asking something), or "unknown"\n'
' "reason": string or null — for booking, why they want to be seen (visit type or eye '
"problem); for callback, a one-line note of what they need. 'an appointment' alone is NOT "
"a reason — use null.\n"
' "reason": string or null — WHAT the caller wants. For booking: the visit type or eye '
'problem (e.g. "annual exam", "eye pain"). For callback: what they want checked or done, '
'even if phrased as a question (e.g. "are my glasses ready", "status of an order", '
'"billing question"). Only \'an appointment\' with no visit reason is NOT a reason — '
"use null then.\n"
' "location": string or null — the office/city the caller wants\n'
' "patient_name": string or null — the caller\'s name as given (full or first-only)\n'
' "name_is_full": boolean — true only if it clearly has first AND last name\n'
@@ -112,17 +114,27 @@ def build_state_block(state) -> str:
needed.append(label)
if ctype == "callback":
reason = (state.get("reason") or "").strip() if isinstance(state.get("reason"), str) else ""
lines = [
"CALL STATE (auto-tracked from this conversation — trust it over your memory):",
"- This is a NON-BOOKING call: the caller needs staff to handle something off the "
"phone. Do NOT ask about insurance, office, or a preferred day/time.",
]
if reason:
lines.append(f"- Their request (already known — NEVER ask what they're calling "
f"about again): {reason}")
got = [g for g in got if not g.startswith("reason for the visit")] # shown above
if got:
lines.append("- ALREADY COLLECTED — NEVER ask for these again: " + "; ".join(got))
wrap = ("STATE the number on file back to them (it's in CALLER ID above) and invite a "
"correction only — NEVER ask them for a phone number — then say staff will call "
"them back, and close.")
if state.get("patient_name") is None:
lines.append("- Still needed: their name. Then confirm the callback number and close.")
lines.append(f"- Still needed: their name. Then {wrap}")
elif not state.get("name_is_full"):
lines.append(f"- Still needed: their LAST name (you have the first). Then {wrap}")
else:
lines.append("- You have what you need: confirm the callback number and close.")
lines.append(f"- You have what you need: {wrap}")
return "\n".join(lines)
if ctype == "booking" and (got or needed):