Skip to content

Email ​

Bishop reads a Google Workspace mailbox and answers mail in the same thread. The agent needs its own Workspace user, say [email protected]. That address is what people write to, and its mailbox is what Bishop reads. Don't point this at a person's account.

Setup ​

Create an OAuth client, once:

  1. In the Google Cloud console, pick or create a project and enable the Gmail API.
  2. Configure the OAuth consent screen with user type Internal. This is what lets you skip Google's app verification.
  3. Create an OAuth client ID of type Desktop app.
  4. Put both values in .env:
sh
BISHOP_GMAIL_CLIENT_ID=...
BISHOP_GMAIL_CLIENT_SECRET=...

Then authorize the mailbox:

sh
bishop gmail setup

A browser opens. Sign in as the agent's Workspace user, not as yourself, and approve. Bishop catches the redirect, writes BISHOP_GMAIL_REFRESH_TOKEN to .env, and tells you which mailbox it reached.

Re-running it later checks the credentials instead of authorizing again, so it doubles as a health check in a deploy script. It exits non-zero when the mailbox can't be reached.

Set gmail.allow before pointing anyone at it. Without it, every address that can reach the mailbox can use the agent, and a Workspace mailbox can be reached from anywhere.

json
{ "gmail": { "allow": ["[email protected]", "@example.com"] } }

Moving it to a server ​

The refresh token isn't tied to the machine you authorized on. Copy three lines to the server's .env and start Bishop there:

sh
BISHOP_GMAIL_CLIENT_ID=...
BISHOP_GMAIL_CLIENT_SECRET=...
BISHOP_GMAIL_REFRESH_TOKEN=...

To set it up on the server directly instead, run bishop gmail setup there. It notices it's over SSH, prints a URL instead of opening one, and asks you to paste back where the browser ended up. The browser lands on a http://127.0.0.1 address that fails to load, which is expected: the code is in the address bar, and pasting the whole address is enough. --no-browser forces that mode anywhere.

When it stops working ​

Google revokes Gmail refresh tokens when the mailbox's password is reset. The agent goes quiet, the log says the token is no longer valid, and bishop gmail setup fixes it by authorizing again.

If that isn't acceptable, use domain-wide delegation instead. Nothing about it expires and no person is ever needed again, but it costs more to set up: a service account key, which most organizations now block by default, plus a Workspace super admin to grant the delegation. Set BISHOP_GMAIL_USER and BISHOP_GMAIL_SERVICE_ACCOUNT instead of the three OAuth variables, and run bishop gmail setup to check it. It prints the exact client ID and scope to paste into the admin console when the grant is missing.

Using it ​

Anyone on the allow list emails the agent, and the reply arrives in the same thread. An email thread is an agent session, exactly as a Slack thread is: reply to the agent's answer and it picks up where it left off.

  • Nothing happens until the turn is over. No streaming, no progress, no sign the agent is working. Then one plain-text reply arrives with everything it had to say. This makes a long turn fine, which it isn't in Slack.
  • The reply goes to everyone on the thread. So Bishop refuses a thread with anyone on it who isn't on the allow list. If you're on the list and copied someone who isn't, it tells you why. If you're not on the list, it sends nothing at all.
  • Labels are the only progress you get. Bishop marks each thread Bishop/Working while it runs, then Bishop/Done, Bishop/Failed, or Bishop/Refused. Open the mailbox to see what the agent is doing.
  • Attachments come through. Bishop downloads what was attached and hands the agent the path, the same as in Slack.
  • No stop button. Nothing in email can cancel a turn.

Mail the agent never answers ​

Bishop never answers automated mail: autoresponders, mailing lists, bounces, its own address, or anything Gmail marked spam. It also refuses mail whose sender Gmail's own verdict doesn't clear, without writing back, since the from address is the one thing known to be untrustworthy there. That check reads DMARC rather than a bare SPF or DKIM pass, and only from the topmost Authentication-Results header, because a sender can write that header themselves and only Gmail's own copy means anything.

Bishop only ever writes to an address on the allow list. Someone not on it gets no reply, not even one explaining why. The thread is labelled Bishop/Refused and the reason goes in the log. Without this, pointing the agent at a mailbox that receives ordinary mail means it answers every stranger who writes in.

Bishop never answers mail that arrived before you pointed it at the mailbox. It records that moment the first time it connects and refuses anything older. Startup logs the cutoff as answeringMailAfter. Restarts still catch up on whatever arrived while it was down, because the cutoff is when it first attached, not when the process started. There is no setting that moves it earlier.

Configuration ​

The gmail block takes allow, pollSeconds, labelPrefix, markRead and internalDomains. Configuration describes each.