首页/运维/运维管理

运维管理

管理端负责四件事:谁能用(用户与授权)、 能用什么(数据源与 KB)、自动跑什么(定时任务)、 以及留下什么(记忆与保留策略)。

用户与凭据

初始管理员的密码由 TROVE_ADMIN_PASSWORD 决定;不提供时随机生成一个 20 位密码,只在首次引导时打印一次。所以第一次启动的输出要留住。

main.py:157 TROVE_ADMIN_PASSWORD service.py:141 token_urlsafe

用户管理走 /v1/admin/users 一组端点(增删改查)。每个用户可以签发多个 token (便于轮换与按用途区分),token 形如 trove_ + 32 字节随机串, 默认有效期 720 小时。密码用 PBKDF2 哈希存储。

admin.py:165 users service.py:270 token_urlsafe

三个层次,别混

层作用在哪管
账号角色admin / 非 admin,决定能否进管理端用户页面
数据源授权(grants)这个用户能问哪些源用户页面
工具 ACLanalyst 角色,决定 catalog 工具可见性运行时角色解析

grants 有三种取值,是三个不同的语义,别混:

取值含义
None拿不到授权依据 → 拒绝一切,不查任何数据源
空集合有依据、依据为空 → 只放行默认数据源
非空集合严格白名单

三种取值都落在「安全的一侧」:忘了授权不会放出全部数据源,读不到授权依据也不会退化成放行。

flowchart TB
    U["用户"]:::entry --> L1["① 账号角色
admin / 非 admin → 能否进管理端"]:::gate U --> L2{"② 数据源授权 grants
这个用户能问哪些源"}:::gate U --> L3["③ 工具 ACL
analyst 角色 → catalog 工具可见性"]:::gate L2 -- "None" --> R1["拿不到授权依据
拒绝一切,不查任何数据源"]:::err L2 -- "空集合" --> R2["有依据、依据为空
只放行默认数据源"]:::entry L2 -- "非空集合" --> R3["严格白名单"]:::entry classDef entry fill:#71717a14,stroke:#71717a59,stroke-width:1px; classDef gate fill:#f59e0b14,stroke:#f59e0b99,stroke-width:1.5px; classDef err fill:#dc262614,stroke:#dc262699,stroke-width:1.5px;
图 1 · 三层各管各的,别混。grants 的三个取值是三件不同的事——但都落在安全的一侧:忘了授权不会放出全部源,读不到授权依据也不会退化成放行。 上面这段以源码显示:图渲染库没加载起来(离线、CDN 被拦或浏览器禁用了 JavaScript 时会这样)。这段 Mermaid 文本本身就说明了上面那些框与连线。

policy.py:146 Principal deps.py:187 require_datasource

数据源与 KB

注册流程在接入数据源里讲了。这里补充管理端的操作要点:

操作注意
注册 注册即探测,失败 400 并给出原因;同名不同身份会 409 拒绝
KB 初始化 异步任务(返回 202),可查状态;会调 LLM,有成本
KB 重载 同样是 202 + task_id;无条件重读全部 YAML,重建镜像并把条目重推给检索后端
测试连接 非破坏性探测,排障时先用它

admin.py:824 datasources admin.py:1097 kb admin.py:1039 test-connection

重载不是「改完 YAML 的必经步骤」:下一次提问会按内容摘要判断文件动没动过, 动过就重读,镜像与检索库一起更新(pg_hybrid / rag 有索引钩子,builtin 直接读镜像,没有推送这一步)。 重载的价值在无条件——它先清空同步摘要表再全量重读, 所以能修「镜像认为文件没变、检索库却落后」这类不一致。 它与初始化共用同一个按数据源键控的任务槽:同源已有任务在跑时返回 409,而不是排队等。

admin.py:1189 kb/reload service.py:962 force_sync pg_hybrid.py:111 index_file

KB 的确认队列在这里

自动回写的示例、蒸馏出的教训、自动学习的偏好,都停在 pending 等确认。 这个队列是管理端最该定期看的东西——它直接影响准确率, 而且积压久了会让人忘记上下文,确认质量下降。

定时任务

定时任务就是「按计划重复问一个问题」。它复用同一条查询链路, 只是多了调度、告警与冷却。

service.py:40 JobsService store.py:3 jobs.sqlite

支持 interval 与 cron 两种调度。告警评估在任务跑完后进行,带冷却窗口 (默认 30 分钟)——否则一个持续异常每轮都报,很快就会没人看。

两个容易出事的地方

① 内嵌 tick 与 CLI daemon 不能同时跑

trove serve 在生命周期里自带一个调度 tick(默认每 30 秒扫一次), 不需要另起 trove-cli schedule --daemon。 两个一起跑会把到期的任务执行两遍。

想让 serve 不调度,把轮询间隔设为 ≤0,改用外部 daemon。

main.py:421 内置调度 app.py:177 _job_tick config.py:523 scheduler_poll_seconds

② 定时任务会自动批准 HITL

任务跑出来的 SQL 如果停在待确认状态,调度器会直接以「批准」继续—— 否则无人值守的任务会永远卡住。

这意味着开 HITL 的任务不会得到人工复核。如果你的场景需要「定时跑但结果要人看过才能用」, 应该用告警+通知,而不是 HITL。

runner.py:92 approve

结果集有行数上限(200 行),避免一个失控的任务把大结果灌进通知里。

记忆运维

记忆子系统有三块需要管理端介入的地方:

端点作用
GET /v1/admin/memory/profile按(用户 × 数据源)看正确率、失败模式、已确认事实
GET /v1/admin/memory/preferences自动学到的偏好草稿
POST .../confirm · .../reject逐条处置

admin.py:1585 profile admin.py:1608 preferences

偏好草稿的来源是会话压缩时的 LLM 抽取:高置信度的候选直接进 user_facts, 低置信度的落到待确认队列。明确的一律不自动注入—— 详见记忆子系统。

保留策略与周期维护

默认不清理任何东西。清理需要显式配 retention_days, 否则那些字段是空的(配置里对应项是注释掉的)。

models.py:75 retention_days service.py:405 run_lifecycle

为什么默认是不清理

默认清理是危险的方向:一个配错的保留期会静默删掉数据,而「没清理」最坏只是占磁盘。 对一套以「积累知识、越用越准」为卖点的系统来说,默认删数据的代价更大。

周期维护是另一件事——会话数量配额、孤儿会话、检查点深度、过期清扫。 这些有独立的默认值(如每用户 100 个会话、24 小时一轮清扫), 由服务的周期任务驱动。

maintenance.py:326 run_all app.py:245 run_lifecycle

注意「会话维护」与「记忆保留」是两套独立的东西: 前者管会话与检查点的数量(默认开),后者管记忆内容的过期(默认关)。 混在一起理解会得出错误的预期。

继续读

想了解去哪
授权与安全的设计安全边界
记忆分层与门禁记忆子系统
定时任务用到的 CLICLI 参考
相关配置项配置参考
本页源码锚点的基准提交:anchor-base: 211ae86 GitHub 仓库 文档首页