Mirobody 通过单个 config.yml 文件配置 —— 一组扁平的键,由 C++ 内核解析。把提交在仓库里的模板复制成 config.yml 再编辑;每个键都有可用的默认值,所以你只需设置真正要改的那些。
cp config.example.yml config.yml
配置更改在重启后生效。config.yml 已被 git 忽略 —— 只提交 config.example.yml。
解析顺序
配置按键从分层来源合并,高优先级覆盖低优先级:
| 优先级 | 来源 | 说明 |
|---|
| 1(最高) | 环境变量 | 任何键都可被同名环境变量覆盖。 |
| 2 | config.yml | 你的本地文件(已被 git 忽略)。 |
| 3 | 远程配置 | 仅当 CONFIG_SERVER、CONFIG_TOKEN、ENV 三者都设置时拉取。 |
| 4(最低) | config.example.yml | 提交在仓库里的默认值模板。 |
加密的密钥
任何以 gAAAA 开头的字符串值都会被当作 Fernet token,在设置了 CONFIG_ENCRYPTION_KEY 时于加载时解密(config.yml 和远程拉取都适用)。反过来,键名包含 _KEY、_PASSWORD、_PASS、_PWD、_SECRET、_SK、_TOKEN 的值,会用同一个 CONFIG_ENCRYPTION_KEY 自动加密 —— 于是你填进去的明文密钥会被改写成静态的 gAAAA…。
# 生成一个密钥
openssl rand -hex 32
# 经环境提供(不存进 config.yml)
export CONFIG_ENCRYPTION_KEY="<your-key>"
PG_ENCRYPTION_KEY 有意不自动加密(不做 _KEY 后缀处理)—— 它是用来加密数据列的密钥,因此必须保持可读,以便引导数据库启动。生产环境把它放在环境变量或密钥管理器里。
HTTP 服务器
HTTP_HOST: '0.0.0.0' # 监听所有接口
HTTP_PORT: 8080 # 默认端口
# HTTP_URI_PREFIX: '' # 把整个应用挂到子路径下,例如 '/mirobody'
HTTP_ROOT: 'res/htdoc' # 为非 API 的 GET 提供的静态 Web 客户端
# CORS(取消注释以为浏览器客户端启用)
# HTTP_HEADERS:
# Access-Control-Allow-Origin: '*'
# Access-Control-Allow-Methods: 'GET, POST, PUT, DELETE, OPTIONS'
# Access-Control-Allow-Headers: 'Authorization, Content-Type, X-Timezone'
# Access-Control-Max-Age: '86400'
鉴权用的是 Authorization 头里的 bearer token(不是 cookie),所以本地使用时 Access-Control-Allow-Origin: '*' 没问题。不要把 '*' 和 Access-Control-Allow-Credentials: 'true' 一起用 —— 浏览器会拒绝;需要携带凭据时改用固定 origin。生产环境把 origin 限制到你的域名。
LOG_LEVEL: 'INFO' # debug | info | warning | error | critical(大小写不敏感)
LOG_NAME: 'mirobody'
LOG_DIR: '' # 留空 => stdout;设一个路径则写日志文件
LLM 提供商
至少设置一个提供商密钥以启用对话。Agent 在请求时按提供商名挑客户端;默认提供商回退是 gemini-2.5-flash。工具执行方式因提供商而异:OpenAI 和 Gemini 在进程内本地运行内置的 MCP 工具,而 MiroThinker 在提供商侧执行工具(因此需要一个公网可达的 MCP_PUBLIC_URL)。
Google Gemini
GOOGLE_API_KEY: 'AIza...' # AI Studio 密钥(也会读取为 GEMINI_API_KEY)
要覆盖 HIPAA/BAA,把 Gemini 经 Vertex AI 而非 AI Studio 路由:
GOOGLE_GENAI_USE_VERTEXAI: '1'
VERTEX_ACCESS_TOKEN: '' # OAuth 访问令牌,例如 `gcloud auth print-access-token`(约每小时轮换)
GCP_PROJECT: '' # Google Cloud 项目 id(也会读取为 GOOGLE_CLOUD_PROJECT)
VERTEX_LOCATION: 'us-central1'
# VERTEX_BASE_URL: '' # 可选的 host 覆盖(主权云 / 区域)
OpenAI
OPENAI_API_KEY: 'sk-...'
# OPENAI_BASE_URL: '' # 指向任意 OpenAI 兼容端点(OpenRouter、DeepSeek、Groq…)
要覆盖 HIPAA/BAA,把 GPT 跑在你自己的 Azure OpenAI 资源里 —— 设置了 AZURE_OPENAI_ENDPOINT 时客户端会自动切到 Azure 模式:
AZURE_OPENAI_ENDPOINT: 'https://my-resource.openai.azure.com'
AZURE_OPENAI_DEPLOYMENT: 'gpt-4o-mini'
AZURE_OPENAI_API_VERSION: '2024-10-21'
AZURE_OPENAI_API_KEY: '' # 或 AZURE_OPENAI_KEY
MiroThinker
MIROTHINKER_API_KEY: '...' # MiroThinker 提供商必需
# MIROTHINKER_BASE_URL: '...' # 端点覆盖 *(待核实)*
# MIROTHINKER_MODEL: '...' # 模型名 *(待核实)*
MiroThinker 在提供商侧运行工具:MiroMind 的端点会经公网回调到本服务器的 /mcp,所以你还必须设置一个公网可达的 MCP_PUBLIC_URL。localhost 或私网地址不行。
设备本地 Gemma(可选)
原生应用可以完全在设备本地运行 Gemma 4 E2B(Android/iOS 上经 LiteRT-LM,Electron 上经 llama.cpp)—— 无密钥、无网络。如果你自托管了一个 Gemma 运行时(例如 Ollama),把独立服务器指向它:
# GEMMA_CHAT_BASE_URL: 'http://localhost:11434/v1' # 回退到 OLLAMA_BASE_URL
# GEMMA_CHAT_MODEL: 'gemma-4-e2b' # 你的运行时提供的标签
# GEMMA_CHAT_API_KEY: '' # 本地服务器通常留空
Embeddings
EMBEDDING_PROVIDER: 'gemini' # embeddings 提供商(使用上面的 Gemini/Google 密钥)
数据库
二进制里只编译进一个 SQL 后端(在构建期经 MIROBODY_DATABASE_BACKEND 选定 —— 参见 安装指南)。下面这些键配置的是 PostgreSQL 后端,即桌面默认:
PG_HOST: '127.0.0.1'
PG_PORT: 5432
PG_USER: 'postgres'
PG_DBNAME: 'mirobody'
PG_SCHEMA: 'public'
PG_PASSWORD: 'REPLACE_THIS_VALUE_IN_PRODUCTION'
PG_ENCRYPTION_KEY: 'REPLACE_THIS_VALUE_IN_PRODUCTION' # 加密敏感数据列
SQLite 后端(移动端 / 自包含构建)无需连接设置。MySQL、DuckDB、ClickHouse 各有类似的键块。
缓存层是可选的。让 REDIS_HOST 留空,服务器就用进程内的内存 KV 存储 —— 单实例运行没问题。设置 REDIS_HOST 以在多实例间共享缓存状态:
# REDIS_HOST: ''
# REDIS_PORT: 6379
# REDIS_PASSWORD: ''
文件存储
上传的文件和生成的资源(例如图表)会写入一个存储后端,在运行时选定。默认是本地文件系统;其他后端(S3 / S3 兼容、阿里云 OSS、Azure Blob)通过填写各自的块来启用。
本地(默认)
S3 / S3 兼容
阿里云 OSS
Azure Blob
LOCAL_STORAGE_DIR: '_local/storage' # 对象写入位置
LOCAL_STORAGE_URL_PREFIX: '/files' # 本服务器提供对象的 URL 路径
LOCAL_STORAGE_SECRET: 'REPLACE_THIS_VALUE_IN_PRODUCTION' # 预签名 URL 的 HMAC 密钥(设置了 URL 前缀时需 >=16 字符)
# LOCAL_STORAGE_PREFIX: '' # 对象键前缀(留空 => 'mirobody')
# LOCAL_STORAGE_BASE_URL: '' # 公开前缀 / CDN 基址
S3_KEY: '' # AWS access key id
S3_TOKEN: '' # AWS secret access key
S3_REGION: '' # 例如 us-east-1
S3_BUCKET: ''
# S3_ENDPOINT: '' # S3 兼容存储的 host 覆盖(MinIO、R2、GCS interop);留空 => AWS
# S3_PREFIX: '' # 键前缀(留空 => 'mirobody')
ALI_OSS_ACCESS_KEY: ''
ALI_OSS_SECRET_KEY: ''
ALI_OSS_ENDPOINT: 'oss-cn-hangzhou.aliyuncs.com'
ALI_OSS_BUCKET_NAME: ''
# ALI_OSS_PREFIX: ''
AZURE_BLOB_ACCOUNT: ''
AZURE_BLOB_KEY: '' # 账户密钥(base64)
AZURE_BLOB_CONTAINER: ''
# AZURE_BLOB_ENDPOINT_SUFFIX: 'core.windows.net' # 主权云的覆盖
上传的可选静态加密:设置 FILE_ENCRYPTION_KEY(一个可轮换的列表 —— 最后一个密钥负责加密,所有密钥都可解密)外加一个稳定的 FILE_KEY_SEED。参见 config.example.yml 里的注释。
长期记忆
remember / recall_memory 工具存储持久事实。每个后端都会编译进来;在运行时挑一个:
MEMORY_PROVIDER: 'local' # local(默认)| mem0 | zep | everos
local 把事实连同 1024 维 embeddings 存进应用数据库,按进程内余弦相似度排序 —— 无需额外服务。其他后端经 HTTP 与远程记忆服务通信。
邮箱验证码
Web 客户端的默认登录方式。本地测试用预置验证码:
EMAIL_PREDEFINE_CODES:
demo1@mirobody.ai: '777777'
demo2@mirobody.ai: '777777'
demo3@mirobody.ai: '777777'
JWT
JWT_KEY: 'REPLACE_THIS_VALUE_IN_PRODUCTION' # HS256 密钥(256 位):`openssl rand -hex 32`
JWT_SALT: 'REPLACE_THIS_VALUE_IN_PRODUCTION'
# JWT_PRIVATE_KEY: | # 设置以启用 RS256 —— 优先于 JWT_KEY,并发布 JWKS
# -----BEGIN PRIVATE KEY-----
# ...
只设置一种签名模式:JWT_KEY 用于 HS256,或 JWT_PRIVATE_KEY 用于 RS256(经发布的 JWKS 启用第三方令牌校验)。cli/jwt_keygen 工具可生成一对 RSA 密钥。
社交登录(可选)
Google、Apple、X 登录经 Firebase;WeChat 和 GitHub 是直连;Tanka 二维码登录默认开启。
FIREBASE_PROJECT_ID: '' # 校验 Google/Apple/X 的 ID token
# FIREBASE_WEB_API_KEY: '' # Web 应用浏览器 apiKey
# FIREBASE_MESSAGING_SENDER_ID: ''
# APPLE_CLIENT_ID: ''
# WECHAT_APPID: ''
# WECHAT_SECRET: ''
# GITHUB_CLIENT_ID: ''
# GITHUB_CLIENT_SECRET: ''
# TANKA_LOGIN_ENABLED: true # 二维码登录;设为 false 可隐藏按钮
OAuth 2.0 授权服务器
Mirobody 内嵌一个 OAuth 2.0 授权服务器(授权码 + PKCE),让 MCP 客户端可以经浏览器获取令牌,而不必粘贴 bearer token。它配合上面的 JWT 密钥工作;所有 OAUTH_* 键都有可用默认值。
# JWT_ISS: '' # 铸进自签名令牌的 iss/aud/client_id/scope 声明
# JWT_AUD: ''
# OAUTH_RESOURCE_PATH: '/mcp' # 这些令牌保护的资源
发现文档在 /.well-known/oauth-authorization-server、/.well-known/openid-configuration、/.well-known/jwks.json 提供。
MCP 公开 URL
# MCP_PUBLIC_URL: 'https://yourdomain.com'
MCP_PUBLIC_URL 是你 MCP 端点对外可达的基址(<MCP_PUBLIC_URL>/mcp)。它是 MiroThinker 提供商(工具在提供商侧运行)必需的,也是把 MCP 服务器暴露给 ChatGPT Apps、远程 Claude Desktop 及其他 MCP 客户端所必需的。本地开发没有公网域名时,用隧道打通它:
设置隧道 URL
MCP_PUBLIC_URL: 'https://abc123.ngrok-free.app'
参见 ChatGPT Apps。
健康圈(Care circles)
在单用户内核之上的可选分享功能。规模由上限约束(0 禁用对应项):
CIRCLE_MAX_PER_USER: 5 # 一个用户可拥有的最大圈子数
CIRCLE_MAX_MEMBERS: 5 # 每个圈子的最大成员数(待处理的邀请也计入)
分享默认关闭;AI 助手对另一位成员的数据是只读的。参见 架构概览。
对话限流
对每个用户的 Agent / 实时轮次设上限:
CHAT_RATE_MAX: 5 # 每个用户每个窗口的最大轮次(0 = 不限)
CHAT_RATE_WINDOW_SEC: 60 # 窗口长度(秒)
远程配置(可选)
从一个服务而非本地文件拉取配置 —— 仅当三者都设置时生效:
# 经环境变量:
# CONFIG_SERVER=https://config.example.com
# CONFIG_TOKEN=<作为 X-Config-Token 发送的 bearer>
# ENV=prod # 选择远程环境
配置最佳实践
- ✅ 提交
config.example.yml
- ❌ 绝不提交带真实凭据的
config.yml(它默认已被 git 忽略)
- ✅ 经环境变量提供
CONFIG_ENCRYPTION_KEY,而非写进文件
- 把每一个
REPLACE_THIS_VALUE_IN_PRODUCTION 占位符替换成强随机值
- 当其他服务需要校验你的令牌时,使用 RS256(
JWT_PRIVATE_KEY)
- 生产环境限制 CORS origin
- 让 PHI 留在设备本地,或把托管 LLM 调用经 BAA 覆盖的通道路由(Vertex AI / Azure OpenAI)
python3 -c "import yaml; yaml.safe_load(open('config.yml'))"
没有输出表示语法有效。服务器也会在启动时报告配置错误,而不是静默降级。
下一步
API 参考
HTTP、WebSocket、MCP 和 FHIR 端点