Waking your agent when a decision lands

When a person approves, declines, requests a revision or comments on an agent's artefact, LatticeRun can email the agent so something can start it. This guide covers the whole path: give the agent an inbox, tell LatticeRun where to send, receive the mail, and turn it into the agent actually running.

This is a doorbell, not a report. The email says which agent it concerns, which artefact, which task, what the decision was, and links back. Everything else lives behind the link, and the agent still sees the same decisions on its next latticerun_start_task claim — so a missed email is late, never lost.

1 · Give the agent an inbox

An agent needs an address of its own before anything can be delivered. The easiest option is AgentMail, a mail provider built for agents: inboxes are created from an API, messages are readable over HTTP and WebSockets, and webhooks are first-class. Any mailbox would work — LatticeRun only sends email — but AgentMail removes the least pleasant parts.

SetupWhat it costs
One shared inbox, one reader $0 at any fleet size
One inbox per agent ≈$0 up to 3 inboxes · ≈$30/month for 15 · ≈$100/month for 50 (annual billing is materially less: ≈$0 / ≈$24 / ≈$80)
Extra inboxes on the developer tier about $2/month each
AgentMail's flat ≈$200/month tier only becomes cheaper above about 100 inboxes — not the answer for a 15-agent team

Prices verified against AgentMail's own pricing page at the time of writing — check it before you budget. And a shared inbox is not a way to avoid the cost of separate inboxes; read section 3 before you plan around that.

2 · Set it up in LatticeRun

Two things happen in the app, both under Agent tokens in the profile menu:

1

Define a notification address

Under Notification addresses, add the address you want agent mail delivered to — your AgentMail inbox, a shared inbox, a distribution list. Optionally give it a label ("Research bots"), so the agents it manages are recognisable at a glance.

2

Assign agents to it

Each agent row has a Notify: line. Pick an address there. One address can manage many agents, and each agent is assigned to at most one — several agents sharing one address is a first-class setting, not a workaround.

That is the whole setup. Until an agent has an address, nothing changes: no email is sent, exactly as before. When an address is set, a decision or comment on that agent's artefact sends one email — and if a decision ever arrives while no address is set, LatticeRun records it as not delivered and shows it on the agent's row, rather than dropping it silently.

3 · One address, several agents

Sharing one address is supported, and the pattern for it is a single dispatcher: one process reads the inbox, looks at the Agent: line the email carries, and routes the work onward. Because LatticeRun puts the agent's name inside every message, a dispatcher can always tell which agent a notification is for.

One inbox has one reader. AgentMail has no mark-as-read endpoint — read state is a single label on the message, shared by every reader, with no atomic claim. Two independent readers on one inbox consume each other's mail and can both act on the same message. That is silent data loss, not an error you will see.

LatticeRun's job ends at delivering each notification to the address you configured. How it gets from the inbox to the agent — a dispatcher relaying, or an agent reading its own mailbox — is yours to choose. No relaying mechanism is assumed.

4 · How to receive the notification

The email lands in the provider's inbox. Getting from there to something running on your machine or infrastructure takes one of these shapes:

The trade-offs are honest ones. Without a public endpoint there is no instant push — you get the mail when you next poll. And a machine that is asleep receives nothing until it wakes, whichever shape you choose: the notification simply waits.

5 · The last mile: from email to running agent

This is the step people underestimate. "The agent gets notified" is really "the thing that starts the agent gets notified" — the agent is a process, and a process that has exited cannot be woken by a message. The piece you have to write is the wake trigger: the small component that decides to start an agent.

In industry terms this is event-driven agent invocation: a webhook receiver accepts the event, and a wake trigger turns it into a run. There is no single settled standard for the last part — every host does it its own way — so treat this as a pattern, not a specification.

HostCan it be started from outside?Confidence
Hermes CLIYesVerified
Claude Code CLI (claude -p, Agent SDK)YesVerified
OpenAI API (POST /responses)YesVerified
Grok Bot Partial — schedules and Slack/GitHub event triggers are first-party; email/webhook wake is community-documented Mixed
Claude Desktop appNo — scripting and the Agent SDK are CLI-onlyVerified
ChatGPT appNo documented way to start a turn from outsideInferred

Where there is no external entry point there is no last mile to build — the honest fallbacks are notifying the human, or letting the agent pick the work up on its next claim. Do not wire a wake trigger to a host that cannot be started; it will look like it works and quietly do nothing.

6 · AgentMail mechanics worth knowing

7 · A worked example

A reference implementation of the whole path exists and was verified on 6 October 2026. Its inbox is sequelai@agentmail.to; the pattern it follows is the one to copy, wherever you place the pieces:

1

Create the inbox and point LatticeRun at it

Create an AgentMail inbox, then add that address under Agent tokens → Notification addresses and assign the agent. Send a test event: comment on one of the agent's artefacts and confirm the email arrives, naming the agent.

2

Expose a receiver on a public hostname

A Cloudflare named tunnel — or any of the options in section 4 — puts a local receiver online at a hostname you own. Run the tunnel as an auto-restarting service so the hostname survives reboots, and bind the receiver to loopback only: it should be reachable solely through the tunnel, never publicly.

3

Verify every webhook, then answer fast

The receiver checks the provider's signature (Svix) against the endpoint's signing secret and rejects anything that fails: an unsigned request gets a 400 — which is also how you prove verification is genuinely enforced rather than merely configured. Valid deliveries get a 204 immediately, with the real work happening out of band.

# proves the signature check is live — expect 400
curl -i -X POST https://your-receiver.example/agentmail/webhook \
  -H 'content-type: application/json' -d '{}'
4

Store once, then wake

Verified events go into a small durable store keyed on the event id, so a delivery that arrives twice — or arrives on both the webhook and a fallback path — is stored exactly once. A second, independent path (a WebSocket subscription to the same mailbox) writes into the same store, so a message still arrives if the tunnel is down; the key is what makes the redundancy free.

The wake trigger then polls that store — a local database read, no model, no cost — coalesces a burst of messages into one job ("five emails become one run"), and starts the agent. It records the event as handled before starting the agent, so a crash mid-run cannot cause an endless loop, and it caps how often it may fire per hour and per day.

5

Verify the whole loop

  • Unsigned webhook → 400. Signed delivery → 204, and an event row appears in the store.
  • Stop the tunnel and send a comment: the WebSocket path still stores the event.
  • Watch the wake trigger start the agent once for a burst of messages, not once per email.
  • The agent replies once, when the work is done. If the work outlasts its time window, it sends one short acknowledgement and schedules its own next wake — a finished run is an exited process, and nothing can restart it from outside.

What to check when it does not work

8 · What this cannot do

Agent notifications are included with Solo Pro, Founder Lifetime and Team Block. See pricing →