feat: isolate inbound media storage per agent - #194
Conversation
…ent storage isolation
|
Thanks for raising the per-agent media-isolation problem. Preventing one agent from observing another agent's inbound files is important, and we would welcome an author-led port or redesign in the current community repository: https://github.com/NewFuture/openclaw-weixin For the current architecture, the PR should preserve sender authorization and routing order, use a channel-consistent and sanitized media subdirectory, confirm the OpenClaw media-store contract, and keep previously stored media accessible. Please also add regression coverage for multiple agents, rejected senders, unresolved routes, legacy paths, and account isolation rather than relying only on the existing suite. Contribution guide: For transparency, |
Problem
All inbound media files (images, videos, files, voice) from WeChat users are saved to a single flat directory (
~/.openclaw/media/inbound/). When multiple agents are configured, files from different agents are mixed together with no way to tell which agent received which file.Motivation
I maintain an internal OpenClaw deployment for my company's IT department. Recently, many colleagues have started using OpenClaw with WeChat, and we encountered a critical issue:
I first tried to mitigate this via AGENTS.md rules, but that's fundamentally impossible — agents cannot be instructed to read from different folders when all files are co-located in a single flat directory.
After debugging, I identified the root cause in the WeChat plugin. I also examined the DingTalk plugin, which already implements per-agent media isolation. This PR gives the WeChat plugin similar per-agent separation to what DingTalk already has.
This fix would directly improve our production setup at work, and I believe many other multi-agent users would benefit as well.
Why this approach
The plugin uses OpenClaw's
channelRuntime.media.saveMediaBufferto persist inbound media. This SDK method manages the media store internally and does not expose the agent's workspace path — we cannot tell it to save directly to~/.openclaw/agents/<id>/workspace.The
saveMediaBufferAPI does accept asubdirparameter for organizing files within its media store. By resolving the agent route early and passingwecom/<agentId>/inboundas the subdirectory, we achieve per-agent file isolation with minimal code change — no SDK modification, no path traversal, no custom file copy logic.Changes
src/messaging/process-message.ts: MoveresolveAgentRoutebefore the media download step (it only depends oncfg,accountId, andfrom_user_id, all available before download). ConstructmediaSubdirfrom the resolvedagentIdand pass it todownloadMediaFromItem.src/media/media-download.ts: Accept an optionalsubdirparameter (defaults to"inbound"for backward compatibility). Use it instead of thehardcoded
"inbound"in allsaveMediacalls.Before
~/.openclaw/media/inbound/.png
After
~/.openclaw/media/wecom/agentId/inbound/.png
Notes
agentIdcannot be resolved, falls back to the original"inbound"directory.Test Results
state-dir.test.ts>resolveStateDir> falls back to ~/.openclaw\vs/)sync-buf.test.ts>getSyncBufFilePath> returns path under accounts diraccount-index.test.ts>listIndexedWeixinAccountIds> returns empty array when file does not existaccount-store.test.ts>loadWeixinAccount> returns null when no account file existspairing.test.ts>resolveFrameworkAllowFromPath> returns correct pathpairing.test.ts>registerUserInFrameworkStore> uses withFileLockAll failures are in
src/auth/andsrc/storage/test files — none touchsrc/messaging/orsrc/media/where this change was made.