Secure File Storage for AI Agents: Scoped Keys and Logs

An AI agent that reads and writes files needs a place to store them. If the agent uses your main account key, one wrong command or one hostile instruction in a document can reach every file that you own. Give the agent its own storage area, its own key with the lowest access that it needs, and a record of what it did.

This guide shows how to do that on Amazon S3, Cloudflare R2 and Google Drive. The same rules apply to other storage services.

Five rules for agent storage

  1. Give each agent or project its own area: a separate bucket, or a separate prefix in a bucket. A prefix is the start of an object name, for example research-agent/. It works like a folder.
  2. Give each agent its own credential. Then you can delete the key of one agent, and the other agents continue to work.
  3. Give the lowest access that the task needs. An agent that only reads gets read-only access. No agent gets admin access.
  4. Give each key a short life: an expiration date, or temporary credentials that expire on their own.
  5. Keep a record and a way back: access logs, and older versions of each file where the service keeps them.

Keep public access off for the storage of the agent. If a person must see a result, share that one file.

Amazon S3: one prefix and one IAM policy

  1. Create a bucket for agent files, for example acme-agent-files. By default, new buckets do not allow public access.
  2. Turn on S3 Versioning for the bucket. Versioning is off by default.
  3. In IAM, create an identity for the agent.
  4. Attach a policy that gives access to one prefix only, as in the example that follows.
  5. If the agent runs on AWS, for example on Amazon EC2 or AWS Lambda, give it an IAM role. AWS then delivers temporary credentials to it.
  6. If the agent runs outside AWS and needs an access key, create the key for this IAM user only.

This policy lets the agent list, read and write objects under research-agent/ in one bucket, and nothing else:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ListOnlyTheAgentPrefix",
      "Effect": "Allow",
      "Action": "s3:ListBucket",
      "Resource": "arn:aws:s3:::acme-agent-files",
      "Condition": { "StringLike": { "s3:prefix": ["research-agent/*"] } }
    },
    {
      "Sid": "ReadAndWriteInTheAgentPrefix",
      "Effect": "Allow",
      "Action": ["s3:GetObject", "s3:PutObject"],
      "Resource": "arn:aws:s3:::acme-agent-files/research-agent/*"
    }
  ]
}

The policy does not include s3:DeleteObject. With versioning on, an overwrite makes a new version, and you can restore the earlier version. For an agent that only reads, remove s3:PutObject. AWS shows more policy examples for one bucket or one folder.

AWS recommends temporary credentials with IAM roles for workloads. If you must use a long-term access key, replace it when needed and delete it when the agent stops.

To see what the agent did, turn on logs. AWS recommends CloudTrail for bucket-level and object-level actions. CloudTrail data events, which record object reads and writes, have a fee. S3 server access logs that go to a bucket cost only their storage, and they arrive within a few hours.

Cloudflare R2: a token for one bucket

R2 has an S3-compatible API, so the agent can use S3 tools and SDKs. Its tokens are scoped to buckets, so give each agent its own bucket.

  1. Create a bucket for the agent. Buckets are not public by default.
  2. In the Cloudflare dashboard, go to R2 object storage > Overview.
  3. Under Account Details, select Manage next to API Tokens.
  4. Select Create Account API token.
  5. Select Object Read & Write. For an agent that only reads, select Object Read only.
  6. Scope the token to the bucket of the agent only.
  7. Create the token. Copy the Access Key ID and the Secret Access Key.
  8. Give the agent the two keys and the endpoint https://<ACCOUNT_ID>.r2.cloudflarestorage.com.

To create the bucket from a terminal, use Wrangler:

wrangler r2 bucket create acme-agent-files

The dashboard shows the Secret Access Key only once. Do not give an agent the Admin permissions. They also let the token create and delete buckets and change the bucket configuration.

If your own code gives a key to an agent for one task, use R2 temporary credentials. They come from an existing API token and are bound to exactly one bucket. You can limit them to prefixes or to single objects, and they expire after the time that you set.

R2 does not support the S3 bucket versioning operations. If the agent must not lose source files, keep the originals in a bucket where the agent has Object Read only access. Give the agent Object Read & Write access to a second bucket for its results.

To see what the agent did, open the Bucket settings of the bucket and turn on Data Access Logs. The log records reads, writes, lists and deletes, with the access key ID of each signed request. Cloudflare keeps the logs for seven days. Delivery is best effort, so some events can be late or missing. The R2 audit logs record changes to the bucket configuration, not object reads and writes.

Google Drive: a separate account and one shared folder

Some agents reach storage through a connector in a chat app, not with an API key. For these agents, connect a separate account that can see only one folder.

  1. Create a separate Google Account for the agent. You do not need a Gmail address for it.
  2. In your own Drive, create a folder for the agent work.
  3. Select the folder, click Share and enter the address of the agent account.
  4. Choose Viewer for an agent that only reads. Choose Editor for an agent that must add files.
  5. In the chat app, connect Google Drive with the agent account, not with your own account.

By default, an Editor can also delete, move and share files in the folder. Give Editor access only to an agent that must write. With the Claude Google Drive connector, for example, Claude can search and read files, upload files and create folders. By default, it asks for your approval before it shares a file, moves a file or puts a file in the trash.

Drive keeps older versions of uploaded files, such as PDFs and images. It can delete an older version after 30 days, or when 100 newer versions exist. To keep a version, open Manage versions for the file and select Keep forever. The same help page shows how to see the activity on a file.

Files that arrive by email

Do not give a storage agent your mailbox. A mail connector is not a file store. The Claude Gmail connector, for example, reads the metadata of attachments, not their content.

Let one process save each attachment into the storage of the agent. On Cloudflare, Email Workers run your Worker code on each incoming message. A Worker can write objects to an R2 bucket through a binding. The agent then reads the files from the bucket and never sees the mailbox.

Mistakes to avoid

  • One key for all agents. You cannot see which agent made a change, and you cannot remove one agent alone.
  • The root key or an admin token in the configuration of the agent.
  • A public bucket for a quick share. Share one file instead.
  • Keys in a prompt, a chat or a Git repository. Put keys in environment variables or in the secret store of your platform.
  • Keys with no end date. AWS recommends that you remove unused users, roles, permissions and credentials. IAM shows last accessed information for each of them.
  • Instructions inside files. Text in a document can try to give orders to the agent. This attack is called prompt injection. Treat file content as data. A scoped key limits the damage when an attack works.

A docs portal with Ask AI
and support tickets

Connect a repository, or describe your product to start. Each docs site has search, Ask AI, an API console, an MCP server and support tickets.

  • Publishes from GitHub on every push
  • Works with Mintlify repositories
  • API console from your OpenAPI file
  • MCP server and llms.txt for AI agents
  • Ask AI and support tickets
  • Analytics for people and AI agents
Start Free Questions? Ask AI in our docs

No card required.

Frequently Asked Questions

Is a separate bucket better than a separate prefix?

On Amazon S3, a prefix with its own IAM policy is enough. On Cloudflare R2, API tokens are scoped to buckets, not to prefixes, so give each agent its own bucket. R2 temporary credentials can be limited to prefixes, but they expire.

What do I do when an agent key leaks?

Delete the key at once and create a new key for the agent. Then read the access logs for the time after the leak. Restore changed files from older versions where the service keeps them.

Share:
Markdown version
↧
Loading PDF…