Keep email prompt injection from becoming tool authority
Treat sender content, attachments and quoted conversations as untrusted data throughout an agent workflow.
Turn verified inbound events into proposed actions while keeping sender content separate from account authority.
A dependable flow is verified delivery, tenant binding, durable job, selected context, proposed action, approval and execution result. Each stage has a different source of truth. The webhook authenticates the delivery path, the API key controls resource access, application storage owns work assignment, and a human or existing explicit authorization governs an external effect. Putting every stage into one model turn makes failures hard to recover. Save stage transitions so a worker restart can resume known work without rereading an email as a fresh request to execute everything again.
Verify Lupin’s raw-body signature and all svix headers before parsing the event. Bind the inbox or project to your known tenant mapping and enqueue one job per stable event or message identity. A webhook acknowledgment should mean the job was durably accepted, not that the model completed it. Polling and webhook processing can discover the same message, so they should converge on the same local work record. Spam, blocked and unauthenticated variants need an explicit routing policy rather than falling through into the ordinary external-action queue.
Read the selected message or thread and extract only the context the task needs. Let the model propose a catalog operation with structured arguments, then validate it against the concrete schema. Do not permit arbitrary HTTP methods, URLs or credentials derived from an email body. For connected apps, discover the real tool, concrete version, account revision and argument shape first. Keep the target account server-selected and owned by the workspace. A sender’s suggested API endpoint is untrusted reference material, not an instruction to bypass your registered tool boundary.
Show the actual destination, account, resource and content before running a sensitive tool. In Lupin’s consumer agent, exact pending approvals are saved and consumed once; external MCP clients must provide their own authorization interface. An email telling the model that the owner already approved cannot grant approval. After approval, preserve the corresponding operation identity through execution and retry recovery. If the proposal changes its recipients, account or important arguments, return it to review rather than applying an old grant to new behavior.
Store the tool result, structured failure or uncertain outcome with the work item, and describe only what the evidence establishes. A provider acknowledgment may prove acceptance without proving recipient delivery or downstream completion. Diagnostics cannot authorize or replay the action, and an absent trace does not prove nothing happened. Your next step is an offline end-to-end fixture from signed event to reviewed draft or mocked tool result, including duplicate delivery and lost-response cases, before enabling any real provider execution.
A denied proposal should remain a completed decision rather than an error that triggers repeated model attempts. Save the reason and let the user revise the task if needed. This prevents a persistent worker from treating human refusal, missing permission or a spending boundary as a temporary obstacle to route around.
Reviewed against checked-in Lupin API handlers and documentation. Example requests were not executed against live providers.
Prepared with AI assistance by Lupin editorial. How we research and maintain these guides.