✉️ Email was built for humans. MailOS is built for AI agents to communicate on behalf of humans — reading, negotiating, and reaching agreements over ordinary email, and only interrupting the owner when their judgment is actually needed.
Think of MailOS as an operating system that sits on top of a mailbox: instead of you opening your inbox and manually triaging, replying, and following up, a team of specialized agents does that work continuously in the background, escalating to you only for the handful of decisions that actually need a human.
MailOS connects to a mailbox, listens 24/7, and gets straight to work:
- 🛡️ Guards against phishing & prompt injection
- 🏷️ Classifies and responds to incoming mail
- 🤝 Negotiates autonomously within a policy you set
- 📰 Learns from newsletters
- 💡 Surfaces business opportunities hiding in your inbox
⚡ Powered end-to-end by Qwen. 📄 MIT licensed · 🧩 Designed to be embedded into any application.
Handle high-volume customer inquiries automatically. MailOS classifies support tickets, drafts contextual replies, and only escalates complex issues to your team.
Customer email → Classification → Auto-draft reply → Human approval (if needed)
Examples:
- SaaS companies responding to pricing inquiries
- E-commerce handling order status questions
- B2B companies qualifying leads from inbound emails
Let MailOS negotiate on your behalf within policy bounds. Set max discount percentages, approval thresholds, and round limits — the AI handles the back-and-forth.
Examples:
- Negotiating bulk purchase discounts
- Renegotiating contract terms with vendors
- Scheduling meetings with suppliers across time zones
Automatically classify and route incoming business inquiries. MailOS identifies high-value opportunities and notifies the right team members.
Examples:
- Qualifying enterprise leads from demo requests
- Routing partnership inquiries to business development
- Escalating urgent sales opportunities immediately
Extract insights from industry newsletters automatically. MailOS reads, summarizes, and identifies trends across multiple sources.
Examples:
- Tracking competitor announcements
- Monitoring industry news for strategic insights
- Building a knowledge base from subscribe content
Embed MailOS into your application to give it email superpowers. Every email becomes a structured event your code can react to.
Integration Examples:
- CRM that auto-creates contacts from email signatures
- Project management tool that creates tasks from action items
- Helpdesk that auto-categorizes and routes tickets
// React to classified emails via API
const emails = await fetch('/emails?label=Customer&status=classified');
emails.forEach(email => {
// Your custom logic here
crm.createContact(email.from, email.classification);
});Extend the agent pipeline for your specific domain. Create specialized agents that plug into the same event bus.
Examples:
- Legal document classifier for law firms
- Invoice extractor for accounting automation
- Support ticket sentiment analyzer
Use the ingest endpoint to feed messages from any source into the pipeline — Slack, GitHub, WhatsApp, or custom webhooks.
curl -X POST http://localhost:4000/ingest \
-H "Authorization: Bearer $API_KEY" \
-d '{"from": "slack", "subject": "New support ticket", "text": "..."}'Query the API to build custom dashboards, reports, or integrate with business intelligence tools.
Examples:
- Customer sentiment trends over time
- Response time analytics
- Classification accuracy metrics
Stop drowning in email. MailOS archives newsletters, drafts replies to common questions, and only surfaces what actually needs your attention.
Examples:
- Freelancers managing client inquiries
- Consultants handling meeting requests
- Professionals triaging high-volume inboxes
Let MailOS handle the back-and-forth of scheduling. It checks your calendar and proposes times that work — no more "What time works for you?" email chains.
Examples:
- Scheduling client calls across time zones
- Coordinating interviews with candidates
- Managing recurring meeting requests
Guardian agent blocks malicious emails before they reach you. Heuristics catch known patterns; AI detects sophisticated attacks.
Examples:
- Blocking BEC (Business Email Compromise) attempts
- Filtering out AI-generated phishing attempts
- Protecting against prompt injection attacks
Every email you've sent or received becomes searchable memory. Ask questions and get answers based on your actual communication history.
# Natural language query
curl -X POST http://localhost:4000/ask \
-d '{"question": "What did John say about the Q4 budget?"}'- Patient inquiry triage (non-diagnostic)
- Appointment scheduling automation
- Insurance verification correspondence
- Client onboarding communication
- Document request automation
- Compliance notice handling
- Property inquiry responses
- Showing schedule coordination
- Document collection from buyers
- Student inquiry management
- Office hour scheduling
- Administrative communication automation
- Order status inquiries
- Return/exchange processing
- Vendor communication
npm install
cp .env.example .env
# ✍️ edit .env: set QWEN_API_KEY at minimum
npm startOpen http://localhost:4000 in your browser. 🎉 First run shows a one-time setup page to create your admin account — after that, it's a normal login.
- 🌐 Go to the Alibaba Cloud Model Studio console (DashScope): https://bailian.console.aliyun.com/
- 👤 Sign in with (or create) an Alibaba Cloud account.
- 🗝️ Open API-KEY Management and create a new key.
- 📋 Paste it into
.envasQWEN_API_KEY, or into Settings → Qwen provider in the running app — the latter takes effect immediately, no restart needed. ⚡
flowchart TD
A[📥 Message arrives via IMAP IDLE<br/>instant push, not polling] --> B{🛡️ Guardian<br/>heuristics + AI-assisted<br/>injection detection}
B -- 🚫 blocked --> X[❌ Stopped here]
B -- ✅ clean --> C[🏷️ Classification<br/>Newsletter · Meeting · Invoice<br/>Personal · Customer · Marketing<br/>Spam · Scam]
C --> D[📡 Event Bus<br/>publish / subscribe]
D --> E[🧠 Memory]
D --> F[📰 Newsletter Intelligence]
D --> G[💡 Opportunity]
D --> H[⚖️ Decision]
H --> I{Action}
I --> I1[🗄️ archive]
I --> I2[🔔 notify]
I --> I3[✍️ reply_draft]
I --> I4[🙈 ignore]
I --> I5[🙋 requires_human]
I3 --> J[🤝 Negotiation<br/>policy-gated · round-capped]
Every agent is independent and talks only through the internal event bus — publish/subscribe, never direct agent-to-agent calls. 🔌 The bus runs on real BullMQ-backed Redis queues when REDIS_URL is set, and an in-process equivalent otherwise — both paths run the identical pipeline.
| Agent | Responsibility |
|---|---|
| 🛡️ Guardian | Blocks phishing, malicious attachments, and prompt injection — heuristics first (instant, zero cost), then an AI-assisted semantic check for attempts no fixed pattern anticipated. Degrades to heuristics-only if the AI call fails; never depends on AI availability to keep working. |
| 🏷️ Classification | Multi-label classification with confidence scores. Bulk mail that doesn't cleanly fit a category (unsubscribe links, "view in browser" banners) falls back to Newsletter rather than a dead-end Uncategorized, so it still feeds the knowledge pipeline. |
| 🧠 Memory | Recency + importance + relevance retrieval (the same three-factor family as the Stanford "Generative Agents" memory-stream design), reinforcement on recall, and hierarchical consolidation into higher-level reflections. |
| 📰 Newsletter Intelligence | Reads newsletters, safely visits links/PDFs, extracts ideas/trends/stats, and detects when independent sources converge on the same topic. |
| 💡 Opportunity | Mines newsletter insights and customer emails for business opportunities and recurring pain points. |
| ⚖️ Decision | Assigns one of five actions with a confidence score and a plain-language reason. |
| 🤝 Negotiation | Autonomous multi-round negotiation, policy-gated (see below). |
📎 Connecting a mailbox is the only step — monitoring starts immediately via IMAP IDLE, and a bounded history sync runs automatically so MailOS has something to reason about from minute one, not just mail from that point forward.
Two mailboxes — or one MailOS-connected mailbox talking to any ordinary inbox — can carry out an entire negotiation without the owner reading a single intermediate message. 📭 No special protocol: MailOS negotiates in plain natural-language email, threaded via standard RFC 5322 headers, so it works with any correspondent's normal inbox.
🧭 The AI proposes, policy decides. Every autonomous reply is checked against a deterministic, code-enforced policy — max discount %, an approval threshold above a given amount, a confidence floor — before anything is sent. Two independent circuit breakers 🚦 stop a negotiation from running away: a hard round cap, and the policy/confidence gate. Either one hands the conversation to a human via webhook (Telegram, Slack, Discord, or any endpoint) instead of continuing.
The owner isn't consulted every round — that would defeat the point. MailOS only reaches out once, when something genuinely can't be resolved on its own. 🙋
🎯 Owner-initiated negotiation: define a goal, MailOS sends the opening move:
curl -X POST localhost:4000/negotiations -H "Content-Type: application/json" -d '{
"mailboxId": "...", "to": "seller@example.com",
"subject": "Purchasing your software license",
"intent": { "type": "purchase", "goal": "Buy a 50-seat license",
"constraints": { "maxPrice": 5000, "preferredPaymentTerms": "net-30" } }
}'📅 Calendar-aware meeting scheduling: for Meeting-classified mail, availability is checked deterministically against a mailbox's configured calendar (Settings → mailbox profile) — not guessed by the AI. The AI communicates the verified result, it doesn't invent it. ✅
📊 Efficiency, measured not claimed: every round records its real token usage (from Qwen's own API response) and wall-clock time. GET /negotiations/:id returns a computed efficiency block comparing autonomous handling against a stated single-agent baseline.
- ⚡ Real-time, not polled — IMAP IDLE (via
imapflow) means new mail is picked up the instant it arrives, no restart or manual sync required. - 🔁 Reconnects itself — both the database connection and every mailbox's IMAP connection retry with exponential backoff on a drop, at boot and mid-session.
- 💾 Embedded, durable storage (
@seald-io/nedb) — no separate database server to install, run, or lose. Scales to real MongoDB (MONGODB_URI) if you need multi-server horizontal scaling. - 📝 Full audit trail — every significant failure is logged with context and queryable at Settings → Recent errors.
- 🧭 Clear, actionable errors — a failed mailbox connection tells you exactly what's wrong, not a raw stack trace.
- 🔐 API key or session auth on every route. The browser UI uses a signed session cookie from username/password login; external clients use
API_KEYS. Neither is optional. - 🚫 Login lockout — 3 failed attempts blocks that IP+browser fingerprint for 15 minutes. Blocks live in
data/login-blocks.json, editable directly or via Settings → Login security. - 🐢 Rate limiting on every route, stricter on anything that sends real email or spends real AI tokens.
- 🔒 Encrypted credentials — mailbox passwords are AES-256-GCM encrypted before they're ever written to disk.
- 🧱 Content Security Policy enforced via Helmet, zero inline event handlers anywhere in the UI.
- ✅ Zero known vulnerabilities — every dependency runs on its latest maintained major version (
npm auditclean).
- 🖥️ Create the instance. In the Alibaba Cloud ECS console, launch an instance — Ubuntu 22.04 LTS, 2 vCPU / 4 GB RAM is comfortable for a single-instance deployment. Attach a public IP.
- 🔓 Open the security group. Allow inbound TCP on 22 (SSH) and 443/80 (or your chosen app port).
- 🔧 SSH in and install Node.js:
ssh root@<your-ecs-public-ip> curl -fsSL https://deb.nodesource.com/setup_22.x | bash - apt-get install -y nodejs git
- 📦 Get the code onto the server — clone your repo (recommended, since it powers the in-app update checker) or upload the zip:
git clone <your-repo-url> mailos && cd mailos npm install --omit=dev
- ⚙️ Configure environment:
cp .env.example .env nano .env # set QWEN_API_KEY, ENCRYPTION_KEY, JWT_SECRET, API_KEYS, NODE_ENV=production - ♻️ Run it under a process supervisor (required for auto-restart, including in-app updates):
npm install -g pm2 pm2 start src/index.js --name mailos pm2 save pm2 startup # follow the printed instructions so MailOS survives a reboot - 🔐 Put it behind Nginx + HTTPS (recommended so session cookies are sent over TLS):
apt-get install -y nginx certbot python3-certbot-nginx # point an Nginx server block's proxy_pass at http://127.0.0.1:4000 certbot --nginx -d your-domain.com - 🌍 Visit
https://your-domain.com, complete the first-run setup, and connect a mailbox.
📁 data/ (mailboxes, memory, negotiations) lives outside the git-tracked source, so git pull && npm install && pm2 restart mailos — or the in-app Update now button — never touches it. 🙌
- 📬 Multi-mailbox IMAP/SMTP connector, any provider, real-time IMAP IDLE
- 🛡️ Guardian: heuristic + AI-assisted phishing/injection/malware defense
- 🏷️ 8-label classification with a newsletter fallback for bulk mail
- 🧠 Recency+importance+relevance memory with hierarchical consolidation
- 🤝 Autonomous, policy-gated, round-capped negotiation
- 🎯 Owner-initiated negotiation (define a goal, MailOS sends the opening move)
- 📅 Calendar-aware meeting scheduling, deterministic availability checks
- 📰 Newsletter intelligence + cross-source trend detection
- 💡 Opportunity mining from newsletters and customer email
- 🧾 Mailbox profiles: calendar, priorities, location, freeform preferences, reference documents
- 💾 Data backup/export per mailbox or instance-wide, credentials always excluded
- 🔌 Full REST API, session or API-key auth, per-route rate limiting, login lockout
- 🌗 Light/dark themed web UI, mobile responsive
- 🛠️ Live-editable settings (Qwen key/model/endpoint, negotiation policy) — no restart
- 🔄 In-app update checker against GitHub releases, one-click update, data untouched
- 🗄️ Embedded zero-setup storage, optional MongoDB; embedded event bus, optional Redis/BullMQ
- 🧠 Memory export/import — export an agent's full memory stream (raw events + hierarchical reflections) to a file, and import it into a new instance for migration, staging, or handoff, with point-in-time snapshots for audit.
- 🕸️ Cross-mailbox trust graph — a local reputation score per contact, built from every past negotiation and correspondence across all threads and mailboxes, applied automatically at the policy level.
- 📞 Voice escalation bridge — when an email negotiation stalls, MailOS autonomously places an outbound voice call under the same policy guardrails, then writes the outcome back into the email thread.
- 💸 Agent-to-agent payments — letting one MailOS instance pay another to close a negotiated deal, gated behind strict, explicit, per-transaction owner-approved limits.
- 👥 Multi-user / team accounts — currently single-admin per instance.
- 🔗 More connectors — Slack, GitHub, Calendar, CRM, WhatsApp Business, all through the same
ConnectorInterfaceemail already implements. - 📈 Real vector index at scale — for memory/document search well beyond the embedded store's comfortable range.
- 🏋️ Load-tested concurrency — many simultaneous negotiations across many mailboxes.
src/
core/ EventBus, AgentBase, Orchestrator, ConnectorRegistry, Logger, topics
connectors/ ConnectorInterface, EmailConnector
providers/ ProviderInterface, QwenProvider, ProviderManager
repositories/ RepositoryInterface, NeDbRepository (default), MongoRepository (optional)
agents/ Guardian, Classification, Memory, NewsletterIntelligence, Opportunity, Decision, Negotiation, QA
services/ DashboardService, SettingsService, AuthService, LoginGuard, ErrorLogService, NotificationService
api/ Fastify server, security (auth), routes
utils/ security, vector/memoryScoring, calendarAvailability, emailThreading, retry, passwords
public/ Web UI — plain HTML/CSS/JS, no build step
- 🏗️ Create
src/connectors/YourConnector.jsextendingAgentBaseand implementingConnectorInterface(connect,disconnect,startMonitoring,sync,send). - 🔄 Normalize incoming payloads into the same shape
EmailConnector.ingest()uses and publish onto the event bus the same way. - 📝 Register it in
src/core/Orchestrator.js:this.connectors.register(new YourConnector()). - ✅ Every existing agent picks it up automatically — they only ever see the generic message shape, never the connector that produced it.
All endpoints require authentication. Two methods are supported:
| Method | Use Case |
|---|---|
| Session Cookie | Browser UI — login via /auth/login to get a signed cookie |
| API Key | External/programmatic clients — send as Authorization: Bearer <key> or x-api-key: <key> header |
Setting up API Keys:
Add to your .env file:
API_KEYS=key1,key2,key3Or set a single key:
API_KEYS=your-secret-api-keyThen use it in requests:
curl -H "Authorization: Bearer your-secret-api-key" http://localhost:4000/emails
# or
curl -H "x-api-key: your-secret-api-key" http://localhost:4000/emails| Method | Endpoint | Description |
|---|---|---|
GET |
/auth/status |
Check if admin account exists (public) |
POST |
/auth/register |
Create admin account (first-run only) |
POST |
/auth/login |
Login and receive session cookie |
POST |
/auth/logout |
Clear session cookie |
GET |
/auth/me |
Get current logged-in user |
curl -X POST http://localhost:4000/auth/register \
-H "Content-Type: application/json" \
-d '{"username": "admin", "password": "your-password"}'curl -X POST http://localhost:4000/auth/login \
-H "Content-Type: application/json" \
-d '{"username": "admin", "password": "your-password"}'
# Response includes Set-Cookie header for subsequent requests| Method | Endpoint | Description |
|---|---|---|
GET |
/mailboxes |
List all mailboxes (credentials excluded) |
POST |
/connect-email |
Connect a new mailbox |
POST |
/disconnect-email |
Disconnect a mailbox |
GET |
/mailboxes/:id/profile |
Get mailbox profile |
PATCH |
/mailboxes/:id |
Update mailbox settings |
POST |
/mailboxes/:id/documents |
Add reference document |
DELETE |
/mailboxes/:id/documents/:docId |
Remove document |
POST |
/sync |
Manually sync mailbox(es) |
curl -X POST http://localhost:4000/connect-email \
-H "Authorization: Bearer your-api-key" \
-H "Content-Type: application/json" \
-d '{
"host": "imap.gmail.com",
"port": 993,
"user": "you@gmail.com",
"password": "your-app-password",
"tls": true,
"smtpHost": "smtp.gmail.com",
"smtpPort": 465,
"label": "My Gmail"
}'Request Fields:
| Field | Required | Description |
|---|---|---|
host |
✅ | IMAP server hostname |
port |
No | IMAP port (default: 993) |
user |
✅ | Email address/username |
password |
✅ | Email password or app password |
tls |
No | Use TLS (default: true) |
smtpHost |
✅ | SMTP server hostname |
smtpPort |
No | SMTP port (default: 587, use 465 for SSL) |
label |
No | Friendly name for the mailbox |
webhookUrl |
No | Webhook for escalation notifications |
negotiationPolicy |
No | Per-mailbox negotiation rules |
profile |
No | Initial profile settings |
curl -X PATCH http://localhost:4000/mailboxes/:id \
-H "Authorization: Bearer your-api-key" \
-H "Content-Type: application/json" \
-d '{
"label": "Work Inbox",
"webhookUrl": "https://hooks.slack.com/services/...",
"profile": {
"calendar": "https://calendar.google.com/...",
"priorities": ["urgent", "important"]
}
}'| Method | Endpoint | Description |
|---|---|---|
GET |
/emails |
List emails with filters |
GET |
/emails/:id |
Get single email |
POST |
/emails/:id/send-draft |
Approve and send draft reply |
POST |
/emails/:id/dismiss |
Dismiss without sending |
# Get all emails
curl -H "Authorization: Bearer your-api-key" \
http://localhost:4000/emails
# Filter by classification
curl -H "Authorization: Bearer your-api-key" \
"http://localhost:4000/emails?label=Customer&status=classified&limit=20"
# Filter by mailbox
curl -H "Authorization: Bearer your-api-key" \
"http://localhost:4000/emails?mailboxId=abc-123"Query Parameters:
| Param | Description |
|---|---|
mailboxId |
Filter by mailbox ID |
label |
Classification label (Customer, Meeting, Newsletter, etc.) |
action |
Decision action (archive, reply_draft, ignore, notify, requires_human) |
status |
Email status (received, classified, etc.) |
limit |
Max results (default: 50) |
curl -X POST http://localhost:4000/emails/:id/send-draft \
-H "Authorization: Bearer your-api-key" \
-H "Content-Type: application/json" \
-d '{"body": "Thank you for your inquiry. Our pricing starts at $99/month."}'
# Or send the existing draft without editing:
curl -X POST http://localhost:4000/emails/:id/send-draft \
-H "Authorization: Bearer your-api-key"| Method | Endpoint | Description |
|---|---|---|
GET |
/negotiations |
List negotiations |
GET |
/negotiations/:id |
Get negotiation details |
POST |
/negotiations |
Start owner-initiated negotiation |
POST |
/negotiations/:id/resume |
Resume escalated negotiation |
curl -X POST http://localhost:4000/negotiations \
-H "Authorization: Bearer your-api-key" \
-H "Content-Type: application/json" \
-d '{
"mailboxId": "abc-123",
"to": "seller@example.com",
"subject": "Bulk License Inquiry",
"intent": {
"type": "purchase",
"goal": "Buy a 50-seat enterprise license",
"constraints": {
"maxPrice": 5000,
"preferredPaymentTerms": "net-30"
}
},
"policy": {
"maxDiscountPercent": 10,
"maxRounds": 8
}
}'curl -H "Authorization: Bearer your-api-key" \
"http://localhost:4000/negotiations?status=open"| Method | Endpoint | Description |
|---|---|---|
GET |
/memory |
List/search memories |
GET |
/memory/:id |
Get memory with sources |
DELETE |
/memory/:id |
Delete a memory |
POST |
/memory/consolidate |
Trigger memory consolidation |
curl -H "Authorization: Bearer your-api-key" \
"http://localhost:4000/memory?q=pricing&limit=10"| Method | Endpoint | Description |
|---|---|---|
GET |
/dashboard |
Aggregate metrics |
GET |
/dashboard/mailboxes |
Per-mailbox breakdown |
GET |
/daily-report |
Daily summary report |
curl -H "Authorization: Bearer your-api-key" \
http://localhost:4000/dashboard
# Filter by mailbox
curl -H "Authorization: Bearer your-api-key" \
"http://localhost:4000/dashboard?mailboxId=abc-123"| Method | Endpoint | Description |
|---|---|---|
GET |
/knowledge |
Newsletter insights extracted |
GET |
/opportunities |
Business opportunities found |
curl -H "Authorization: Bearer your-api-key" \
"http://localhost:4000/knowledge?limit=20"
curl -H "Authorization: Bearer your-api-key" \
http://localhost:4000/opportunities| Method | Endpoint | Description |
|---|---|---|
GET |
/settings |
Get current settings (keys masked) |
PATCH |
/settings |
Update settings (takes effect immediately) |
curl -X PATCH http://localhost:4000/settings \
-H "Authorization: Bearer your-api-key" \
-H "Content-Type: application/json" \
-d '{
"qwenModel": "qwen-plus",
"negotiationMaxRounds": 12,
"negotiationMaxDiscountPercent": 20
}'Editable Settings:
qwenApiKey— Qwen API keyqwenBaseUrl— Qwen API endpointqwenModel— Model for completionsqwenEmbeddingModel— Model for embeddingsnegotiationMaxRounds— Max negotiation roundsnegotiationMaxDiscountPercent— Max discount percentagenegotiationRequireApprovalAboveAmount— Amount threshold for approvalnegotiationMinConfidenceToAutoSend— Confidence threshold for auto-send
| Method | Endpoint | Description |
|---|---|---|
GET |
/agents/status |
Status of all agents |
curl -H "Authorization: Bearer your-api-key" \
http://localhost:4000/agents/status| Method | Endpoint | Description |
|---|---|---|
POST |
/ask |
Ask a question to the QA agent |
curl -X POST http://localhost:4000/ask \
-H "Authorization: Bearer your-api-key" \
-H "Content-Type: application/json" \
-d '{
"question": "What pricing did we discuss with Acme Corp?",
"mailboxId": "abc-123"
}'| Method | Endpoint | Description |
|---|---|---|
POST |
/ingest |
Inject message into pipeline |
Useful for webhook-style connectors or testing:
curl -X POST http://localhost:4000/ingest \
-H "Authorization: Bearer your-api-key" \
-H "Content-Type: application/json" \
-d '{
"mailboxId": "abc-123",
"from": "test@example.com",
"subject": "Test Message",
"text": "This is a test message."
}'| Method | Endpoint | Description |
|---|---|---|
GET |
/backup |
Full instance backup |
GET |
/mailboxes/:id/backup |
Single mailbox backup |
# Full backup
curl -H "Authorization: Bearer your-api-key" \
http://localhost:4000/backup \
-o mailos-backup.json
# Single mailbox
curl -H "Authorization: Bearer your-api-key" \
http://localhost:4000/mailboxes/abc-123/backup \
-o mailbox-backup.jsonNote: Credentials are never included in backups (security feature).
| Method | Endpoint | Description |
|---|---|---|
GET |
/health |
Health check (public) |
GET |
/system/version |
Current version info |
GET |
/system/update-check |
Check for updates |
POST |
/system/update |
Trigger in-app update |
GET |
/system/errors |
Recent error logs |
GET |
/system/login-blocks |
List login blocks |
DELETE |
/system/login-blocks/:fingerprint |
Remove login block |
The web dashboard is available at:
http://localhost:4000/login.html
On first run, you'll see the setup page to create your admin account.
| Variable | Description | Default |
|---|---|---|
QWEN_API_KEY |
Qwen API key | Required |
JWT_SECRET |
Secret for JWT signing | Dev insecure default |
ENCRYPTION_KEY |
32-char key for credential encryption | Dev insecure default |
API_KEYS |
Comma-separated API keys for external access | None |
ADMIN_USERNAME |
Bootstrap admin username | None |
ADMIN_PASSWORD |
Bootstrap admin password | None |
PORT |
Server port | 4000 |
HOST |
Server bind address | 0.0.0.0 |
NODE_ENV |
Environment | development |
MONGODB_URI |
MongoDB connection string | Embedded NeDB |
REDIS_URL |
Redis URL for queues | In-process |
NEGOTIATION_MAX_ROUNDS |
Max negotiation rounds | 10 |
NEGOTIATION_MAX_DISCOUNT_PERCENT |
Max discount allowed | 15 |
NEGOTIATION_APPROVAL_ABOVE |
Amount requiring approval | None |
NEGOTIATION_MIN_CONFIDENCE |
Min confidence for auto-send | 0.7 |
NEGOTIATION_WEBHOOK_URL |
Default escalation webhook | None |
GITHUB_REPO |
GitHub repo for update checks | None |
Made with 🧠 + ✉️ + Qwen
