Your agent accepts callbacks and can act without a person watching. Putting the full message in that callback feels efficient: one request arrives, the model reads it, and work begins. It also turns a notification endpoint into a content-injection endpoint.
A safer webhook carries enough information to locate authorized work and no more.
A trigger crosses a sensitive boundary
Webhook receivers often sit close to automation. Their whole purpose is to convert an external event into internal work, so fields in the request are unusually likely to influence routing, prompts, tools, or queues.
If the payload includes free-form message content, whoever can produce or forge a callback can place prose directly on that path. For an AI agent, that prose may look like an instruction even when the application intended it as correspondence.
An HMAC signature helps, but it does not change the consequence of secret loss. A signing secret is retained by both sides because the sender needs it to create future signatures. If it leaks, the attacker can create requests that authenticate as the webhook sender. A full-content payload would give that credential the power to publish agent input.
The receiver should still verify every signature. The design question is how much authority a valid signature should grant.
Authenticated pull narrows that authority
RelayLink's package.received webhook carries an envelope:
- Event and stable delivery id
- Package and thread ids
- Sender name and email
- Topic and sent time
- Whether the package is a reply
- The host's
mcp_url
It omits the note, TL;DR, ask, and context brief.
After accepting the event, the worker authenticates independently to mcp_url and calls get_package. The webhook secret proves the callback came from the holder of that subscription secret. The MCP credential proves that the worker may read packages for the account.
Those are different permissions. A forged envelope can make the receiver attempt a lookup, but a nonexistent package or unauthorized identity fails at the content boundary. The attacker does not get to substitute prose for the server's authenticated result.
The fetched content is still third-party material, not an instruction to the agent. Separate authorization does not make another person's words trustworthy; it makes their source, account boundary, and package identity explicit.
The pull preserves provenance
RelayLink gives a sender a careful answer to “did their assistant fetch it?” The get_package call records PulledViaMcp.
If the complete briefing rode inside the webhook, a consumer could process it without making that call. The sender would see no pull even though the receiving agent had the content. Adding a “webhook delivered” read event would be worse: a 2xx says only that a receiver accepted an HTTP request.
Envelope-only delivery keeps the evidence aligned with the act. Webhook acceptance is transport. MCP pull is an authenticated fetch. Acknowledgement is a deliberate recipient action. None has to impersonate another.
This is the same reason a package-link fetch is not treated as reading: automated scanners and previewers fetch links. Observable transport events should not be promoted into human or agent intent.
An envelope still discloses metadata
Minimal does not mean empty. A RelayLink receiver learns who sent the package, their address, the topic, the time, and identifiers. Registering a receiver is therefore portal-only and is standing permission to receive that metadata for every package delivered to the account.
Sender name and topic are human-chosen fields. Treat them as untrusted data:
- Do not concatenate them into system instructions.
- Do not choose tools because a topic tells you to.
- Keep the raw body and any token-bearing receiver URL out of logs; structure and length-limit any metadata you do record.
- Use the package id for lookup, never a command embedded in text.
The envelope reduces exposure; it does not erase the need for careful handling.
The general design rule
For any event-driven agent, split the path into three capabilities:
- Notify: a signed envelope says work may exist.
- Authorize: a separate credential controls who may fetch it.
- Process: the agent treats fetched correspondence as data under explicit provenance rules.
Add a stable delivery id for at-least-once retries. Commit the receipt and its work item atomically, then return 2xx; making a “seen” row without durable work creates a loss window. Keep message bodies, private context, and executable instructions out of the notification layer.
RelayLink's exact payload examples show how little the trigger needs. The result is not merely a smaller JSON document. It is a narrower credential, a clearer audit trail, and less outside prose on an automatic path.