AFP v0.1 DRAFT

Files for AI Agents

Do not share a filesystem. Share objects by reference. AFP lets an agent put a file, name it, prove what it is, and hand it to another agent or a person on any host, with no mounted folders.

Draft specification. Companion to AMP (messages), AAP (UI actions) and AID (identity).

THE PROBLEM

Why AFP?

TodayWhat goes wrong
Mounted network folders (SMB, NFS)macOS drops the mount. The agent hangs or errors on a path that vanished.
Attach the file to a messageFine for one recipient. Capped at 25 MB, expires with the message, nothing to browse later.
A web file server on one hostPeople can use it. Agents on other hosts cannot.
Per-vendor cloud storageEach runtime invents its own way, and nothing interoperates.

THE IDEA

Objects, not mounts

Nothing is mounted, so nothing can drop. The store is the truth. A message that says "a file arrived" is only a hint.

agent A: afp-put.sh report.pdf --space artifacts  ->  afp://artifacts/2026/10/report.pdf  (sha256:3b2c...)
agent A: sends an AMP message that carries the reference, not the bytes
agent B: afp-get.sh afp://artifacts/2026/10/report.pdf  ->  verified against the digest
human:   opens the same file from the agent UI, or from any S3 client

Space

A named place with one backend and one access scope, such as shared or artifacts. A host configures its spaces.

Object and reference

An object is one file at a path. Its reference, afp://space/path, travels with a SHA-256 digest and a size.

Manifest

A small JSON file next to each object: digest, size, content type, owner, created, optional expiry, and the scan result.

Capabilities

A backend declares what it can do (link, expire, versions, offline, ui). Callers check before relying on one.

Not in v0.1: merging concurrent edits, end-to-end encryption, quotas, cross-organization federation.

OPERATIONS

Five operations and a capability check

OperationWhat it doesReference client
putComputes the SHA-256, uploads, reads the digest back from the store, writes the manifest. Reports stored: true only after that check. Never falls back silently to a local copy. An existing path is not overwritten unless force is set; otherwise the code is exists.afp-put.sh <file> [--space NAME] [--path PATH] [--ttl TTL] [--content-type TYPE] [--force]
getDownloads and compares the digest (from the reference object, else the manifest). A mismatch deletes the partial file and fails with digest_mismatch. A reference with neither a digest nor a manifest cannot be verified and also returns digest_mismatch. A suspicious or rejected scan blocks the fetch with scan_blocked. Without credentials for the space, the url in a reference object may be used; the digest check still applies.afp-get.sh <ref> [--digest SHA] [--dest PATH] [--force]
lsLists objects in a space, optionally by prefix, from their manifests (default limit 100). Returns truncated: true when more objects matched than the limit returned.afp-ls.sh [--space NAME] [--prefix PREFIX] [--limit N]
linkReturns the full reference object with a time-limited download url (default 1 hour, maximum 7 days). Needs the link capability, otherwise unsupported. Needs the object's manifest, because the reference carries its digest; without one the code is not_found.afp-link.sh <ref> [--ttl TTL]
rmDeletes an object and its manifest. By default only the owner or a host administrator may delete. Returns ok: true only when the store confirms the deletion.afp-rm.sh <ref> [--admin]
capabilitiesReturns what a space's backend can do, so an agent does not promise a link where none can be made.afp-capabilities.sh [--space NAME] [--probe]

All output is JSON. A failure returns { "ok": false, "error": { "code": "...", "message": "..." } }, and a command-line implementation exits non-zero. An unreachable store returns unreachable and is never hidden.

Error codes: exists, not_found, digest_mismatch, scan_blocked, unsupported, unreachable, invalid_path, invalid_space, forbidden, too_large, usage. usage means missing or malformed arguments.

BACKENDS

Any S3-compatible store

v0.1 defines one profile, s3. Garage is the reference backend: a small, self-hosted store with a single-node mode and optional replication. Nothing in AFP requires it.

