Agent-First Mail v0.7: Run It Again

by Agent-First Kit Contributors

v0.7 makes every mutation safe to retry: a --request-id turns any local change into an idempotent operation, remote effects only fire from a plan you already reviewed, and pulls run inside a byte-and-count budget you set up front.

afmail builds a local workspace your agent navigates by path. Agents crash mid-command, lose a connection, and resume from an unclear state — so the question that runs through v0.7 is: what happens when the agent runs the same command twice? The answer, across the whole surface, is now “nothing bad.”

A request id makes any mutation idempotent

An agent that adds a message to a case, times out waiting for the response, and retries used to add it twice. There was no way to tell afmail “this is the same operation I already tried.”

v0.7 adds a global --request-id:

afmail case add c20260714001 --message message_inbox_90233_7 \
  --reason "billing dispute" --request-id add-90233-to-case

Run that command again with the same id and afmail recognises the operation, replays the original outcome, and changes nothing. The id is an idempotency key: the first call does the work and records the result; every repeat returns that recorded result. It covers the non-idempotent local mutations — message dispositions, case lifecycle, membership edits, draft edits, contact edits and renames, notes, summaries, and local deletes.

The agent picks the id. Derive it from whatever makes the operation unique in your workflow — a task id, a hash of the inputs — and a dropped connection stops being a correctness problem. Retry blindly; the second run is a no-op.

Remote effects only fire from a plan you reviewed

Idempotency handles repeats of a local change. Remote pushes get a stronger guarantee: they can’t fire from anything but a plan the agent has already looked at.

Push and purge now bind their remote effects to a reviewed plan id. You inspect the plan — every server-side move, delete, or send it intends — and the confirming command only proceeds against that plan. If the queue changed underneath you, the id no longer matches and afmail refuses rather than pushing a different set of effects than the one you approved.

afmail push                         # review the plan and its id
afmail push --confirm               # executes only the reviewed plan

Case archiving fits the same shape: a case’s archive lifecycle finalizes only after its push succeeds, so a case never looks archived locally while its server-side move is still pending.

Pulls run inside a budget

Reading mail from a remote mailbox is the one operation whose size you don’t know before you start. v0.7 lets you estimate first and cap what lands:

afmail pull --dry-run                              # estimate candidates and bytes, download nothing
afmail pull --since-days 7 --max-new-messages 200 --max-total-bytes 50000000

--dry-run reports what a real pull would fetch without writing anything. --max-new-messages and --max-total-bytes bound what a real pull stores across all selected mailboxes, so an agent working a fresh account can’t accidentally pull a decade of history into the workspace. Under the hood, pulls now persist an incremental cursor, so a resumed pull picks up where the last one stopped instead of rescanning from the top.

Knowing where you stand

Two additions make the workspace state legible before the agent acts. afmail status now reports explicit onboarding readiness — whether the workspace is configured enough to pull, push, and send — so an agent can check readiness instead of inferring it from failures. The same report carries a storage object with local byte counts, so the agent can see how much space the workspace occupies without walking the tree itself.

Boundaries around untrusted mail

Mail is attacker-controlled input, and v0.7 tightens how afmail handles it. IMAP body fetches are bounded by default, so a hostile server can’t stream an unbounded response into the workspace. Rendering enforces boundaries on untrusted message content. And afmail redacts private values from its own startup argv and runtime logs, so diagnostics never leak workspace contents or credentials.

Under the hood

v0.7 also adopts afdata protocol v1 end-to-end — commands emit typed, structured results with flattened error fields through a semantic emitter, so agents parse one consistent shape across the surface. Drafts carry explicit intent and content states, message listing gained filters, case and notification additions batch, and the AFUI workspace was redesigned to render full case conversations — active and archived — safely.

Install

brew install agentfirstkit/tap/afmail        # macOS / Linux
scoop bucket add agentfirstkit https://github.com/agentfirstkit/scoop-bucket
scoop install afmail                          # Windows
cargo install agent-first-mail                # any platform

After installing, run afmail skill install so your agent reloads afmail’s updated behavior rules.