career/qwestly/2026-10-briefing-interview-memories.md
Table of Contents
Made what members say in the briefing reach chat (deal-breakers, goals, story)
Situation
After the onboarding briefing, chat told members it had nothing on file about their deal-breakers or what excites them, though they had just given both. The pitch used them, so members saw the product contradict itself. The cause was systemic: the memory extractor ran once per conversation, so in the briefing only the first interview turn ever became memory. Everything after it (career story, strengths, networking targets, next role, deal-breakers) never reached chat.
What I did
- Investigated with the local prod copy: showed the agent reported its tools accurately and that the answers lived only in the briefing's progress tracker, which chat can't read. Quantified the gap across all briefings (below).
- Chose to extract the briefing in windows (one per closed service area plus completion) over exposing the tracker's facts to chat, which would have created a stale second copy.
- Built it with a cursor, a token-held lease, pay kept out of memories, and the chat-ingestion tool no longer silencing the extractor; routed the beacon/admin extraction through the same windows (it used to re-read whole briefings and could write pay as a memory).
- Wrote a backfill for past briefings; ran three independent review passes; validated with evals, the ticket's exact chat question, and before/after on the QA accounts.
- Added
scripts/find-member-fact.shto the workspace so "where did this fact go" takes one command. - PR: https://github.com/Qwestly/qwestly-agent/pull/481 ยท Ticket: https://app.asana.com/0/0/1219203102588930/f
Result
Pending: ships with qwestly-agent#481, then the production backfill. Locally, the QA account went from "I don't have explicit deal-breakers on file" to listing all four deal-breakers and what excites them.
Metrics
| Metric | Baseline (2026-10-08, local prod copy) | Target | Latest (date) |
|---|---|---|---|
| Completed briefings whose interview was extracted past its first turn | 4 of 44 had more than one extraction batch (36 one batch, 4 none) | all new briefings, past ones via backfill | |
| Members with a deal-breakers answer who have a memory resembling it | 9 of 29 | 29 of 29 after backfill | |
| Backfill scope (local copy) | 39 completed briefings due, 587 member turns | 0 due after apply |
How to measure
- Batches per briefing: for each
onboarding_statewithphase/stepcompleted, count distinctcreated_atamonguser_memorieswith thatsource_conversation_idandsource_type != "explicit". - Deal-breakers coverage: members with
progress.service_areas.finds_opportunities.assessment.dealbreakersvs those with auser_memoriesrow matching/deal.?breaker|won.?t|avoid|not interested|never/i. - Backfill scope:
qwestly-agent/scripts/backfill_briefing_memories.py(dry run) under the shared env. - Run against a fresh prod copy (restore-prod-db skill) for production numbers.
Log
- 2026-10-08: baseline taken on the local prod copy; fix built and validated; PR #481 opened.