whatsapp-backfill — import a WhatsApp export into memory
Load an exported WhatsApp chat into the agent's long-term memory so its contents
become recallable later. The user exports a chat from WhatsApp (Chat → Export
chat → Without media), which produces a .zip; pass that .zip straight to
--file (the skill extracts the _chat.txt inside — no unzip step) or pass a
.txt directly. The skill parses it, groups messages into conversation windows,
and retains them into the memory bank. Afterward the user can just ask the agent
about the conversation.
When to use
- The user wants an existing WhatsApp conversation remembered/queryable: "import
this WhatsApp export", "remember this chat", "load my WhatsApp history".
When NOT to use
- Live/ongoing capture. This imports an exported file; it does not stream new
messages. There's no WhatsApp history API, so a file export is the only source.
- Non-WhatsApp text. For arbitrary notes/files, use the agent's normal memory
directly; this skill is specifically for WhatsApp
Export chat files.
The tool
One script at ${HERMES_SKILL_DIR}/scripts/wa_backfill.py,
invoked as python3 <path> <command> [args]. Each call prints ONE JSON object
({"ok": true, ...}; failures are {"ok": false, "error": "..."} with exit 1).
| Command |
Purpose |
preview --file <export.zip> |
Parse the export (.zip or .txt) and report stats (messages, blocks, date range, what was skipped) plus a sample block. No memory is written. |
import --file <export.zip> [--bank <id>] |
Parse and store the conversation into long-term memory. Returns how many blocks were submitted and the operation ids. |
status --bank <id> [--operation-id <id> …] [--wait] |
Report how many documents/facts are in the bank, and the status of specific import operations. Use this to monitor an import — no external tooling needed. |
clear --bank <id> [--confirm] |
Delete a bank and everything in it. Dry-run without --confirm (just reports the document/fact counts); --bank is required so nothing is wiped by accident. |
Grouping (both preview and import):
--block-days N — preferred. Put one document per N-day window (e.g. 7)
and let the memory layer chunk and date-stamp it itself. Disables the caps below.
--block-messages N (default 10) / --block-gap-hours H (default 6) —
legacy small-block mode; ignored when --block-days is set.
Other options: --chat "<name>" (label; defaults to the filename), --since /
--until YYYY-MM-DD (limit the date range), --alias "Old=New" (rename a
sender; repeatable), --include-system (keep join/left/encryption notices;
default skips them).
Monitoring: add --wait to import to block until extraction finishes and
report the documents/facts landed; or submit without --wait and call status --operation-id <id> --wait later. Progress prints to stderr; the final JSON is
on stdout.
How to run it
- Always
preview first and show the user the stats — message count, date
range, and how many blocks will be stored. This catches a wrong or malformed
file before anything is written.
- Confirm with the user, then run
import (prefer --block-days 7). The
chat's contents go into the agent's memory.
- Monitor the import with
--wait on import, or a follow-up status --operation-id <id> --wait. Report the documents/facts landed and whether
every operation completed. Extraction runs in the background and can take a
while; once it finishes the user can ask about the conversation normally.
Turning the user's words into calls
| User said |
Call |
| "import my WhatsApp export at ~/Downloads/chat.zip" |
preview --file ~/Downloads/chat.zip --block-days 7 → confirm → import --file ~/Downloads/chat.zip --block-days 7 --wait |
| "load this WhatsApp chat with the sailing group" |
preview --file <export.zip> --chat "Sailing Group" --block-days 7 → confirm → import … --wait |
| "remember my chat with Mom, keep the system messages" |
import --file <export.zip> --chat "Mom" --block-days 7 --include-system --wait |
Output shape
preview → {"ok": true, "chat": "...", "messages_parsed": 812, "system_or_media_skipped": 47, "blocks": 34, "date_range": ["2026-01-02T…", "2026-06-30T…"], "unparsed_timestamps": 0, "sample_block": "..."}
import → {"ok": true, "chat": "...", "bank": "David", "messages_parsed": 812, "blocks_submitted": 34, "batches": 4, "operation_ids": [...], "note": "..."}. With --wait, it also includes status_counts, all_completed, and bank_summary ({"documents": N, "facts": N}).
status → {"ok": true, "bank": "...", "bank_summary": {"documents": 1, "facts": 27}, "operation_status": {...}, "status_counts": {"completed": 1}, "all_completed": true}.
After preview, relay the message count, date range, and block count so the user
can confirm it's the right export. After import, tell them it's stored; if you
used --wait (or a follow-up status), relay the documents/facts landed and
whether every operation completed. Otherwise relay the note and offer to
monitor with status.
When a command reports an error
"no messages parsed…" → the file isn't a WhatsApp Export chat (wrong file,
or an unusual locale format). Ask the user to re-export via Chat → Export
chat → Without media.
"no chat .txt inside the zip…" / "not a readable zip" → the .zip isn't a
WhatsApp export. Ask the user for the export .zip (or the _chat.txt).
"Hindsight config not found…" / "no api_url…" → the memory provider isn't
set up. Tell the user to run hermes memory setup and pick their memory backend.
"retain failed…" → the memory server rejected or timed out on the request.
Report it; do not retry in a loop.
Always ask the user for guidance when there is an error; do not proactively try to resolve errors yourself.
Empty results
preview with messages_parsed: 0 means nothing was recognized as WhatsApp
messages — say so plainly and ask for a proper Export chat export.
1---2name: whatsapp-backfill3description: Import a WhatsApp chat export into the agent's long-term memory so you can ask about those conversations later ("what did Dan say about the regatta?"). Takes the WhatsApp "Export chat" .zip (or the _chat.txt inside it), groups the messages into conversation windows, and stores them in the agent's long-term memory, which it recalls from. PREFER THIS SKILL whenever the user wants to load, import, ingest, or remember a WhatsApp conversation/history/export. It handles existing history only (WhatsApp has no live-history API — the user exports the chat from the app). Activate on any of: "import my WhatsApp", "WhatsApp export", "load this chat into memory", "remember this WhatsApp conversation", "backfill WhatsApp", "add my WhatsApp history", "ingest WhatsApp chat".4license: MIT5---67# whatsapp-backfill — import a WhatsApp export into memory89Load an exported WhatsApp chat into the agent's long-term memory so its contents10become recallable later. The user exports a chat from WhatsApp (**Chat → Export11chat → Without media**), which produces a `.zip`; pass that `.zip` straight to12`--file` (the skill extracts the `_chat.txt` inside — no unzip step) or pass a13`.txt` directly. The skill parses it, groups messages into conversation windows,14and retains them into the memory bank. Afterward the user can just ask the agent15about the conversation.1617## When to use1819- The user wants an existing WhatsApp conversation remembered/queryable: "import20 this WhatsApp export", "remember this chat", "load my WhatsApp history".2122## When NOT to use2324- **Live/ongoing capture.** This imports an exported file; it does not stream new25 messages. There's no WhatsApp history API, so a file export is the only source.26- **Non-WhatsApp text.** For arbitrary notes/files, use the agent's normal memory27 directly; this skill is specifically for WhatsApp `Export chat` files.2829## The tool3031One script at `${HERMES_SKILL_DIR}/scripts/wa_backfill.py`,32invoked as `python3 <path> <command> [args]`. Each call prints ONE JSON object33(`{"ok": true, ...}`; failures are `{"ok": false, "error": "..."}` with exit 1).3435| Command | Purpose |36|---|---|37| `preview --file <export.zip>` | Parse the export (`.zip` or `.txt`) and report stats (messages, blocks, date range, what was skipped) plus a sample block. No memory is written. |38| `import --file <export.zip> [--bank <id>]` | Parse and store the conversation into long-term memory. Returns how many blocks were submitted and the operation ids. |39| `status --bank <id> [--operation-id <id> …] [--wait]` | Report how many documents/facts are in the bank, and the status of specific import operations. Use this to monitor an import — no external tooling needed. |40| `clear --bank <id> [--confirm]` | Delete a bank and everything in it. **Dry-run without `--confirm`** (just reports the document/fact counts); `--bank` is required so nothing is wiped by accident. |4142Grouping (both preview and import):43- `--block-days N` — **preferred.** Put one document per N-day window (e.g. 7)44 and let the memory layer chunk and date-stamp it itself. Disables the caps below.45- `--block-messages N` (default 10) / `--block-gap-hours H` (default 6) —46 legacy small-block mode; ignored when `--block-days` is set.4748Other options: `--chat "<name>"` (label; defaults to the filename), `--since` /49`--until YYYY-MM-DD` (limit the date range), `--alias "Old=New"` (rename a50sender; repeatable), `--include-system` (keep join/left/encryption notices;51default skips them).5253Monitoring: add `--wait` to `import` to block until extraction finishes and54report the documents/facts landed; or submit without `--wait` and call `status55--operation-id <id> --wait` later. Progress prints to stderr; the final JSON is56on stdout.5758## How to run it59601. **Always `preview` first** and show the user the stats — message count, date61 range, and how many blocks will be stored. This catches a wrong or malformed62 file before anything is written.632. **Confirm with the user**, then run `import` (prefer `--block-days 7`). The64 chat's contents go into the agent's memory.653. **Monitor the import** with `--wait` on `import`, or a follow-up `status66 --operation-id <id> --wait`. Report the documents/facts landed and whether67 every operation completed. Extraction runs in the background and can take a68 while; once it finishes the user can ask about the conversation normally.6970## Turning the user's words into calls7172| User said | Call |73|---|---|74| "import my WhatsApp export at ~/Downloads/chat.zip" | `preview --file ~/Downloads/chat.zip --block-days 7` → confirm → `import --file ~/Downloads/chat.zip --block-days 7 --wait` |75| "load this WhatsApp chat with the sailing group" | `preview --file <export.zip> --chat "Sailing Group" --block-days 7` → confirm → `import … --wait` |76| "remember my chat with Mom, keep the system messages" | `import --file <export.zip> --chat "Mom" --block-days 7 --include-system --wait` |7778## Output shape7980- `preview` → `{"ok": true, "chat": "...", "messages_parsed": 812, "system_or_media_skipped": 47, "blocks": 34, "date_range": ["2026-01-02T…", "2026-06-30T…"], "unparsed_timestamps": 0, "sample_block": "..."}`81- `import` → `{"ok": true, "chat": "...", "bank": "David", "messages_parsed": 812, "blocks_submitted": 34, "batches": 4, "operation_ids": [...], "note": "..."}`. With `--wait`, it also includes `status_counts`, `all_completed`, and `bank_summary` (`{"documents": N, "facts": N}`).82- `status` → `{"ok": true, "bank": "...", "bank_summary": {"documents": 1, "facts": 27}, "operation_status": {...}, "status_counts": {"completed": 1}, "all_completed": true}`.8384After `preview`, relay the message count, date range, and block count so the user85can confirm it's the right export. After `import`, tell them it's stored; if you86used `--wait` (or a follow-up `status`), relay the documents/facts landed and87whether every operation completed. Otherwise relay the `note` and offer to88monitor with `status`.8990## When a command reports an error9192- `"no messages parsed…"` → the file isn't a WhatsApp `Export chat` (wrong file,93 or an unusual locale format). Ask the user to re-export via **Chat → Export94 chat → Without media**.95- `"no chat .txt inside the zip…"` / `"not a readable zip"` → the `.zip` isn't a96 WhatsApp export. Ask the user for the export `.zip` (or the `_chat.txt`).97- `"Hindsight config not found…"` / `"no api_url…"` → the memory provider isn't98 set up. Tell the user to run `hermes memory setup` and pick their memory backend.99- `"retain failed…"` → the memory server rejected or timed out on the request.100 Report it; do not retry in a loop.101102Always ask the user for guidance when there is an error; do not proactively try to resolve errors yourself.103104## Empty results105106`preview` with `messages_parsed: 0` means nothing was recognized as WhatsApp107messages — say so plainly and ask for a proper `Export chat` export.