Skip to content

feat(apiserver): give the WhatsApp/Email autopilot enough loan context to answer basic questions#68

Merged
psanders merged 1 commit into
mainfrom
feat/autopilot-loan-context
Jul 16, 2026
Merged

feat(apiserver): give the WhatsApp/Email autopilot enough loan context to answer basic questions#68
psanders merged 1 commit into
mainfrom
feat/autopilot-loan-context

Conversation

@psanders

Copy link
Copy Markdown
Member

Summary

Answers a question that came up while testing: does the WhatsApp agent have loan context available to it? Short answer — the data was already loaded, but almost none of it was reaching the model.

  • buildOutreachContext already pulls the full account/loan record (principal, terms, balance, days past due, missed installments, last payment, etc.) into EmailAutopilotRequest.context.
  • But buildPrompt() in both whatsAppAutopilot.ts and emailAutopilot.ts only ever converted two fields into actual prompt text: outstandingBalance, and a customerName key that buildOutreachContext never sets (it's firstName/fullName) — so that line silently never rendered. In practice the model had the balance and nothing else, and couldn't answer "when's it due" / "what are my terms" / "did I miss a payment" even though the answer was sitting in the DB the whole time.
  • New buildAutopilotContextLines (mods/common/src/utils/outreach.ts), shared by both autopilots instead of each hand-rolling its own copy — the customerName/firstName mismatch is exactly the kind of drift duplicating this invites. Surfaces principalAmount, termsAmount/termsFrequency/termsLength, daysPastDue, missedInstallments, lastPaymentDate/lastPaymentAmount, each only when meaningful for the account (e.g. skips "días de atraso" when the account isn't past due).
  • Deliberately excludes negotiationOptions — internal, freeform admin notes on negotiation flexibility (e.g. discount thresholds), not safe for the model to repeat verbatim to a customer. Covered by a regression test asserting it never leaks into the context lines.
  • Added one instruction line telling the model it may use the Contexto to answer basic loan questions and not invent data outside it.

Test plan

  • npm test --workspace=mods/common — 132 passing (128 existing + 4 new, incl. the negotiationOptions exclusion check)
  • npm test --workspace=mods/apiserver — 230 passing (no regressions)
  • npm run typecheck — common + apiserver clean
  • eslint on changed files — clean

🤖 Generated with Claude Code

…t to answer basic questions

The full account/loan record was already loaded into EmailAutopilotRequest.context
(buildOutreachContext pulls every field), but buildPrompt() in both autopilots only
ever forwarded two fields into the actual prompt text: outstandingBalance, and a
customerName key that buildOutreachContext never sets (it's firstName/fullName) —
so that line silently never rendered. In practice the model had the balance and
nothing else: no due date, terms, missed-payment count, or last-payment info, so
it couldn't answer basic loan questions even with that data sitting in the DB.

Added buildAutopilotContextLines (mods/common/src/utils/outreach.ts), shared by
both whatsAppAutopilot.ts and emailAutopilot.ts instead of each hand-rolling its
own two-line context array — the customerName/firstName mismatch is exactly the
kind of drift that duplicating this logic invites. Surfaces principalAmount,
termsAmount/termsFrequency/termsLength, daysPastDue, missedInstallments, and
lastPaymentDate/lastPaymentAmount, each only when meaningful for the account.
Deliberately excludes negotiationOptions (internal, freeform admin notes on
negotiation flexibility) — not safe for the model to repeat verbatim to a
customer. Added a prompt instruction telling the model it may use the Contexto
to answer basic loan questions, and not to invent data outside it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@psanders
psanders merged commit 696136e into main Jul 16, 2026
2 checks passed
@psanders
psanders deleted the feat/autopilot-loan-context branch July 16, 2026 10:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant