The work
EngineeringAgencies

Every agent that sends an email sends it from its own real account, so you can always see which one did what.

Liberators and WEDOHYPE
gmail_replyDraft by default
The agent supplies
message_id
body
that is all
The server computes
threadout of reach
in-reply-toout of reach
referencesout of reach
subjectout of reach
toout of reach
cc (whole thread, minus self)out of reach
A reply cannot drop a recipient if it never chose one

The agent supplies two things. Everything that could go wrong is computed for it.

The situation

How this used to work

The obvious way to give a set of agents access to email, files and calendars is one connection with broad permissions, shared by all of them. It is less to build and less to maintain.

It also makes every action untraceable. When four agents across two companies and a personal account all act through one login, the record of who did what is a single name that means nothing, and the answer to which agent sent that email is unavailable in principle rather than just hard to find.

This was not theoretical here. One company's account was once used to write into the other company's files, as a workaround when an interface was disabled. The note written afterwards lists three separate harms, and the one in the middle is that the audit trail was now wrong.

What we built

The system

One server per identity. Six of them, each holding its own credential, each acting as its own real account, split across both companies plus a personal account and a client's.

The identity is not configured anywhere. Each server asks the provider who it is, using the credential it holds, and caches the answer. That means the mailbox and the credential cannot disagree, because one is derived from the other.

Each one also carries its own outbound signature, compiled in. An agent working for one company cannot send mail that looks like it came from the other, because the branding travels with the credential rather than being chosen per message.

The honest part: this is not a shared library with six configurations. It is the same codebase copied six times. Diffing two of them turns up nine differing lines, and all nine are the signature. The duplication bought the isolation and it charges maintenance for it, which is visible in the fact that the copies have already drifted apart on permissions.

How it works

The pipeline, step by step

01 / Hold one credential

The server is the boundary

Each deployment gets exactly one credential, supplied to it as configuration and refreshed automatically when it expires. There is no mechanism for selecting an account per request, which is the point. What a server can reach is decided at deploy time, not at call time by whatever is asking.

02 / Ask who you are

Identity is derived, never declared

On first use the server calls the provider to find out which account the credential belongs to. Everything afterwards, including who to exclude from a reply, is based on that answer rather than on a string somebody typed into a config file and might have got wrong.

03 / Take capability away

The reply the agent cannot get wrong

The reply tool accepts two things: which message, and what to say. Everything else, the threading identifiers, the full reference chain, the subject line, the recipient, and the copy list, is computed from the thread itself. The copy list is the union of every participant across every message in it, minus the account's own address. Its own note says the point plainly, which is that the agent never touches any of this, so a reply cannot accidentally break the thread or drop somebody.

04 / Default to a draft

Sending is the exception, in the signature

The reply tool's draft parameter defaults to true across every server in the fleet. Sending immediately is possible and it is the thing you have to ask for. The rule that emails are drafted rather than sent is written in the workspace instructions too, but instructions are a request and a default is a behaviour.

05 / Land in the record

Auditing is a side effect, not a feature

There is no logging layer here and there does not need to be. Every action is a real API call made by a real account, so it lands in that account's sent folder, its file revision history and its administrative logs by construction. The traceability comes from the identity being real, which is the whole argument for six servers instead of one.

Where it landsNo logging layer
An email is sentThat account's Sent folder
By construction
A document is editedThe file's own revision history
By construction
Anything at allThe workspace administrative log
By construction
The traceability comes from the identity being real

Nothing here was built for auditing. All of it audits anyway.

06 / Scope per identity

Only two of them can touch the directory

The permissions are not uniform. The two servers that need to manage groups hold that permission and the others deliberately do not, with a note next to it recording what it costs to grant. Least privilege is applied per identity, which is only possible because the identities are separate in the first place.

Scopes per identity6 deployments
Directory · manage groups2 of 6
Mail, Drive, Docs, Sheets, CalendarAll six
Least privilege per identity, which needs the identities to be separate

Six deployments. Two of them hold the directory permission.

What changed

The result

Five hundred and fifty eight tools across the six servers, counted from the code rather than read off a README, because every one of those READMEs undercounts itself. The largest single surface is not email. It is documents, at up to thirty one tools per server, which makes this a document production system with a mailbox attached rather than the other way round.

The rule that governs it was written after it was broken rather than before. That is worth stating accurately: the separation existed, somebody worked around it under time pressure, and the write-up afterwards is what turned a design into a rule with a reason attached.

The pattern that generalises is not one mailbox per agent. It is that the safest way to stop an agent doing something wrong is to never give it the ability, rather than to instruct it not to. The reply tool is the clearest example, and the draft default is the same idea written into a function signature.

The stack

Servers

  • Python
  • FastMCP
  • streamable HTTP
  • Railway

Identity

  • user-delegated OAuth
  • one credential per deployment
  • runtime identity lookup

Surface

  • Docs
  • Gmail
  • Drive
  • Sheets
  • Calendar
  • 558 tools counted

Safety

  • draft by default
  • thread-computed recipients
  • per-identity scopes

Free 30 minute call

Let's find where AI fits in your business

A 30 minute call, free, no commitment. You leave with two or three things worth building, whether or not you work with us.

Free, no commitmentYou own everything we buildNo slide deck