The decision was in memory. The contract was in Slack.
Empirical memories can now carry the files they are about. Twenty per memory, 25MB each, and deleting one is reversible for thirty days with the purge date printed on the receipt. Here is what it does, and the two places it deliberately stops.
Here is a shape I kept running into.
A decision gets made. The reasoning behind it lands in Empirical, because that is the part I want an agent to recall in three months. Then the artifact that proves it, the signed PDF, the screenshot of the broken state, the export someone sent me, goes somewhere else. A Slack thread. A Drive folder. A download directory I will never open again.
Six weeks later the memory recalls perfectly and the artifact is gone. Not deleted, just unfindable, which is the same thing.
Memories can hold their files now.

What it actually does
Twenty files per memory, 25MB each. Attach from wherever you already are:
empirical memory attach --memory-id <id> --file ./contract.pdf
empirical memory attachments --memory-id <id> --format tableThe portal has the same thing on any memory, and a connected agent can list, delete and restore files through its own tools. One implementation, three doors, which matters more than it sounds like: the reason to put a file here rather than in Drive is that the thing recalling the memory can also reach the file.
The part I spent the most time on
Deleting.
A delete that actually destroys the bytes is a feature nobody can use confidently. You hesitate over every file, because being wrong is permanent. So a delete here is reversible for thirty days, and the response tells you the exact date the bytes get removed:

That date is not decoration. It is computed from the deletion stamp and returned by every door, so an agent relaying "I deleted that for you" can also say when it stops being recoverable. Until then the file is one click, or one tool call, from coming back with its bytes intact.
The honest version of why: the bytes outliving the click is what makes restore real. A system that removed them immediately and offered an undo button would be lying.
Two places it deliberately stops
An agent cannot upload bytes. MCP tool arguments are JSON. Base64 inflates a file by a third, and the per-file cap is 25MB, so a file of any real size cannot travel as a tool argument. Rather than build something that works for a 200KB text file and fails confusingly at 4MB, agents get a URL-based attach and a clear instruction to hand the CLI command to you when the file is on your own machine.
That URL fetch is the one place the server goes out to an address somebody else chose, so it refuses anything but https, requires every DNS answer to be a public address, pins the connection to the address it checked, re-checks every redirect, and caps the download while it streams rather than trusting the server's declared length. Cloud metadata endpoints, loopback, and a public URL that redirects to 127.0.0.1 are all refused. The tests are written as those attacks rather than as happy paths.
It is not a file manager. There is no folder tree, no search inside documents, no versioning of the file itself. A memory is the unit. If what you want is a place to keep four hundred PDFs, this is the wrong tool and Drive is the right one. What this is for is the handful of artifacts that only make sense next to a particular decision.
Attachments also need a paid plan. The free tier has no attachment storage at all, and an upload returns an upgrade link instead of a vague error.
Where it lands
The test I care about is not whether a file uploads. It is whether, in three months, asking an agent about the 2027 renewal gets back the reasoning and the contract rather than the reasoning and a dead link.
That is the whole point of putting them in the same place.
empirical memory attach --match "2027 renewal" --file ./contract.pdf