跳转到主要内容

Agent

Mirobody 运行一个简单的 Agent —— “Base”,定义在 res/agents/base.cpp。它刻意保持极简:没有 Agent 循环,没有 planner,没有中间件。每一轮它会:
  1. 按 provider 名称选择一个 LLM 客户端(使用请求指定的 provider,否则用默认值)。
  2. 构建 system prompt —— 一段固定的内联字符串,包含当前时间、回复语言,以及引导去获取上传文件(list_files / read_file)和健康记录(family_health)的说明。
  3. 把 provider 的事件直接流式返回,让模型按需调用内置的 MCP 工具
你选择的是一个 模型provider),而不是 Agent 类型 —— Mirobody 运行单一 Agent。

支持的提供商

该 Agent 注册最多四个 provider 客户端(各自以 /api/providers 选择器展示的模型名为键)。前三个始终会注册,因此它们会出现在选择器中;其中未配置凭据的那个,只会在调用时报错。
Provider key模型客户端工具执行
gemini-2.5-flashGoogle Gemini 2.5 Flash(默认GeminiClient本地,进程内
gpt-5-nanoOpenAI GPT-5 nanoOpenAIChatClient本地,进程内
mirothinker-1.7MiroThinker(MiroMind)MiroThinkerClient通过 MCP_PUBLIC_URL 使用 provider 原生 MCP
gemma-4-e2b端侧 Gemma 4 E2BOpenAIChatClient(本地端点)取决于服务栈
原生应用还会在端侧运行 Gemma 4 E2B(Android/iOS 上用 LiteRT-LM,Electron 上用 llama.cpp)—— 离线、无需密钥。上表中的 gemma-4-e2b 是同一个模型,通过本地 OpenAI 兼容端点(Ollama / llama.cpp / vLLM)提供服务,仅在配置了 base URL 时才注册。
工具的运行方式因 provider 而异。 OpenAI 和 Gemini 把工具作为 function-call 描述符接收,引擎以已认证用户的身份在本地进程内执行每次调用。MiroThinker 则在 provider 侧运行工具 —— MiroMind 通过公网在 MCP_PUBLIC_URL 反向访问你的 /mcp 端点。

配置

Provider 使用 config.yml 中的扁平键配置(参见 配置)。没有 PROVIDERS_DEEP 块。
config.yml
# OpenAI (gpt-5-nano)
OPENAI_API_KEY: 'your_openai_key'
OPENAI_BASE_URL: 'https://api.openai.com'   # client appends /v1/chat/completions

# Google Gemini (gemini-2.5-flash, the default provider)
GOOGLE_API_KEY: 'your_google_key'

# MiroThinker (mirothinker-1.7) — provider-native MCP
MIROTHINKER_API_KEY: 'your_mirothinker_key'
MIROTHINKER_BASE_URL: ''      # optional override
MIROTHINKER_MODEL: ''         # optional override
MCP_PUBLIC_URL: 'https://your-domain.com/mcp'   # where MiroMind reaches your MCP

# On-device Gemma served over a local OpenAI-compatible endpoint (optional)
GEMMA_CHAT_BASE_URL: 'http://localhost:11434/v1'   # or OLLAMA_BASE_URL
GEMMA_CHAT_API_KEY: ''
GEMMA_CHAT_MODEL: 'gemma-4-e2b'

Agent 覆盖的范围

个人健康类问题几乎总是归结为:读取用户的记录 → 按需读取上传文件 → 按需检索长期记忆 → 作答,有时渲染一张图表。内置工具正好一一对应这些步骤,而模型会在单次流式回合内自行编排它们。

工具系统

什么是工具?

工具是 res/mcp_tools/ 中的 C++ 文件。每个文件声明一个 Tool(名称、描述、一个 auth 标志、一张小小的 Param 表以及一个 handler),并在编译时自注册。CMakeLists.txt 会把该目录下的每个 .cpp 都 glob 进构建(带 CONFIGURE_DEPENDS),因此只需丢入一个新文件并重新构建即可 —— 无需手动注册,无需手写 JSON schema。
这是编译期机制:工具从 res/mcp_tools/ 编译进程序,而非从运行时目录加载。

九个内置工具

工具Auth用途
list_files列出用户上传的文件
read_filefile_key 读取一个上传文件
family_health读取用户或已共享护理圈成员的近期 FHIR Observation
whoami确认认证状态,返回 session id
recall_memory检索用户最相关的长期记忆
remember在长期记忆中存储一条事实
render_chart在聊天界面绘制图表(Apache ECharts)
summarize_conversation为当前对话设置一个简短标题
echo回显文本(示例 / 连通性测试)
各工具的参数与返回结构见 内置工具

添加一个工具

创建 res/mcp_tools/<name>.cpp,声明一个 Tool,并用 MIROBODY_REGISTER_TOOL(...) 宏注册 —— 然后重新构建:
res/mcp_tools/echo.cpp
#include "mcp/tool.hpp"
#include <rapidjson/document.h>

namespace {
using namespace mirobody::mcp;

Result echo(const Args& args, const UserInfo&, const ToolContext&) {
    const std::string text = args.str("text");
    rapidjson::Document d;
    d.SetObject();
    rapidjson::Document::AllocatorType& a = d.GetAllocator();
    d.AddMember("echo",
                rapidjson::Value(text.c_str(),
                                 static_cast<rapidjson::SizeType>(text.size()), a), a);
    return Result::ok(to_json(d));
}

const Tool kEcho = {
    "echo",
    "Echo back the provided text.",
    false,                                                    // auth
    { Param("text", Type::String, Required, "Text to echo back") },
    &echo,
};
}   // namespace

MIROBODY_REGISTER_TOOL(kEcho);
Auth 范围内的工具将 auth = true,并以 UserInfo 接收调用者身份;handler 需要的其它一切(缓存、对象存储、数据库、长期记忆)都通过 ToolContext 送达。完整流程:添加自定义工具

MCP 端点

引擎通过 src/mcp/ 提供的 MCP 端点对外暴露其工具。它使用 JSON-RPC 2.0
http://localhost:8080/mcp                 # authenticates via bearer JWT
http://localhost:8080/mcp/{secret}        # personal-MCP secret resolving to a user
支持的方法包括 tools/listtools/call。本地开发时,把端口打通隧道(例如 ngrok http 8080)并设置 MCP_PUBLIC_URL,以便远端客户端 —— 以及 MiroThinker 的 provider 原生 MCP —— 能够访问它。参见 MCP 集成 连接 Claude、Cursor 和 ChatGPT。
curl -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

健康数据存放在哪里

family_health 这样的工具不会命中临时表 —— 它们通过内嵌的 FHIR R4 存储src/fhir/)读取,返回 FHIR Observation 资源。数据在进入时会被归一化(单位转为 UCUM),而关系型后端是在构建期通过 CMake(-DMIROBODY_DATABASE_BACKEND=)选定的:SQLite(移动端默认)、PostgreSQL(桌面端默认)、MySQL、DuckDB 或 ClickHouse。SQL schema 位于 res/sql/pgsqlitemysqlduckdbclickhouse)。完整图景见 架构

下一步

内置工具

默认提供的九个工具

添加自定义工具

编写你自己的 C++ 工具

MCP 集成

连接 Claude、Cursor 和 ChatGPT

添加 MCP

连接外部 MCP 服务器