关于 openagentemail
OpenAgentEmail 是一个可自托管的开源服务,为 AI Agent 提供邮箱身份、邮件收发、OTP 提取以及结构化任务交接功能,通过 MCP 和 REST 提供访问。适合需要在不同环境的 Agent 之间协作并保持可审计性的团队。
主要功能
- 01Agent 身份地址与独立身份令牌
- 02邮件收发、OTP 验证码与链接提取
- 03带状态历史的结构化任务交接
- 04记录指定审核人的批准或拒绝
- 05Webhook 与人工通知推送
适用场景
- 01让不同终端或设备上的 Agent 交接任务
- 02为 Agent 接收并读取注册验证码邮件
- 03记录需要人工审批的任务结果
MCP 相关
OpenAgentEmail 通过 HTTP MCP 和 stdio MCP 封装器提供邮件、任务和审批等操作,MCP 客户端可以通过这些工具访问服务。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
npx -y @openagentemail/mcpOPENAGENTEMAIL_API_KEY密钥Bearer key for the openagent.email API — best: the identity token (oa_…) returned by POST /v1/identities.OPENAGENTEMAIL_API_URLBase URL of the openagent.email API.本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
工具
25收录的工具列表 · 更新于 2 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| name | string | 否 | 身份的可选显示名称 |
| domain | string | 否 | 地址的可选域名。必须是服务器配置的域名之一。默认使用主 DOMAIN。 |
| scopes | array | 否 | 可选令牌 scopes。支持:read:messages、identities:create、messages:send。使用 [] 表示没有 API 操作权限;管理员省略时使用旧版完整身份权限;对于限定权限的父身份,默认使用子身份 scopes(父身份有 read:messages 时为 [read:messages],否则为 [])。子身份创建时不能授予 identities:create。 |
| localpart | string | 否 | 自定义电子邮件 localpart(例如,my-bot@domain 中的 'my-bot')。省略时会随机生成。 |
| canNotifyUser | boolean | 否 | 仅限管理员:允许此身份发送人工警报通知 |
详细介绍
OpenAgentEmail
为 AI Agent 提供开放的通信和任务交接。
通过 MCP 和 REST 提供可自托管的电子邮件、任务讨论串、审批和 Webhook
——适用于你已在使用的 Agent。
使用你自己的 Agent,掌控工作进度。
开始使用 · 尝试任务交接 · 文档 · 架构 · 简体中文
查看实际运行效果
为 Agent 提供一个地址,给它发送任务,然后在同一讨论串中查看进度和结果。 OAE 让交接过程清晰可查;实际工作由 Agent 现有的运行框架完成。
观看交接录像(MP4) — 时长约 47 秒。 视频通过链接提供,不在页面内嵌播放。双方通过录制脚手架发起真实的 REST 调用(并非真人实时点击控制台);画面使用无头 Chrome + CDP 捕获;时间戳采用 UTC+8 的 12 小时制;指针和字幕条为后期装饰。录像中明确展示了激活操作——请勿将其视为自动唤醒的证明。你可以使用双身份只读代码审查方案自行复现该协议。
sequenceDiagram
participant A as Requester agent
participant O as OpenAgentEmail
participant B as Recipient agent
A->>O: Create a task for B
B->>O: Read the task when activated
B->>O: Report working
Note over B: Review in its own environment
B->>O: Report completed with a result
A->>O: Read the result and history
查看现有的电子邮件和 OTP 界面

