Majordomo Documentation
Majordomo is a fully autonomous AI email agent. It connects to your mailbox, reads incoming emails, decides whether to reply or escalate, and sends replies — all without a human in the loop.
Getting Started
From zero to an autonomous email agent in under five minutes.
-
Create an accountSign up at /app/#register. You'll receive a welcome email and 10 free replies to try the platform immediately. No credit card required.
-
Create an agent mailboxClick Create Agent on the dashboard. Choose a handle (e.g.
support) and your agent email will besupport@agents.usemajordomo.com. Alternatively, connect your own mailbox via IMAP/SMTP. -
Write your personaDescribe who your agent is, what it knows, and how it should behave. This is the system prompt the LLM receives. Example: "You are Alex, the customer support agent for Acme Corp. Reply concisely to customer enquiries about orders, refunds, and shipping. Never discuss competitor products."
-
Set escalation triggers (optional)Enter plain-language conditions for emails that should be forwarded to you rather than auto-replied. Example: "Legal threats or compliance requests", "Refund requests over $500".
-
Test your personaUse the Test my persona button to generate 5 sample customer emails and see exactly how your agent would reply — before any real email arrives.
-
Send emails to your agentForward your inbox, publish the agent address, or start routing emails to it. The agent polls for new mail and replies automatically.
Hosted Mailbox
The simplest way to get started. Majordomo creates a dedicated mailbox for your agent at <botname>@agents.usemajordomo.com. No external email provider required.
Requirements
- Botname must be alphanumeric and may contain dashes (e.g.
support,alex-agent). - The address will be
<botname>@agents.usemajordomo.com. - You set a password at creation time; it is encrypted at rest.
Capabilities exclusive to hosted mailboxes
- Reply content retrieval — the dashboard can fetch and display the actual body of sent replies from the IMAP Sent folder.
Hosted mailboxes are the recommended starting point. You can add a custom-domain alias later via your DNS provider by pointing an MX record or SMTP relay to the agent address.
External Mailbox (IMAP / SMTP)
Connect any existing email account to Majordomo using standard IMAP and SMTP credentials. Works with Gmail (App Password), Outlook, Fastmail, Zoho, Proton Bridge, and most other providers.
Required fields
| Field | Example | Notes |
|---|---|---|
email_address | support@acme.com | The address the agent will read and reply from. |
imap_host | imap.gmail.com | Auto-discovered via DNS SRV if available. |
imap_port | 993 | Standard TLS port. |
smtp_host | smtp.gmail.com | |
smtp_port | 465 | SSL port. 587 (STARTTLS) also supported. |
username | support@acme.com | Usually the same as the email address. |
password_or_token | abcd efgh ijkl mnop | App password or OAuth token. Encrypted at rest with Fernet. |
DNS Auto-Discovery
When you enter an email address in the wizard, Majordomo queries DNS SRV records for _imap._tcp.<domain> and _submission._tcp.<domain> (RFC 6186) to pre-fill IMAP and SMTP settings automatically. You can override any field manually.
For Gmail, you must use an App Password, not your regular Google account password. Enable 2FA first, then generate an app password under your Google Account settings.
Batch Import (CSV)
Agencies and power users can create multiple agent mailboxes at once by uploading a CSV file. The dashboard wizard includes a batch mode (click Advanced then select Batch CSV).
CSV format
Two row types are supported and can be mixed in the same file:
Hosted mailbox row
agent_name,password
support,S3cretPass!
sales,AnotherP4ss
External IMAP/SMTP row
email,username,password,imap_host,imap_port,smtp_host,smtp_port
alex@acme.com,alex@acme.com,apppassword,imap.acme.com,993,smtp.acme.com,465
- Maximum 100 rows per upload.
- Rows are processed sequentially; a progress bar shows completion.
- Failures on individual rows do not stop the batch — errors are shown inline per row.
→ Import mailboxes via CSV in the dashboard (Create Agent → Advanced)
Mailbox Status Lifecycle
| Status | Meaning | Agent polls? |
|---|---|---|
active | Running normally. Agent polls and replies. | Yes |
inactive | IMAP login failed (wrong credentials or connectivity). Update connection settings to re-activate. | No |
pending_billing | Reply quota exhausted. Upgrade or purchase credits to resume. | No |
error | Unexpected processing error. Check the activity log for details. | No |
deleted | Disconnected by the user. The record is retained for audit purposes. | No |
When a mailbox enters inactive status due to an IMAP login failure, you will see an error badge on the dashboard. Update the credentials under Connection Settings to restore service — the status will return to active automatically on the next successful connection.
Persona & Tone
The persona is the most important configuration for your agent. It is passed to the LLM as a system message and defines the agent's entire behavior.
What to include in a persona
- Identity — Name, role, company. "You are Maya, customer success lead at Bright Software."
- Knowledge — What the agent knows: product details, FAQ answers, pricing, policies.
- Tone — How the agent communicates: formal, warm, brief, technical.
- Constraints — What the agent should NOT do: mention competitors, commit to timelines, discuss internal systems.
- Special instructions — When to ask for more information, how to handle attachments, language preferences.
Example persona
You are Alex, the customer support agent for Acme Corp.
Your job is to answer questions about orders, shipping, returns, and our product
catalog. Keep replies short and professional — no more than 3 paragraphs.
Company policies:
- Returns accepted within 30 days of delivery, unused items only.
- Standard shipping takes 3–5 business days. Express available at checkout.
- Refunds are processed within 7 business days.
Never discuss competitor products. If a customer reports a billing dispute over
$500, respond with "I'm escalating this to our billing team" and output NO_ACTION.
Tone field
The Tone field is a short descriptor (e.g. formal, warm and concise, technical) that is appended to the persona prompt. You can achieve the same by including tone instructions in the persona text itself.
Rules field
An additional plain-text rules field that is appended after the persona. Use it for quick operational constraints without rewriting the full persona.
Token limit
Persona text is limited to 2,000 tokens (measured with the cl100k_base tokenizer). The API will reject updates that exceed this limit. If you need a longer context, use the Document Context feature to inject reference material dynamically.
Persona history
Every time you update a mailbox's persona, the previous version is committed to a git repository on the server (WORKING_DIR/persona_history/<email>/). This provides a full audit trail of persona changes over time.
Escalation Triggers
Escalation triggers are plain-language conditions that tell the agent when to alert you instead of (or in addition to) replying autonomously. The LLM semantically evaluates each incoming email against your defined triggers — no keyword matching required.
What happens on escalation
-
Email is flaggedThe original email is marked
\Flagged $Importantin your IMAP inbox so it visually stands out. -
Tentative reply is generatedThe LLM generates a draft reply showing what the agent would have said — for your reference.
-
Notification email sent to youYou receive an email at your account address with subject
[Majordomo] Escalation: <original subject>containing: sender, original message, and the tentative reply. -
No reply sent to the original senderThe agent takes no further action. You decide how to respond.
Example triggers
- Legal threats, lawsuits, or compliance requests
- Refund requests over $500
- Media inquiries or press questions
- Angry or abusive language from the sender
- Requests for custom contract terms or enterprise pricing
Configuring triggers
Enter one trigger per line in the wizard, or a comma-separated list in the mailbox config view. You can add, edit, or remove triggers at any time — changes take effect on the next polling cycle.
Escalation is evaluated before reply generation. An escalated email consumes no reply credits from your quota.
Draft Mode
By default the agent sends replies automatically (Auto-reply mode). Switching to Draft mode makes the agent save its replies to your IMAP Drafts folder instead of sending them. You review and send each draft manually.
| Mode | Value | Behavior |
|---|---|---|
| Auto-reply | draft_mode = 0 |
Reply sent via SMTP immediately. Copied to Sent folder via IMAP APPEND. |
| Draft | draft_mode = 1 |
Reply saved to IMAP Drafts with the \Draft flag. No email is sent. |
Draft mode is useful when you're still tuning your persona and want to review AI-generated replies before they reach customers. Once you're confident, switch to Auto-reply mode to go fully hands-off. Draft mode still consumes one reply credit per draft.
NO_ACTION / DISCARD Signal
You can instruct the agent to deliberately do nothing for certain email types. If the LLM outputs the literal string NO_ACTION (or its synonym DISCARD) as its reply, the agent records a no_action log entry and sends nothing. The email is not marked as read, escalated, or replied to.
When to use it
- Newsletter and digest emails you can't avoid receiving.
- Internal automated notifications you want the agent to skip.
- Conditional logic: handle only English emails, skip all others.
- High-value escalation fallback: when in doubt, output NO_ACTION instead of a wrong reply.
How to configure it
Add instructions to your persona. For example:
If the email is a newsletter, automated digest, marketing email, or social
notification, output exactly: NO_ACTION
NO_ACTION (or DISCARD) must be the entire LLM output, not embedded in a sentence. The agent checks for an exact match after trimming whitespace.
→ Add NO_ACTION instructions to your persona in the dashboard
Reply-to-All
Majordomo always performs a reply-to-all when sending autonomous replies. This means the agent preserves the full recipient context of the original email thread rather than replying only to the sender.
How it works
When the agent processes an incoming email it inspects the To and CC headers of that email. The outgoing reply is addressed as follows:
- To — the original sender (
Fromaddress of the incoming email). - CC — every address that appeared in the original
ToorCCheaders, excluding the agent's own mailbox address (to avoid self-loop) and the original sender (already inTo).
All CC recipients are also included in the SMTP envelope so they actually receive the message.
Example
Original email received by the agent:
From: alice@example.com
To: support@agents.usemajordomo.com, bob@example.com
CC: carol@example.com
Agent reply headers:
From: support@agents.usemajordomo.com
To: alice@example.com
CC: bob@example.com, carol@example.com
Duplicate addresses (same address in both To and CC) are deduplicated automatically. The comparison is case-insensitive.
Document Context (RAG)
The Document Context feature allows the agent to dynamically fetch and inject relevant documentation into its replies. It is a lightweight Retrieval-Augmented Generation (RAG) system that works over HTTP.
Document context is configured per mailbox — each mailbox can have its own document list, or none at all. Configuration is set in the Agent Rules section of the mailbox settings in the dashboard, or via the API.
How it works
-
Define documents for your mailboxIn your mailbox settings (Agent Rules tab), provide either an inline JSON array of document objects or a URL that serves such an array. Each document has a
name,description, andurl. -
LLM selects relevant documentsFor each incoming email, the LLM is first asked to select which document names are relevant based on the email's subject and body.
-
Documents fetched and injectedThe agent fetches the URLs of selected documents via HTTP (
User-Agent: Majordomo-Agent/1.0) and injects the content into the reply prompt as a reference section. -
Reply generated with contextThe LLM generates a reply using both the persona and the fetched document content.
Configuration formats
There are two ways to configure documents for a mailbox:
Option A — Inline JSON array
Paste a JSON array of document objects directly into the Document Context (RAG) field:
[
{
"name": "shipping_policy",
"description": "Shipping times, costs, and carrier information",
"url": "https://acme.com/policies/shipping.txt"
},
{
"name": "return_policy",
"description": "Return and refund process",
"url": "https://acme.com/policies/returns.txt"
}
]
Option B — Manifest URL
Enter a single HTTPS URL that returns a JSON array in the same format as above. The agent fetches this URL at runtime whenever a document is needed:
https://acme.com/majordomo-docs.json
The URL must respond with a JSON array. This is useful when you want to manage your document catalog centrally and have multiple mailboxes or agents pick it up automatically.
Documents are fetched fresh on every relevant email. This means your agent always has the latest version of your policies without requiring a configuration update. Serve documents as plain text or Markdown for best results.
Field reference
| Field | Required | Description |
|---|---|---|
name | Yes | Short unique identifier used by the LLM to select this document. |
description | Yes | Human-readable description shown to the LLM as a hint for relevance selection. |
url | Yes | HTTP(S) URL of the document content (plain text or Markdown). Fetched per-email. |
PDF Attachments
When an incoming email contains PDF attachments, the agent automatically extracts their text content and makes it available to the LLM alongside the email body. This allows the agent to reason about and respond to documents sent by customers — invoices, contracts, reports, etc. — without any extra configuration.
How it works
- The agent walks the MIME tree of each incoming message looking for
application/pdfparts or parts whose filename ends in.pdf. - Text is extracted with PyMuPDF (
fitz). Only the embedded text layer is read; scanned PDFs without OCR will not yield useful content. - Each attachment is appended to the email body under a clearly labelled separator:
--- Attachment: report.pdf ---
(extracted text content of the PDF)
Truncation
To keep prompts within a reasonable size, each PDF is truncated to approximately 20 pages of text (~80,000 characters). If a PDF is cut short, a notice is appended:
[PDF TRUNCATED — showing first ~20 pages]The 20-page limit applies per attachment. Emails with multiple PDFs each receive their own 80,000-character budget. The full extracted text (up to the limit) is sent to the LLM in the same prompt as the email body — no extra quota is consumed.
Limitations
- Scanned PDFs — image-only PDFs without an embedded text layer yield no content. The agent will still reply, but based only on the email body text.
- Encrypted PDFs — password-protected files cannot be extracted. The attachment is silently skipped and the error is recorded in the agent log.
- Large files — very large PDFs are truncated at the 20-page limit. For best results, send focused, concise documents.
Poll Interval
The agent polls each mailbox for new (UNSEEN) emails on a configurable schedule.
| Option | Description |
|---|---|
| Every minute | Near-real-time. Suitable for live customer support. |
| Every hour | Good balance for most use cases. |
| Every day | Low-volume or non-urgent inboxes. |
| Custom (N hours) | Enter any interval in whole hours. |
The poll interval affects response latency. For customer support scenarios, use Every minute to maximize response speed. The agent only consumes API calls when new, unread emails are found.
Activity Log
The activity log records every action the agent takes — replies sent, emails escalated, messages skipped, and errors encountered. Email content is never stored; only metadata is logged.
Log entry fields
| Field | Description |
|---|---|
action | The action taken (see table below). |
recipient | The email address of the original sender. |
reason | A short description of why this action was taken (e.g. escalation trigger name). |
timestamp | UTC timestamp of the action. |
Action types
| Action | Meaning | Consumes quota? |
|---|---|---|
replied | Agent sent a reply via SMTP. | Yes |
drafted | Agent saved a draft (Draft mode). | Yes |
escalated | Email matched an escalation trigger; notification sent to owner. | No |
no_action | LLM returned NO_ACTION signal. | No |
tested_persona | Persona test was run from the dashboard. | Yes |
error | An unexpected error occurred during processing. | No |
Viewing reply content
For hosted @agents.usemajordomo.com mailboxes, the dashboard can retrieve and display the full body of any replied entry by fetching it from the IMAP Sent folder. Click the View action on an activity row to open the reply content.
Pagination
The activity log is paginated. The default page size is 20 entries. Use the API directly for programmatic access with custom page sizes.
Stats & Metrics
The dashboard displays three summary metrics for each mailbox:
Emails Handled
Total count of replied + drafted + tested_persona actions.
Remaining Credits
Free replies remaining + remaining subscription or purchased credits.
Escalated
Count of emails that matched an escalation trigger and were forwarded to the owner.
Test My Persona
The Test my persona feature lets you preview your agent's behavior before real emails arrive. The system generates 5 realistic sample customer emails based on your persona and shows the agent's replies side by side.
How it works
- Click Test my persona in the mailbox config view.
- The server uses your current persona to generate 5 diverse sample customer emails, then generates a reply for each.
- Results are displayed as an expandable email/reply pair grid.
- Previous test runs are saved in your browser's
localStoragefor comparison. - Each test run is logged as a
tested_personaaction and consumes one reply credit.
Run a persona test after every significant persona change. It's the fastest way to spot unexpected tone, incorrect facts, or missing constraints before they affect real customers.
Persona testing is disabled while a mailbox is in pending_billing status. Purchase credits to re-enable it.
Plans & Pricing
Free
10 reply credits included. No credit card required. Full feature access — persona, escalation, test mode, all mailbox types.
Pro — $9.99 / month
500 reply credits per billing period. Cancel anytime. Recurring credits reset each cycle. Connect unlimited mailboxes at the per-mailbox rate.
Credit Packs
One-time purchase of 500 additional reply credits. Never expire. Stack on top of free or subscription credits.
Agency pricing example
An agency managing 20 client inboxes pays $9.99/mailbox/month = $199.80/month. Each mailbox is fully independent with its own persona, rules, activity log, and billing quota.
Quota & Credits
Reply credits are deducted from your account each time the agent sends a reply, saves a draft, or runs a persona test.
How quota is calculated
Your remaining credits are calculated as:
free_credits (10) + purchased_credits + subscription_credits − total_replies_sent
What happens when quota runs out
- If you have an active subscription, credits are renewed at the next billing date.
- If you have no subscription, all your mailboxes are set to
pending_billingstatus. - You receive a notification email prompting you to purchase more credits.
- Mailboxes resume automatically once credits are purchased or subscription is reactivated.
Escalated emails and no_action responses do not consume credits. Only sent replies, saved drafts, and persona test runs are charged.
One-Time Credit Packs
Need more replies without committing to a subscription? Purchase a one-time credit pack. Credits are added immediately to your account after payment and never expire.
- Available for purchase from the Settings → Billing view.
- Works alongside a subscription — subscription and purchased credits are pooled together.
- Payment is processed via Stripe. Majordomo never stores payment card details.
- Stripe checkout sessions are idempotent — accidental double-clicks or network retries will not result in double-charging.
Privacy by Design
Majordomo is built with email privacy as a first-class concern, not an afterthought.
In-Memory Processing
Emails are loaded from IMAP, processed to generate a reply, and immediately discarded. Email body content is never written to disk or stored in the database.
EU Hosting
All infrastructure runs in European data centers. No transatlantic data transfer. GDPR Article 46 compliant by location.
No Training Use
Your email content is never used for model training, shared with third parties, or retained after the session ends.
Right to Erasure
Delete your account at any time. All user data, mailbox configurations, and activity logs are permanently removed.
What is stored
- Account data — Email address, hashed password (bcrypt), Stripe customer ID, subscription status.
- Mailbox config — IMAP/SMTP connection details (password Fernet-encrypted), persona, rules, escalation triggers.
- Activity log metadata — Action type, recipient address, timestamp, reason. No email content.
GDPR & Right to Erasure
Majordomo supports the GDPR Right to Erasure (Article 17). You can permanently delete your account and all associated data at any time.
How to delete your account
- Go to Settings in the dashboard.
- Scroll to the Danger Zone section.
- Click Delete My Account.
- Confirm the action in the dialog.
This action permanently deletes: your user account, all mailbox configurations, all activity logs, and all associated Stripe data references. The deletion is irreversible.
Data Processing Agreement
For business customers requiring a formal DPA, contact us at contact@agents.usemajordomo.com.
Credential Security
Email passwords
IMAP/SMTP passwords and app tokens are encrypted at rest using Fernet symmetric encryption (AES-128-CBC + HMAC-SHA256) from the Python cryptography library. The encryption key is stored in the server environment and never in the database.
Account passwords
User account passwords are hashed with bcrypt before storage. Plain-text passwords are never persisted or logged.
Session tokens
Authentication uses JWT tokens (HS256, 7-day TTL) stored in the browser's localStorage. Tokens are validated on every protected API request.
What we never log
- Email body content.
- IMAP/SMTP credentials (plain text).
- API keys or OAuth tokens.
- JWT tokens or session secrets.
Unsubscribe
If you receive an unwanted email from a Majordomo agent and wish to opt out, you can unsubscribe at any time. Unsubscribed addresses are added to a global suppression list; Majordomo agents will not send further emails to addresses on this list.
- Visit /unsubscribe.html and submit your email address.
- Or use the unsubscribe link included in the footer of every agent-sent email.
Authentication
All API endpoints except those listed below require a Bearer JWT token in the Authorization header.
Authorization: Bearer <your_jwt_token>
Public endpoints (no token required)
POST /api/v1/auth/registerPOST /api/v1/auth/loginGET /api/v1/pricingGET /api/v1/email-autoconfigGET /api/healthPOST /api/v1/billing/webhook(Stripe; validated by signature)POST /api/v1/unsubscribe
Register
// Request
{
"email": "you@example.com",
"password": "YourSecurePassword",
"referral_data": { "utm_source": "twitter" } // optional
}
// Response 200
{
"id": "uuid",
"email": "you@example.com",
"created_at": "2025-01-01T12:00:00Z"
}
Login
// Request
{ "email": "you@example.com", "password": "YourSecurePassword" }
// Response 200
{
"user": { "id": "...", "email": "..." },
"token": "eyJhbGc..."
}
Current user
Returns the authenticated user's profile, including subscription status and remaining reply credits.
Delete account
Permanently deletes the user account, all mailboxes, and all activity logs. Irreversible.
Mailboxes API
Update mailbox config
{
"persona": "You are Maya...",
"tone": "warm and concise",
"rules": "Always sign off with your name.",
"escalation_triggers": ["Legal threats", "Refunds over $500"],
"draft_mode": 0,
"poll_interval_in_minutes": 60
}
Activity API
Activity list query params
| Param | Default | Description |
|---|---|---|
page | 1 | Page number (1-indexed). |
size | 20 | Results per page. |
Activity list response
{
"items": [
{
"id": "uuid",
"action": "replied",
"recipient": "customer@example.com",
"reason": "Product availability question",
"timestamp": "2025-03-20T14:22:00Z"
}
],
"total": 142,
"page": 1,
"size": 20,
"pages": 8
}
Billing API
Create checkout session
// Subscription
{ "checkout_type": "subscription" }
// One-time credit pack
{ "checkout_type": "one_time" }
// Response
{ "url": "https://checkout.stripe.com/..." }
Utility Endpoints
Email autoconfig
// Response (example: Gmail)
{
"imap_host": "imap.gmail.com",
"imap_port": 993,
"smtp_host": "smtp.gmail.com",
"smtp_port": 465
}
Self-Hosting Overview
Majordomo is fully self-hostable for teams with strict data residency or security requirements. The entire stack — API, agent process, and frontend — can run on your own infrastructure.
Components
| Component | Description |
|---|---|
__init__.py | FastAPI backend — single file, all REST endpoints. Run with Uvicorn. |
agent.py | Background agent process. Polls mailboxes, generates and sends replies. Run separately from the API. |
app/index.html | SPA frontend. Can be served as static files by Nginx or the FastAPI static files middleware. |
| PostgreSQL | Required. Connection via DATABASE_URL env var. |
| Poste.io (optional) | Required only if you want to create hosted mailboxes at your own domain. The API calls docker exec into the container to provision mailboxes. |
Minimal startup
# 1. Start the API
uvicorn __init__:app --host 0.0.0.0 --port 8000
# 2. Start the agent (separate process)
python agent.py --config config.py
Live reload
The agent process watches agent.py for changes on disk and automatically restarts itself via os.execve when the file is modified. No process manager required for development.
Config Reference
Backend environment variables
| Variable | Default | Description |
|---|---|---|
DATABASE_URL | — | PostgreSQL connection string. Required. |
JWT_SECRET | Fallback string | JWT signing key. Set to a strong random value in production. |
ENCRYPTION_KEY | Fallback key | Fernet key for encrypting stored IMAP/SMTP passwords. |
STRIPE_API_KEY | Keyring fallback | Stripe secret API key. |
STRIPE_WEBHOOK_SECRET | Keyring fallback | Stripe webhook endpoint secret for signature validation. |
STRIPE_PRICE_ID_SUBSCRIPTION | — | Stripe Price ID for the monthly subscription. |
STRIPE_PRICE_ID_ONE_TIME | price_one_time_dummy | Stripe Price ID for one-time credit packs. |
NB_FREE_REPLIES | 10 | Number of reply credits on the free tier. |
PERSONA_MAX_LENGTH_TOKENS | 2000 | Maximum persona size in tokens (cl100k_base). |
NB_ONE_TIME_REPLIES_BOUGHT_WITH_PAYMENT | 500 | Credits added per one-time purchase. |
WORKING_DIR | — | Directory for persona history git repo and unsubscribe list. Required. |
DEFAULT_MONITORING_EMAIL | — | BCC address for all outgoing agent replies (for monitoring). |
Agent config.py variables
| Variable | Default | Description |
|---|---|---|
LLM_MODEL | — | LLM model identifier (e.g. gpt-4o-mini). |
ANTHROPIC_AUTH_TOKEN | — | LLM API key. |
LLM_X_TITLE | — | Optional X-Title HTTP header for LLM API requests. |
LLM_HTTP_REFERER | — | Optional Http-Referer header for LLM API requests. |
POLL_INTERVAL_SECONDS | — | Main loop sleep interval in seconds. |
MAX_TOKENS | 1000 | Maximum LLM output tokens per reply. |
MAX_THREAD | 10 | Maximum number of historical thread messages to include in context. |
DOCUMENTS | None | Global fallback list of document objects for RAG context injection (self-hosted). Per-mailbox documents configured via the dashboard or API take precedence. See Document Context (RAG). |