Memory
Employee Profiles
Employee profiles are the persistent memory layer. They give the assistant user-specific context across conversations.
Model
The EmployeeProfile model stores extracted information about each user:
| Field | Type | Description |
|---|---|---|
summary | String | LLM-extracted bio / role description |
currentProjects | String[] | Active projects the employee works on |
preferences | JSON | Communication preferences |
frequentIntents | String[] | Commonly used intents |
accessLevel | String | Authorization tier (e.g., "standard", "elevated") |
metadata | JSON | Custom key-value data |
profileVersion | Int | Incremented on each extraction |
lastExtractedAt | DateTime | Timestamp of last extraction |
One profile per user (one-to-one relationship with User).
How Profiles Are Used
The profile is injected into the LLM context during RAG generation:
- Summary — grounds the assistant in the employee's role.
- Current projects — enables project-aware answers.
- Preferences — shapes response style.
The profile is added to the system prompt before the user's query, which is what gives the assistant memory across conversations.
API
List Profiles
GET /api/v1/employee-profiles
Auth: users see profiles inside their effective department scope; global users may filter by departmentId.
Get Profile
GET /api/v1/employees/:userId/profile
Auth: own profile or a profile inside the caller's effective department scope.
Update Profile
PATCH /api/v1/employees/:userId/profile
Body: any profile fields.
Auth: users may update their own profile; canManageEmployeeProfiles is required to update other profiles inside the caller's effective department scope.
Automatic Extraction
The Memory Extraction Worker updates profiles after every N messages (set by MEMORY_EXTRACT_EVERY_N_MESSAGES).
Manual Updates
Users with canManageEmployeeProfiles can edit profiles via the API — useful for seeding initial context or correcting extracted data.
Extraction Worker
The extraction worker analyzes conversations and updates employee profiles with extracted facts.
Implementation
src/knowledge/memory-extractor.ts — processMemoryExtractionJob()
Trigger
Every N messages in a conversation (MEMORY_EXTRACT_EVERY_N_MESSAGES, default 10), a BullMQ job is enqueued to memory-extraction.
Pipeline
- Load profile — fetch the existing
EmployeeProfile, create if missing. - Fetch messages — pull messages since
lastExtractedAt. - Format conversation — build a
"user: ...\nassistant: ..."transcript. - LLM extraction — call
gpt-4o-mini(orMEMORY_EXTRACTION_MODEL) with:Extract JSON with fields: summary, currentProjects, preferences, frequentIntents, metadata.
Only include fields with new information. - Parse response — extract JSON from the LLM output.
- Merge with the existing profile:
- arrays are de-duplicated (union);
- objects are shallow-merged;
- strings are replaced.
- Save — update the profile, increment
profileVersion, setlastExtractedAt.
Queue Configuration
| Setting | Value |
|---|---|
| Queue name | memory-extraction |
| Concurrency | 1 |
| Max retries | 3 |
| Backoff | Exponential |
| Worker shutdown | Graceful (SIGTERM) |
Configuration
| Variable | Default | Description |
|---|---|---|
MEMORY_EXTRACT_EVERY_N_MESSAGES | 10 | Messages between extractions |
MEMORY_EXTRACTION_MODEL | gpt-4o-mini | LLM model for extraction |