Architecting Safe AI Workflows: Why One Developer Denied His Agent a Send Button
Om Davra demonstrates how Model Context Protocol (MCP) agents can safely automate follow-up email drafts without risk by strictly limiting tool capabilities in code.

Automating client outreach often presents an uncomfortable trade-off between productivity and operational risk. Handing an autonomous AI agent full access to an email inbox risks fabricated context, hallucinations, and damaged professional relationships. To address this friction, developer Om Davra documented an architectural pattern using a custom Model Context Protocol (MCP) server that drafts weekday follow-up emails without possessing the capability to actually send them.
Rather than relying on automated dispatch, the system produces native email draft files every weekday morning. The user reviews the generated copy, makes quick adjustments, and clicks send manually. The implementation demonstrates a practical balance: letting an LLM eliminate the blank-page problem while maintaining human-in-the-loop verification on all outbound communication.
Architectural Safety by Omission
A central premise of Davra’s design is enforcing guardrails at the tool level rather than inside the system prompt. While prompts can instruct a model not to transmit an email without confirmation, LLMs can still fail or misunderstand complex conditions. As Davra notes, a prompt is merely a request, whereas an absent tool serves as an absolute barrier.
To enforce this boundary, the underlying MCP server exposes a file-creation tool called save_draft rather than an SMTP transmission tool. When Claude runs through the workflow, it passes a lead_id, subject line, and body text. The server inspects the local SQLite database, retrieves the recipient's address, constructs a standard .eml file using Python’s email.message.EmailMessage, and sets the X-Unsent: 1 email header. This header signals clients like Microsoft Outlook to open the file as an editable draft rather than a received message, while Apple Mail users can achieve the same via the "Send Again" option.
Additionally, preventing the LLM from supplying the recipient address directly eliminates hallucinated email addresses or accidental cross-contact between leads. The model only handles content generation based on prior lead notes, while the database maps the verified target.
The Automation Stack and Scheduling
The implementation links SQLite, an MCP server (leads_server.py), and an orchestration script named morning.py. The runner script relies on LangChain's MultiServerMCPClient and create_agent to invoke the Claude Sonnet 3.5 model (anthropic:claude-sonnet-5-5).
To ensure portability, the script initializes the MCP server process dynamically via sys.executable, running the server within the same virtual environment as the runner. Davra configured the script to execute automatically via cron every weekday at 9:00 AM (0 9 * * 1-5), writing its output to a log file.
Davra highlighted several operational hurdles common to local cron deployments. Because cron executes in a minimal environment that does not inherit shell variables, the runner script must explicitly load environment variables from a .env file via python-dotenv. On macOS, cron also requires Full Disk Access within system settings to read protected folders. Furthermore, if a machine is asleep at the scheduled time, cron misses the execution entirely—prompting the alternative use of launchd or deployment to a persistent cloud instance.
What it means for developers
Davra's architecture provides a clear blueprint for engineering safe, pragmatic agentic workflows:
- Hard Boundaries Over Soft Prompts: When designing agents for sensitive tasks, omit dangerous capabilities from the tool schema altogether. Removing the "send" or "delete" capability entirely ensures deterministic safety that prompt engineering cannot guarantee.
- ID-Based Tool Interfaces: Shielding models from directly handling critical data points (such as target recipient addresses) prevents misattribution. Passing database IDs forces tools to resolve targets against structured, trusted records.
- Leveraging Standard Formats: Integrating with standard formats like
.emland using existing client conventions likeX-Unsentbridges terminal automation and native desktop user interfaces without complex API integrations. - Context Quality Dictates Output: As Davra observed, low-context database entries like "interested" produce generic follow-ups, whereas specific notes like "wants it live before Diwali" yield relevant drafts. System prompts should explicitly skip records lacking substantive notes.
When building similar workflows with tool-calling models like Claude, developers can try top AI models cheaply through one API at https://apixoai.online, simplifying integration across different providers.
Ultimately, the pattern shifts the user's workload from authoring to editing. By tackling the friction of initial composition while leaving delivery strictly in human hands, developers can scale operational tasks without sacrificing trust.
Source: My AI Drafts My Follow-Up Emails Every Morning. I Still Press Send. — Towards AI. Written by the Apixo team from that report.
One key for Claude, GPT, GLM, DeepSeek and more. Pay per token with crypto.
Get your API key

