User Preferences & CV Parsing
Relevant source files
The following files were used as context for generating this wiki page:
The User Preferences and CV Parsing system in Flow is designed to personalize agent interactions by capturing and managing stable user traits, technical stacks, and operational goals. This system automates the ingestion of user data through structured onboarding, continuous conversation analysis, and direct résumé (CV) processing to ensure that every agent run feels tailored to the specific user context.
The system distinguishes between "global" preferences that apply across the workspace and agent-specific facets. These preferences are categorized into distinct classes, such as style and tooling, and follow a lifecycle from initial candidacy to active use based on reinforcement and scoring algorithms.
Sources: services/api/flow/application/preference_service.py:7, apps/web/src/app/(app)/settings/profile/page.tsx:55-60
Preference Taxonomy and Facets
Preferences are organized into "Facets" which define specific dimensions of user interaction. The system currently supports six valid classes for preference categorization.
| Preference Class | Description | Example Values |
|---|---|---|
style | Communication and output formatting preferences. | "Bullet points", "Concise", "French language" |
tooling | Programming languages, frameworks, and software tools used. | "Python", "TypeScript", "FastAPI" |
goal | Active learning objectives or professional milestones. | "Learning Rust", "Build a compiler" |
veto | Explicit anti-patterns or technologies to avoid. | "No legacy PHP", "Avoid verbose explanations" |
domain | The user's primary professional or technical field. | "Software Engineering", "Data Science" |
channel | Communication channels preferred for delivery. | "Email", "Slack" |
Sources: services/api/flow/application/preference_service.py:7-27, apps/web/tests/OnboardingQuestionnaire.test.tsx:117-122
Preference Lifecycle & Scoring
The system employs a dynamic scoring mechanism to manage the reliability of extracted preferences. Preferences are not immediately activated unless they come from high-confidence sources like onboarding. Instead, they often enter a "Candidate" state for user review.
Status Transitions
Preferences progress through the following statuses:
- Candidate: Newly extracted signals pending manual or algorithmic promotion.
- Provisional: Preferences that have begun to prove their stability.
- Active: Verified preferences used by the agent to tailor output.
- Pinned: Preferences explicitly locked by the user to prevent decay.
The logic for "auto-graduation" checks if the effective score meets specific thresholds (0.7 for provisional, 0.9 for active).
Sources: services/api/flow/application/preference_service.py:75-87, services/api/flow/interfaces/http/routes/preferences.py:151-160
Scoring and Decay Logic
Preferences are subject to a decay algorithm to ensure the assistant adapts as user habits change. The effective_score is calculated using a half-life decay model:
- Calculation:
score * (0.5 ** (days_since_last_reinforcement / half_life)) - Pinned Status: If a preference is pinned, it is immune to decay.
Sources: services/api/flow/application/preference_service.py:53-63
CV Parsing and Import Pipeline
Flow allows users to bootstrap their preference profile by uploading a professional résumé. The backend processes the file (PDF or DOCX) through a dual extraction pipeline.
The Import Workflow
- File Upload: The user uploads a file through the
CVDropzonecomponent. - Text Extraction: The system extracts raw text from the binary data.
- Regex Matching: A deterministic pass identifies common tools and languages (e.g., Python, React, AWS) using case-insensitive word-boundary matching.
- LLM Extraction: An LLM analyzes the text to find nuanced signals like career goals, seniority, and industry domains.
- Candidate Staging: Extracted signals are saved to the database with a
candidatestatus for user review.
The regex pass ensures deterministic detection of common technologies, while the LLM pass provides semantic understanding of professional focus.
Sources: services/api/flow/application/preference_service.py:127-185, services/api/flow/interfaces/http/routes/preferences.py:102-123
Onboarding and User Interface
The preference system is integrated into the initial user experience and the core settings interface.
Onboarding Questionnaire
During the first-run walkthrough, users complete a 7-step questionnaire. This process directly populates the workspace with active preferences, bypassing the candidate phase to provide immediate value.
Sources: apps/web/src/app/(app)/onboarding/page.tsx:75-103, apps/web/tests/OnboardingQuestionnaire.test.tsx:28-34
Settings & Candidate Queue
The Profile page serves as the central management hub for preferences. It includes:
- Persona Section: Management of the
SOUL.mdpersona. - CV Import: A specialized dropzone for résumé processing.
- Candidate Queue: A specialized UI for bulk promoting or dismissing preferences extracted from background conversations or CV imports.
- Facet Sections: Grouped views of preferences by class (style, tooling, etc.).
Sources: apps/web/src/app/(app)/settings/profile/page.tsx:78-125
API Endpoints for Preferences
| Method | Endpoint | Description |
|---|---|---|
GET | /api/v1/preferences | Lists global and agent-specific preferences. |
POST | /api/v1/preferences/onboarding | Submits answers from the onboarding flow. |
POST | /api/v1/preferences/import-cv | Uploads and processes a CV for preference staging. |
PATCH | /api/v1/preferences/{id} | Performs actions: promote, pin, unpin, forget, or veto. |
Sources: services/api/flow/interfaces/http/routes/preferences.py:53-150
Implementation Details
Preference Extraction from Conversation
The preference_service includes an LLM-powered function extract_preferences that monitors conversations. It is instructed to only extract clear, stable signals rather than one-off run-specific requests.
Sources: services/api/flow/application/preference_service.py:13-27
Learned Workspace Facts
As documented in the agent configuration, preferences significantly influence output. For example, substantial planning work defaults to a "GSD-style" (Get Stuff Done) phased output, and technical documentation defaults to a specific project root directory context.
Sources: AGENTS.md:1-12
The system ensures that the agent follows these learned facts, such as never mentioning specific internal tools (e.g., Cursor) in Git commits and pushing to the correct GitHub remote (Sekoya88/Flow.git).
Sources: AGENTS.md:13-20