Recovery Method: OpenClaw Session JSONL Files via Fly SSH
Recovery Method: OpenClaw Session JSONL Files via Fly SSH
Why this works
OpenClaw writes every conversation to session JSONL files at /data/agents/main/sessions/ on each bot’s Fly machine. These files persist on the /data volume independently of Discord — deleting a Discord channel does NOT delete the bot’s local session records.
Steps
1. Get the session index
fly ssh console --app mangrove-{botname} -C "cat /data/agents/main/sessions/sessions.json"
This maps channel display names to session IDs. Search for the channel name in displayName or groupChannel fields. Example entry:
"agent:main:discord:channel:1482308244964774120": {
"displayName": "discord:1479164061533863949#scammaster-corleone",
"groupChannel": "#scammaster-corleone",
"sessionId": "47af0e90-2c57-4d55-9227-fa3dc7e38e9b",
"sessionFile": "/data/agents/main/sessions/47af0e90-2c57-4d55-9227-fa3dc7e38e9b.jsonl"
}
2. Pull the session JSONL
fly ssh console --app mangrove-{botname} -C "cat /data/agents/main/sessions/{sessionId}.jsonl" > recovered.jsonl
3. Parse the JSONL
Each line is a JSON record. Records with "type":"message" contain the conversation:
message.role=user(incoming Discord messages) orassistant(bot responses)message.content= text string or array of content blocks withtype: "text"timestamp= ISO 8601 timestamp
Records with "type":"session" are session metadata. Records with "type":"toolResult" are tool call results.
Incorporating into a cron job
Periodically SSH into each bot’s Fly machine, pull sessions.json and all *.jsonl session files, and push them to Firebase RTDB (e.g. at session_backups/{botname}/). This way even if a channel is deleted AND the Fly machine is redeployed/destroyed, the conversation data survives in Firebase.
The data_push.py daemon on the gateway already does a version of this but only captures the latest session — a full backup should capture all session files from every bot machine.
Precedent: #scammaster-corleone (2026-03-15)
- Channel deleted by Corleone; daily Discord scraper (6 AM) missed it; Discord API returned 404
- Successfully recovered full 594KB / 160-record conversation from
mangrove-scammasterFly machine - Also recovered 5 other sessions from that bot (DMs, #protocols, #general, #ejbot-scammaster, #scammaster-corleone-recover)
Discord API limitations (confirmed)
GET /channels/{id}→ 404 for deleted channels- Audit log: deletion metadata only, no message content
- Guild search: doesn’t index deleted channel messages
- GDPR data request: 30+ days, only returns messages authored by requesting account
