feat(apiserver): give the WhatsApp/Email autopilot enough loan context to answer basic questions#68
Merged
Merged
Conversation
…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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.
buildOutreachContextalready pulls the full account/loan record (principal, terms, balance, days past due, missed installments, last payment, etc.) intoEmailAutopilotRequest.context.buildPrompt()in bothwhatsAppAutopilot.tsandemailAutopilot.tsonly ever converted two fields into actual prompt text:outstandingBalance, and acustomerNamekey thatbuildOutreachContextnever sets (it'sfirstName/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.buildAutopilotContextLines(mods/common/src/utils/outreach.ts), shared by both autopilots instead of each hand-rolling its own copy — thecustomerName/firstNamemismatch is exactly the kind of drift duplicating this invites. SurfacesprincipalAmount,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).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.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 cleaneslinton changed files — clean🤖 Generated with Claude Code