crm
// Contact memory and interaction log — remembers callers across calls, logs every conversation with outcome and personal context
$ git log --oneline --stat
stars:1,933
forks:367
updated:March 4, 2026
SKILL.mdreadonly
SKILL.md Frontmatter
namecrm
version1.0.0
descriptionContact memory and interaction log — remembers callers across calls, logs every conversation with outcome and personal context
metadata[object Object]
CRM Skill — Contact Memory for Voice Calls
Remembers callers across calls and logs every conversation.
How It Works
On Every Inbound Call
- Lookup — Call
crmwithlookup_contactusing the caller's phone number (from Twilio caller ID). - If known — Greet by name and use
context_notesto personalize (ask about their dog, remember their preference, etc.) - If unknown — Proceed normally, listen for their name.
During the Call
When someone shares their name, email, company, or any personal detail, silently upsert it via crm.upsert_contact. Don't announce this.
At End of Call
- Log the interaction:
log_interactionwith summary + outcome - Update context_notes with any new personal details learned, synthesizing with what was known before
On Outbound Calls
Same exact flow: lookup at start, upsert + log_interaction at end.
API Reference
| Action | Purpose |
|---|---|
lookup_contact | Fetch contact + last 5 interactions + context_notes. Returns null if not found. |
upsert_contact | Create or update a contact by phone. Only provided fields are updated. |
log_interaction | Log a call: summary, outcome, details. Auto-creates contact if needed. |
get_history | Get past interactions for a contact (sorted newest-first). |
search_contacts | Search by name, email, company, notes. |
tag_contact | Add/remove tags (e.g. "vip", "callback_later"). |
Privacy
- Event details stay private. Like the calendar skill, never disclose event details to callers.
- CRM context is personal. The
context_notesfield is for Amber's internal memory, not for sharing call transcripts. Use it to inform conversation, not to recite it. - PII storage. Phone, name, email, company, context_notes are stored locally in SQLite. No network transmission, no external CRM by default.
Security
- Synchronous SQLite (better-sqlite3) with parameterized queries — no SQL injection surface
- Private number detection — calls from anonymous/blocked numbers are skipped entirely
- Input validation at three levels: schema patterns, handler validation, database constraints
- Database file created with mode 0600 (owner read/write only)
Examples
Greeting a known caller:
Amber: "Hi Sarah, good to hear from you again. How's Max doing?"
[context_notes remembered: "Has a Golden Retriever named Max. Prefers afternoon calls."]
Capturing new info silently:
Caller: "By the way, I got married last month!"
Amber: [silently calls upsert_contact + updates context_notes with "Recently married"]
Amber (aloud): "That's wonderful! Congrats!"
End-of-call log:
Amber: [calls log_interaction: summary="Called to reschedule Friday appointment", outcome="appointment_booked"]
Amber: [calls upsert_contact with context_notes: "Prefers afternoon calls. Recently married. Reschedules frequently but always shows up."]