TopologyTypical useTrade-offs
Local only: Garage on one host, reached over a LAN or a private meshA team's fleet on its own networkNo cost, no data leaves the network. One host is a single point of failure until replicated.
Self-hosted in the cloud: Garage on a VPS or cloud instance behind a TLS reverse proxyAgents and people in several places, links that must work from outsideYou run and patch it. Reachable from anywhere, so the network is no longer the trust boundary and access keys matter more.
Hosted S3-compatible serviceNo server to runData leaves your network. Provider terms, egress and pricing apply. Capabilities vary and must be declared.
Multi-node GarageSurviving a host failureMore to operate. Needs a replication factor above 1.

A host may configure several spaces on different topologies, for example shared on a local store and public on a cloud store. Garage supports presigned URLs, multipart upload, CORS and lifecycle expiry. It does not support object versioning, S3 ACLs, bucket policies or quotas, and AFP does not need them.

AMP INTEGRATION

Two kinds of attachment

A message's payload.attachments entry has a storage field. An entry with no field is a provider attachment, so existing messages are unaffected.

storageMeaning
providerExisting AMP behavior: uploaded to the provider, scanned, signed, expires with the message.
afpAn AFP reference. No bytes pass through the provider.
{
  "storage": "afp",
  "filename": "report.pdf",
  "content_type": "application/pdf",
  "size": 1827341,
  "digest": "sha256:3b2c9f5da87e4f1c8b0a2d6e9f3c7a1b5d8e2f4a6c0b3d7e9f1a4c6d8e0b2a40",
  "ref": "afp://artifacts/2026/10/report.pdf",
  "endpoint": "https://files.example.net",
  "url": "https://files.example.net/artifacts/2026/10/report.pdf?X-Amz-Expires=3600&..."
}

The attachment lives inside payload, so the message signature binds the reference and digest. Use a provider attachment for a file that belongs to one message and is under 25 MB. Use afp when the file is large, shared by several parties, must outlive the message, or is published for a person to retrieve.

A sender puts the object, and gets stored: true, before routing the message. A recipient verifies the digest on fetch. A provider that accepts AFP attachments advertises the capability attachments:afp; routing one to a provider that does not list it returns 422 attachments_not_supported. Local delivery needs no negotiation.

SECURITY

What the spec requires

What AFP does not protect: a store operator can read every object (no end-to-end encryption in v0.1), a leaked presigned link works until it expires, and a compromised access key exposes everything in its scope.

INSTALL

Quickstart

The reference client is a set of Bash scripts (bash 3.2 and later, curl 7.75+, jq, openssl, shasum or sha256sum). It is tested against Garage; any S3-compatible store that accepts path-style requests should work.

1. Install the scripts

git clone https://github.com/agentmessaging/agent-files.git ~/agent-files
~/agent-files/install.sh             # copies the scripts to ~/.local/bin
~/agent-files/install.sh /usr/local/bin   # or to another directory

2. Configure a space

A space is a bucket (optionally a key prefix in it) on an S3-compatible store. Add it on every machine that should use it. Put the secret key on the first line of the --secret-file and keep that file mode 600. Spaces are stored in ~/.agent-files/spaces.json, and secrets are never printed.

afp-config.sh add shared --endpoint http://host:3900 --bucket afp --region garage \
    --access-key <key> --secret-file <file> --capabilities link,expire,ui --default

3. Put and get a file

afp-put.sh report.pdf              # -> afp://shared/2026/10/report.pdf
afp-get.sh afp://shared/2026/10/report.pdf
CommandWhat it does
afp-put.sh <file>Store a file, read it back, verify the digest, write the manifest, print the reference
afp-get.sh <ref>Fetch an object and verify its SHA-256 (refuses suspicious and rejected)
afp-ls.shList objects from their manifests
afp-link.sh <ref>Print a reference object with a time-limited download URL
afp-rm.sh <ref>Delete an object and its manifest
afp-capabilities.shReport what a space can do
afp-config.shAdd, list and remove spaces, set the default

Claude Code skill

The agent-files skill teaches an agent to use these commands, with setup, space examples and troubleshooting in its references/setup.md. AI Maestro is the first provider: as a Claude Code plugin, its update-aimaestro.sh installs the skill and puts the afp-*.sh scripts on the PATH.

Read the specification

Open protocol. MIT licensed. v0.1 draft.

AGENTMESSAGING/AGENT-FILES