postMeister is the always-on concierge layer for the agent ecosystem. one email address, one inbox, one dispatcher. the operator sends a message. postMeister routes it to the right agent, wakes sleeping agents, tracks responses, and ensures nothing falls through the cracks.
by saturday morning, the operator sits down with coffee and a bagel and walks through a fully deployed, tested, verified email stack with live agent routing.
OPERATOR (phone/desktop/tablet)
|
| email to: dispatch@untitledprojects.io
v
+------------------+
| STALWART | EC2 (questboard-ec2)
| SMTP/IMAP/JMAP | port 25/587/993/8080
| mail.untitled- | systemd service
| projects.io | ~100MB RAM
+--------+---------+
|
| IMAP poll (python, 30s)
v
+------------------+
| postMeister | EC2 (questboard-ec2)
| python daemon | systemd service
| always-on | ~50MB RAM
+--------+---------+
|
+-----+-----+-----+
| | |
v v v
localMesh agents QB
(nudge) (email) (tickets)
| software | Stalwart Mail Server (rust, single binary) |
| host | questboard-ec2 (100.83.251.119) |
| domain | mail.untitledprojects.io |
| ports | 25 (SMTP), 587 (submission), 993 (IMAPS), 8080 (web admin) |
| storage | local disk (/var/lib/stalwart) |
| TLS | Let's Encrypt auto-cert via Stalwart built-in ACME |
| auth | DKIM + SPF + DMARC configured via GoDaddy DNS |
| address | purpose |
|---|---|
| dispatch@untitledprojects.io | main operator inbox -- postMeister watches this |
| goulard@untitledprojects.io | agent-specific (example) |
| dorlange@untitledprojects.io | keymaster agent |
| postmeister@untitledprojects.io | system/admin mailbox |
| artificer@untitledprojects.io | operator personal (optional) |
| language | python 3 |
| host | questboard-ec2 |
| service | systemd (postmeister.service) |
| poll interval | 30 seconds (IMAP IDLE if supported) |
| dependencies | imaplib, smtplib, requests (for localMesh + QB) |
routing logic:
postMeister is state-aware. it knows which agents are IDLE, PREP, or ACTIVE (via localMesh registry). routing decisions use this:
operator uses ecoute2 voice widget to talk through the system while testing. agent responds via email AND voice (if ecoute2 is connected to the active agent).
required records on untitledprojects.io (GoDaddy):
| type | name | value | TTL |
|---|---|---|---|
| A | 3.149.50.128 (Elastic IP) | 600 | |
| MX | @ | mail.untitledprojects.io (priority 10) | 600 |
| TXT | @ | v=spf1 ip4:3.149.50.128 -all | 600 |
| TXT | _dmarc | v=DMARC1; p=quarantine; rua=mailto:postmeister@untitledprojects.io | 600 |
| TXT | stalwart._domainkey | [DKIM public key - generated by Stalwart] | 600 |
operator must verify GoDaddy DNS access works. goulard3120 has API access via vault (godaddy_personal_api_key) and can set records programmatically. no manual action needed unless API fails.
| task | owner | status |
|---|---|---|
| install Stalwart binary on EC2 | goulard3120 | pending |
| configure Stalwart (domain, TLS, admin) | goulard3120 | pending |
| set DNS records via GoDaddy API | goulard3120 | pending |
| create mailboxes (dispatch, postmeister, test) | goulard3120 | pending |
| send/receive test (agent to dispatch@) | goulard3120 | pending |
| open EC2 security group ports (25, 587, 993) | goulard3120 | pending |
deliverable: stalwart running, DNS propagated, test email round-trip confirmed.
| task | owner | status |
|---|---|---|
| write postMeister daemon (IMAP poll, routing, localMesh nudge) | goulard3120 or successor | pending |
| deploy as systemd service on EC2 | agent | pending |
| agentStateLoop phase 1: state tracking in context.md | agent | pending |
| agentStateLoop phase 2: cron switching prototype | agent | pending |
| integration test: email to dispatch@ triggers agent wake | agent | pending |
deliverable: postMeister daemon running, routing emails to agents, agents waking on nudge.
| task | owner | status |
|---|---|---|
| neonForge dashboard page: agent state, mailbox status, SLAs | agent | pending |
| mobile-responsive testing (Quartz, Pebble, phone) | agent | pending |
| postMeister agent profile doc | agent | pending |
| ecoute2 integration test for saturday | agent | pending |
| end-to-end dry run: operator sends email from phone, agent responds | agent | pending |
| credential resilience test: simulate stale token, verify no halt | agent | pending |
deliverable: everything staged, tested, ready for operator walkthrough.
| task | owner | status |
|---|---|---|
| operator arrives, coffee + bagel | artificer | pending |
| walkthrough: stalwart admin panel (desktop) | agent + artificer | pending |
| test: send email from phone to dispatch@, watch routing | artificer | pending |
| test: send email from desktop, verify agent response <60s | artificer | pending |
| test: trigger state transitions (IDLE->PREP->ACTIVE->IDLE) | artificer | pending |
| review: neonForge dashboard on mobile (Quartz/Pebble) | artificer | pending |
| ecoute2 voice walkthrough of architecture | agent + artificer | pending |
| approve/reject: sign off on postMeister v1 | artificer | pending |
deliverable: operator-approved, production-ready postMeister system.
| resource | usage | cost |
|---|---|---|
| questboard-ec2 (t3.small) | stalwart + postMeister daemon (24/7) | $0 incremental (already running) |
| EC2 security group changes | open ports 25, 587, 993 | $0 |
| EC2 disk | stalwart data (~500MB initial) | $0 (within existing EBS) |
| picass0 (if needed for ecoute2 voice) | 1-2 hours saturday | $1.00 |
| DNS (GoDaddy) | 5 records on untitledprojects.io | $0 (already own domain) |
| day | agent sessions | estimated API cost |
|---|---|---|
| wed (today) | 1 tunnelTime session (goulard3120) | ~$2-3 |
| thu | 1 tunnelTime session | ~$2-3 |
| fri | 1 tunnelTime session | ~$2-3 |
| sat | 1-2 sessions (tunnelTime + specialist) | ~$3-5 |
TOTAL BUDGET
| compute (4 days) | $1.00 (picass0 only) |
| agent labor (4 days) | $9-14 (API tokens) |
| infrastructure | $0 (all existing) |
| total | $10-15 |
within pre-authorized $10/30-day spend. picass0 usage may push slightly over -- requesting approval for up to $15 total.
after goulard3120 sets DNS records via API, operator confirms MX record propagation. can verify via: dig MX untitledprojects.io or mxtoolbox.com.
opening ports 25/587/993 on EC2 security group. pre-authorized per SERVICE-CONTRACT (manage AWS security groups). will lock to tailscale IPs + known mail relay IPs.
operator confirms mailbox naming convention: dispatch@, {handle}@, postmeister@, artificer@. if different names wanted, specify now.
operator walks through all deliverables. approves or requests changes. this is the final gate.
| risk | likelihood | mitigation |
|---|---|---|
| DNS propagation delay | medium | set TTL to 600s. start today, should be fully propagated by thursday. |
| port 25 blocked by AWS | medium | AWS blocks outbound 25 by default on new accounts. we may need to request removal or use port 587 relay. can also use SES as smarthost. |
| stalwart config complexity | low | stalwart has sensible defaults. TOML config. well-documented. |
| agent session continuity | medium | dumpshock/savepoint between sessions. successor agents pick up from project plan. |
| ecoute2 not ready | low | fallback: saturday walkthrough via email thread instead of voice. |
by 9am saturday, the operator should be able to:
| # | title | status |
|---|---|---|
| #680 | agentStateLoop: IDLE/PREP/ACTIVE state machine | queued |
| NEW | stalwart email server deployment on EC2 | to file |
| NEW | postMeister daemon: IMAP routing + localMesh dispatch | to file |
| NEW | neonForge agent state dashboard | to file |
| NEW | DNS config: mail.untitledprojects.io | to file |
postMeister project plan v1.0 // goulard3120 // 2026-05-07
awaiting operator approval to begin execution.