此仓库图片展示的是电子邮件功能,而非 Agent 编排控制台。下方人工可见性部分展示任务看板产品图片。
为什么选择 OpenAgentEmail?
在不同终端或不同设备上运行的 Agent 需要一种共享的通信方式:谁提出了工作请求、谁接收了请求、当前进展如何,以及最终返回了什么。它们不应为了交换工作而共享管理员凭据,也不应切换到同一个执行环境。
OAE 将普通电子邮件与结构化、经过身份验证的任务讨论串结合起来。你可以将其用作 Agent 邮箱、清晰可查的任务交接层,或两者兼用。电子邮件和 OTP 工作流仍是一等功能;该项目并不局限于替代电子邮件服务。
今天可以做什么
| 功能 | 可提供的能力 | 限制 |
|---|---|---|
| Agent 身份 | 使用你管理的域名地址,并配有单独的身份令牌 | 这是通过兜底邮箱实现的逻辑身份,并非无限量的实体邮箱 |
| 电子邮件和消息 | 发送/读取邮件、提取 OTP 代码和链接、等待匹配项 | SMTP 接受邮件不代表收件人已收到 |
| 任务交接 | 指定接收方、状态历史、结构化结果和直接的父子关联 | 不会自动选择工作者,也不会安排后代任务 |
| 审批 | 记录指定审核者的批准或拒绝 | 决策本身不会执行操作 |
| 通知和 Webhook | 向人员发送提醒,并向你的集成传递出站事件 | Webhook 需主动启用;成功传递不代表 Agent 已处理任务 |
| 人工查看 | 在控制面板中查看邮件、任务、身份和通知 | 访问权限取决于会话的身份和权限 |


