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.
On this page
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.
| Setup | What 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:
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.
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.
- Several agents, one dispatcher → one shared address is fine, and free.
- Agents that read independently (different vendors, different machines) → one inbox per agent. AgentMail "pods" keep each vendor's mail separate.
- Several independent consumers on one inbox → would need per-reader namespaced labels plus message-id idempotency. LatticeRun does not build that for you; if that is what you need, build it in your receiver.
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:
- A webhook receiver hosted anywhere public — a small server, a serverless function, or a container. The provider calls it on delivery; it is instant and reliable as long as the host is up.
- A tunnel to a local machine — Cloudflare Tunnel, Tailscale Funnel or ngrok expose a receiver running on your own computer at a public hostname. Nothing to deploy; the tunnel process must stay up.
- Long-polling the provider's API — a local process asks AgentMail for new messages every few seconds. Nothing is exposed publicly at all.
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.
| Host | Can it be started from outside? | Confidence |
|---|---|---|
| Hermes CLI | Yes | Verified |
Claude Code CLI (claude -p, Agent SDK) | Yes | Verified |
OpenAI API (POST /responses) | Yes | Verified |
| Grok Bot | Partial — schedules and Slack/GitHub event triggers are first-party; email/webhook wake is community-documented | Mixed |
| Claude Desktop app | No — scripting and the Agent SDK are CLI-only | Verified |
| ChatGPT app | No documented way to start a turn from outside | Inferred |
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
- An inbox is not bound to one API key — several keys can exist for it, for different components.
- Multiple webhook receivers on one inbox fan out to every matching endpoint, not one winner. Another reason two independent readers on one inbox is dangerous.
- Multiple WebSocket subscribers on one inbox are supported — a good fallback path when a webhook cannot be delivered.
- The only published per-inbox numeric caps are send caps: free 100/day; developer 1,000/day and 100 per 5 minutes; startup 15,000/day and 1,500 per 5 minutes. There is no published read cap — so do not design against a promise of read throughput.
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:
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.
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.
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 '{}'
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.
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
- Your test call returns 400 — that is the signature check doing its job. For real deliveries, make sure the receiver has the endpoint's current signing secret.
- 204 but nothing stored — the handler answered before persisting, or the write failed silently. Log the event id before acknowledging, and check the store directly.
- Nothing arrives at all — is the tunnel up, and does the provider have the right webhook URL? If both look right, the WebSocket fallback should still be catching messages.
- The agent never starts — the wake trigger, not the mail, is the usual culprit. Check its caps, and whether it recorded the event as handled before the start.
- Duplicates — expected; the event-id key should absorb them. If it does not, the id is not being used as the key.
- The machine was asleep — nothing was lost. The mail waits in the inbox; the agent gets it when the machine is back and something polls or receives it.
8 · What this cannot do
- It cannot wake a machine that is off or asleep. The notification waits; it does not push a sleeping computer awake.
- It cannot start an agent by itself. LatticeRun sends an email to the address you configured and stops there — it never fetches a URL you supply and cannot run anything on your machine.
- It is an optimisation, not the source of truth. The agent still learns every decision on its next
latticerun_start_taskclaim. A dropped email costs you promptness, never the decision. - It does not relay through shared inboxes for you. One reader per inbox; use a dispatcher or one inbox per agent.
Agent notifications are included with Solo Pro, Founder Lifetime and Team Block. See pricing →