5 Safety Guards for Auto-Archiving Another AI Agent's Conversations into My Vault: Designing a Manus API Bridge A developer built a Python bridge that polls the Manus API every five minutes and archives each task's messages into a shared knowledge vault's raw layer alongside Claude Code conversation logs. The script, run via launchd, uses five safety guards including reading its API key from the macOS Keychain on every run and tracking per-task revision timestamps in a state file to skip unchanged tasks. It only fetches and saves raw sources, leaving summarization to a separate reflection worker. My Claude Code conversations were already saved to my knowledge vault automatically, but anything I gave to Manus stayed inside its browser UI. I couldn't search those tasks or find them later. Now a small Python bridge checks the Manus API every 5 minutes and saves each task to the same shelf as my Claude Code logs. It uses five safety guards to keep it quiet, self-healing and free of secrets. Last time, I wrote about how a weekly batch job in my skills CLI had been failing silently https://zenn.dev/bokuwalily/articles/skills-cli-weekly-silent-fail . This post continues with the same vault setup. It covers how I automatically collect conversations from an AI agent other than Claude Code Manus through its API and store them as primary sources in a shared vault . The vault has a location called raw/conversations/ , and Claude Code conversation logs pile up there automatically. Tasks I sent to Manus were different. The only way to see their contents was to open the task screen in the browser. When I later tried to remember what I had asked for in a task, it didn't show up in vault search or in the shared hot cache. Manus has a public API that lets you read your own task list and messages. That was the starting point for this bridge: fetch those tasks on a schedule and put them on the same shelf the raw layer as the Claude Code conversation logs. launchd runs ~/Documents/claude-obsidian/bin/manus-task-archive.py every 5 minutes, and the script writes its output to ~/Documents/my-knowledge-base/raw/manus-conversations/ . Note This script only fetches and saves . A separate, safe reflection worker handles summaries and "proposals to the vault." This script never does that work. A core rule of how I run the vault is to keep raw primary sources separate from the layer that interprets them. I don't want the API key in the code or in any file, so the script reads it from the macOS Keychain on every run. php KEYCHAIN SERVICE = "manus-vault-memory-archiver" def keychain key - str: result = subprocess.run "security", "find-generic-password", "-s", KEYCHAIN SERVICE, "-w" , text=True, capture output=True, check=False, if result.returncode = 0 or not result.stdout.strip : raise RuntimeError "Manus archive API key is unavailable in macOS Keychain" return result.stdout.strip The docstring also states that this worker never passes the key to print or write . If the key can't be fetched, the function raises an exception. The except in main logs it and the run stops. A broken key doesn't affect other jobs or conversations. The script fetches Manus tasks by paging through task.list → task.listMessages . Fetching every message on every run would be wasteful. Instead, the script saves each task's update time as its "revision" in a state file and skips the task if that value hasn't changed. php def task revision task: dict str, Any - str: for key in "updated at", "updatedAt", "modified at", "timestamp", "created at", "createdAt" : if task.get key not in None, "" : return str task key return "unknown" for task in accessible: ident = task id task if not ident: continue revision = task revision task if state "tasks" .get ident == revision: continue messages = list messages credential, ident archive task task, messages state "tasks" ident = revision Here is the actual state file AI/.runtime/manus-task-archive-state.json : { "tasks": { "rRkPkzEkUrImaYRXsI3sLY": "1790174319", "7hBaAc4dhs9hycZaAnC8z5": "1789628528", "5VXpxPKZkzify3yp9FA5LX": "1790077323" }, "accessible task count": 3 } The launchd log ~/.claude/logs/manus-task-archive.log shows that even though the job runs every 5 minutes, most runs find nothing new: 2026-09-26 07:43:32 +0900 ok: accessible=3 updated=0 2026-09-26 07:48:33 +0900 ok: accessible=3 updated=0 2026-09-26 07:53:34 +0900 ok: accessible=3 updated=0 2026-09-26 07:58:51 +0900 ok: accessible=3 updated=0 A run of accessible=3 updated=0 lines means the API returns 3 tasks each time, but none of their revisions changed, so nothing gets written. Of all my measurements, this was the clearest proof that the diff check works correctly. The launchd StartInterval is fixed at 300 seconds 5 minutes , set in ~/Library/LaunchAgents/com.shun.manus-vault-archive.plist .