这些是真实产品截图,拍摄时经过了匿名化处理。它们展示的是可查看性,并不能证明通知已被处理或获批操作已执行。
REST、HTTP MCP 和 stdio MCP 封装层均提供这些操作。可选的任务租约支持接收方认领、续租和释放任务;但不能保证外部副作用只发生一次。请参阅工具参考。
快速入门
已经有实例?
向其运营者索取你的身份地址和适用的身份令牌,然后连接你的 Agent。你无需再部署一个邮件服务器。 完成首次任务交接,或向你的身份地址发送测试邮件,并确认你可以读取邮件。
部署新实例
启动引导式设置:
npx -y @openagentemail/setup
设置 CLI 会引导你完成部署和客户端配置。选择适合你环境的邮件后端:
| 部署方式 | 适用场景 | 前置条件 |
|---|---|---|
| 捆绑邮件服务器 | 你想自行运营邮件系统 | Docker Compose、域名、DNS 配置、可访问的入站 SMTP,以及出站 25 端口或中继 |
| 仅 API | 服务提供商已托管你的域名 | Docker Compose、兜底邮箱、IMAP/SMTP 凭据,以及使用身份地址发送邮件的权限 |
除非你有意配置 SSH 隧道或 HTTPS 反向代理,否则请保持 API 绑定到 localhost。邮件证书和 API 的 HTTPS 是两项独立配置。不要公开未加保护、会传输令牌的 HTTP API。
部署后,请验证你实际选择的路径:
捆绑邮件服务器。 此堆栈负责管理 mail.$DOMAIN、mail DKIM 选择器,以及 465/993 端口上的 TLS。针对该布局运行 doctor:
sudo ./deploy/doctor.sh
它会检查捆绑堆栈所需的 DNS、端口访问、证书和通知前置条件。但它仍不会通过 IMAP/SMTP 登录,也不会发送往返邮件。
仅 API(使用你自己的邮件提供商)。 跳过 deploy/doctor.sh——它假设使用捆绑邮件主机,对于不同的 MX/DKIM 配置会报告错误。请改为:确认 /healthz 返回健康状态,确认你的 IMAP/SMTP 凭据可用于兜底邮箱,然后向某个身份地址发送真实邮件并读取该邮件。完成这些步骤后,再尝试任务示例。单凭 /healthz 健康只能证明 HTTP 进程正在运行,不能证明邮件投递正常。
现有 api-data 卷:一次性非 root 迁移(#93)
API 运行时镜像以 bun 用户(uid/gid 1000)运行,而非 root。
新建的命名卷会继承镜像中 /app/data 目录的所有权,无需在主机端修复。
现有的生产卷是在 API 以 root 身份运行时写入的,因此仍归 root 所有;新的非 root 进程无法写入,直到你执行一次迁移。
顺序设计为遇到问题立即停止:在滚动更新新镜像之前迁移卷。 先部署新镜像会导致其拒绝启动(或在首次写入时失败),直到所有权得到修复——这是有意为之,并非静默回退。
- 备份项目范围内的卷(项目名称示例
openagentemail→ 卷openagentemail_api-data;仅 API 的堆栈使用其-p/COMPOSE_PROJECT_NAME前缀,例如oae-alpha_api-data)。 - 停止挂载此卷的写入程序(至少停止
api服务;完整堆栈还要在此期间停止任何其他写入api-data的程序),并保持停止状态,直到在第 6 步中重新创建它们。仅停止还不够:只有所有旧容器都彻底移除后,迁移才算完成。restart≠ 重新创建——root 容器如果再次启动(崩溃后重启,或因习惯而启动),就会继续写入,并悄悄地以root:root重新创建卷文件,从而撤销你的chown,且不会报错。如果写入程序因任何原因重新启动,请停止它,并在继续之前重新执行第 3 步。 - 一次性将所有权更改为运行时用户:
# Replace <project>_api-data with your real volume name (docker volume ls).
docker run --rm -v <project>_api-data:/data alpine \
sh -c 'chown -R 1000:1000 /data'
- 在重新启动服务前抽查所有权:
docker run --rm -v <project>_api-data:/data alpine \
sh -c 'ls -ln /data | head'
# Expect uid/gid columns to show 1000 / 1000 for migrated paths.
- 在卷上回读迁移结果——必须通过:
docker run --rm -v <project>_api-data:/data alpine \
sh -c 'find /data ! -user 1000 | head'
# Expect no output: zero files still owned by a non-1000 user.
- 拉取/构建新镜像,然后在启动任何服务之前,确认 API 镜像声明了运行时用户。构建整个项目(运行不带服务名称的
docker compose build)——或者至少同时构建api和ntfy-provision:它们共用一个 Dockerfile,而且下面的--force-recreate也会重新运行一次性ntfy-provision容器,因此它必须来自同一批非 root 镜像。此处重新运行过时的 root 镜像会以 root 身份写入卷,撤销你的迁移——这正是本操作指南要防止的问题。
docker inspect <new-api-image> --format '{{.Config.User}}'
# Expect bun (uid 1000) — never empty/root.
只有完成上述步骤后,才能启动所有服务(运行 docker compose up -d --force-recreate,或使用你惯常的部署流程)。
不要颠倒此顺序。 生产环境的 chown 是部署窗口内的操作;不会由镜像入口点执行。
部署窗口内重新创建的注意事项(2026-09-21 测量)
--force-recreate <service>会沿着依赖链执行。 在参考主机上的测量结果:重新创建api也会沿着api→mailserver→provision重新创建mailserver(而ntfy会拉取ntfy-provision)——服务正常,约 11 秒,无数据损失,但并非预期。若要只重新创建指定的服务,请添加--no-deps;构建整个项目时则保留原样。- 测量覆盖配置的归属——不要想当然。 编辑或移除任何覆盖配置之前,先针对三种配置运行
docker compose config:仅基础配置、基础配置 + 每个覆盖配置,然后逐字段比较解析后的输出。在参考主机上(2026-09-21),这一区分了两个同类文件:docker-compose.override.yml对配置没有任何贡献(其补丁早已并入基础文件),因此已在创建带时间戳的备份后移除;而compose.override.yaml仍在生效,必须保留(它添加了环回绑定并扩大了允许的端口范围)。重新创建时出现 "Found multiple override files" 警告,就是应运行此检查的信号。范围说明:覆盖配置的自动合并仅在使用默认文件的调用中发生——显式选择文件的部署(例如仅 API 部署docker compose -f compose.api-only.yaml ...)不会自动合并任何覆盖配置,必须显式传入每个覆盖配置。
ntfy 非 root 升级(#278)
ntfy 现在以 UID 1000 运行,并监听容器端口 2587。如果现有部署之前以 root 身份运行 ntfy,请在执行 up -d 之前对其数据执行 chown;否则 ntfy 将无法启动,API 也会保持停机状态(depends_on 健康检查):
# Same volume naming as above; only the ntfy subtree is required here.
docker run --rm -v <project>_api-data:/data alpine \
sh -c 'chown -R 1000:1000 /data/ntfy'
然后运行 docker compose up -d(重新创建 ntfy 和 api)。之前完整卷的 #93 迁移已覆盖 /data/ntfy;只有在该子目录仍归 root 所有时才需要重新运行迁移。
连接你的 Agent
选择合适的凭据
| 身份设置 | 预期用途 |
|---|---|
scopes: ["read:messages"] | 读取/等待获准访问的邮件;不能发送邮件或执行任务操作 |
省略 scopes | 当前完整的身份权限,受地址/参与者规则限制;适用于任务参与者 |
scopes: [] | 无 API 操作权限 |
这些是当前的 API 语义,并非对新增作用域的提议。完整的身份权限不等于管理员权限。只有操作员才能创建/列出/管理身份。不要将管理员密钥放入 Agent 客户端配置中。请参阅凭据设置。
本地 stdio MCP
已发布的 MCP 客户端需要 Node.js 20+,与其软件包约定一致。API 服务在容器内通过 Bun 运行。通用的本地客户端配置如下:
{
"mcpServers": {
"openagentemail": {
"command": "npx",
"args": ["-y", "@openagentemail/mcp"],
"env": {
"OPENAGENTEMAIL_API_URL": "http://localhost:3100",
"OPENAGENTEMAIL_API_KEY": "oa_replace_with_your_identity_token"
}
}
}
}
仅当 API 位于同一主机上或通过本地 SSH 隧道访问时,才使用 localhost。对于远程实例,请使用其 HTTPS 基础 URL。保护好客户端配置;不要提交令牌。stdio 客户端不需要邮件服务器的 IMAP/SMTP 凭据。
远程 HTTP MCP
支持远程 MCP 的客户端可以直接连接到实例的 /mcp 端点,无需安装 stdio 软件包。配置公开的 HTTPS 源站,并遵循客户端支持的 Bearer/OAuth 流程。OAuth 授权的变更权限与管理员凭据或直接身份凭据不同。请使用客户端指南;支持该协议并不意味着会自动唤醒,也不代表与任何供应商存在合作关系。
MCP 参考介绍了所有已注册工具、权限和等待语义。每次服务端等待时长上限由 MCP_MAX_WAIT_SECONDS 限定(默认 60 秒,可配置范围为 1 到 600)。MCP 邮件客户端可以在请求的总截止时间内重新启动较短的等待时段;任务等待则是一次受上限约束的等待。如果等待超时,并不代表任务失败。创建结果不确定时,请检查返回的任务 ID/历史记录,而不要盲目再创建一个任务。
工作原理
flowchart TB
Agents["Existing agents / harnesses"] -->|"REST · HTTP MCP · OAuth"| API["OAE API: Bun + Hono"]
Agents --> Stdio["Node stdio MCP wrapper"]
Stdio -->|"REST"| API
Human["Humans via /ui"] --> API
API -->|"SMTP / IMAP"| Mail["Bundled mailserver or external catch-all"]
API --> State["DATA_DIR local state<br/>identities · auth · sessions · webhooks<br/>optional lease journal"]
Mail -->|"IMAP"| Watcher["Watcher in the API process"]
Watcher --> Delivery["ntfy and/or webhook delivery"]
Delivery --> Adapter["External adapter / receiver"]
Adapter -. "Activation is integration-specific" .-> Agents
任务根据经过身份验证的邮件记录重建。本地文件还会保存运行状态,包括可选的待处理租约日志。执行始终在 Agent 自身的运行时中进行——OAE 不会运行模型。这是一个带后台循环的单进程服务,并非分布式工作进程运行时。
核心功能不依赖 Orca。仓库中附带的 webhook-wake 示例目前面向 Orca;它并非通用的替代适配器。已记录的待处理 webhook 投递可以恢复,但监视器不会重放 API 停机期间收到的所有邮件。消费者应在启动或重新连接时协调任务/邮件状态,而不应将通知视为工作的唯一记录。
请阅读当前架构与数据所有权,了解 SMTP/IMAP 可见性叠加层、任务状态和通知边界。
部署与边界
掌控数据流,而不只是服务端。 可自托管实例无需依赖 OAE SaaS 控制平面。外部邮箱提供商、SMTP 中继、归档收件人或通知目标仍可能根据你的配置接收数据。返回给远程模型/客户端的邮件也会离开服务端。在暴露凭据或邮件内容前,请检查这条数据流。
容量与限制是运维层面的选择。 软件不收取按身份计费的许可费用。邮箱容量、提供商策略、磁盘、内存和可配置的速率限制仍然适用(默认每个身份每小时发送 20 封邮件;API 在启动时根据 send-log.jsonl 重建该小时窗口,统计已排队的行以及 SMTP 服务端已回复的失败行;丢失日志行的发送不会计入)。
普通邮件默认保留 30 天;标记为任务的邮件不受该清理程序影响。请一并备份邮件存储、DATA_DIR 和稳定的签名密钥。
已读状态是共享状态。 将邮件标记为已读会影响其他邮箱使用者;这不是 Agent 的私有确认。若需独立处理,请使用特定于使用者的游标并定期进行协调。仅阅读邮件不会将其标记为已读。
可选租约:默认设置与推出边界
TASK_LEASES_ENABLED 默认值为 false。启用后,每个邮箱只能运行一个 API 进程。认领/续租/释放操作必须使用受管理收件人的身份,而非管理员模拟身份。不要针对同一状态启用多个 API 写入进程。
- 可选的
TASK_LEASES_EXPIRY_AUDIT_M3(默认值为 false)将回收与到期审计 SMTP 解耦;始终允许匹配的到期回执延迟到达。 - 可选的
TASK_LEASES_OVERLAY_BOUND(默认值为 false)会在 15 分钟后停止公开列表/详情接口重放未索引的租约覆盖事件。 - 可选的
TASK_LEASES_PENDING_JOURNAL(默认值为 false,要求启用TASK_LEASES_ENABLED)会在重启后保留待处理的代次屏障,并记录或推迟到期审计工作。 - 即使日志功能关闭(生产环境默认设置),当新鲜(
≤15 min)的release/renew已被 SMTP 接受、但尚未纳入持久化重建时,claim也会返回 409lease_overlay_pending_index。调用方应在完成索引后重试。如果回执永久丢失,屏障会在 15 分钟后过期(与TASK_LEASES_OVERLAY_BOUND一致),随后即可继续认领;差异由 #305 读取端降级机制(#308)控制。
生产环境的到期审计发送仍被强制禁用;这些标志不会启用该功能。在配置或启用日志写入前,请阅读日志运行指南。配置不是擦除/恢复流程。存在 claim_lost 墓碑后,回滚到旧版读取器并不安全。租约不会撤销外部文件变更、提交或其他副作用。
| 我想…… | 从这里开始 |
|---|---|
| 将任务交给另一个身份 | 首次任务交接 |
| 了解任务状态和持久化 | 架构 |
| 部署、配置 TLS 或检查 UI | 运维指南 |
| 连接客户端 / 检查工具权限 | 客户端指南 · MCP 工具参考 |
| 集成 HTTP API 或出站事件 | REST 参考 · Webhook 规范 |
| 探索外部唤醒和框架集成 | Orca 唤醒示例 · 适配器示例 |
| Webhook → 无头 Agent 回复(配方 + 模板) | Agent 回复器配方 · 模板 |
| 了解暴露面和隐私 | 安全指南 · 报告漏洞 |
框架示例和本地测试装置不能证明生产环境中的端到端运行。各自的 README 会说明哪些路径使用模拟服务,以及哪些需要明确触发真实调用。
发展方向与贡献
自带 Agent。让工作过程可检查。掌控自己的基础设施。构建交接机制,而非另一个运行时。
下一步将简化与现有工作环境的连接,并完善恢复与运维指南,而不是承诺提供通用调度器、共享工作区管理器、全局联邦或自动代码执行。当前功能如上所列;发布历史请参阅 CHANGELOG.md。npm 徽章跟踪的是 MCP 包,而非统一的服务端 / 部署版本。
有关 README 更新以及尚待完成的实时演示 / 网站后续工作,请参阅 #251。 网站代码库负责公共网站的展示和文档。
欢迎提交 Issue 和 PR。请阅读 CONTRIBUTING.md:大量工作应从 Issue 开始;合并前必须经过独立审查并通过 CI。 文档变更应与实际代码保持一致,而非描述预期功能。
运维快捷方式和高级部署
使用自己的邮件服务
已经为你的域名配置了邮件服务商?使用
compose.api-only.yaml 单独运行 API,并将其连接到该服务商的
全收件箱。外部邮件服务指南
介绍了所需的全收件箱设置、Portainer 部署、SMTP 发件人限制以及 TLS 证书验证。
独立部署的默认项目名称为 openagentemail。如果完整的
compose.yaml 堆栈也在同一主机上运行,则仅运行 API 的堆栈不得使用相同的默认项目名称:为其指定不同的 -p 值或
COMPOSE_PROJECT_NAME,以免两个堆栈接管对方的资源。
要在一台主机上运行多个仅包含 API 的实例,请为每个实例设置独立的环境文件、唯一的 Compose 项目名称和主机侧的 API_PORT。API 在容器内始终监听端口 3100;API_PORT 只会更改主机侧的端口映射。例如:
mkdir -p ../oae-api-only-env
cp .env.api-only.example ../oae-api-only-env/alpha.env
cp .env.api-only.example ../oae-api-only-env/beta.env
chmod 600 ../oae-api-only-env/*.env
# Set API_PORT=3100 in alpha.env and API_PORT=3101 in beta.env.
# Generate separate API_KEYS and TASK_SIGNING_SECRET values in each file.
docker compose -p oae-alpha --env-file ../oae-api-only-env/alpha.env -f compose.api-only.yaml up -d
docker compose -p oae-beta --env-file ../oae-api-only-env/beta.env -f compose.api-only.yaml up -d
你也可以为每条命令设置唯一的 COMPOSE_PROJECT_NAME,而不使用
-p。项目名称会让 Compose 生成不同的容器名称和项目范围内的命名卷。每个实例都必须独立生成 API_KEYS 和 TASK_SIGNING_SECRET 值。使用不同的 API_PORT 值、独立的数据卷,以及预期相互隔离的邮箱 / 服务商边界;这并非多写入者方案。已填入内容的文件应保存在代码库之外。
在浏览器中读取邮件
通过 localhost、SSH 隧道或 HTTPS 打开 /ui,并使用适当的令牌登录。普通会话与已持久化的 信任此设备 会话具有不同的有效期;重启 API 不会清除所有受信任会话。请参阅UI 访问与会话。
仪表板 UI 通过 Settings 中的语言选择器(oa_lang cookie)支持 en / es / ja / ko / zh-CN;术语遵循 docs/i18n-glossary.md。
概览计数统计的是一个有限时间窗口,而非生命周期总量。缓存计时、未知计数和扫描限制详见运维指南。
多域名支持
DOMAIN 加上 EXTRA_DOMAINS 可定义由一个实例管理的域名。显式身份可以在不同的已配置域名上使用相同的本地部分;完整地址不能重复。其他域名仍需配置提供商/MTA 路由和 DNS/DKIM。此功能不支持独立实例间的联合。请参阅多域名运维。
公共邮件 TLS 和续期为可选功能;API 的 HTTPS 需要单独配置受信任的反向代理或隧道。
可选的合规归档:
ALWAYS_BCC 默认关闭,启用后会额外指定一个域外数据接收方。
选择自托管,以掌控部署、数据路径和策略——但这并不意味着零成本、硬件容量无限,也不代表不受上游提供商政策影响。
资源规划取决于工作负载;本 README 不提供未注明日期的基准测试,也不保证 VPS 价格。
OAE 是面向 Agent 邮件和任务交接的开源选项。详细的供应商对比需要注明日期的一手资料;旧版未经核实的功能矩阵已停用。
文档索引。
许可证
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。

