连接一个源
本页解释通用的连接器模型,以及如何把一个真实的源接入引擎。如果你只想连接一个编码智能体,请从 连接 Claude Code 开始——那是协作路径上的一个具体的源,而本页是 它底下的模型。
一个源只做一件事:它观测一个外部系统并发出归一化的观测结果。它从不位于数据路径上、从不 代理(proxy)流量,也从不读取载荷。R/RW access map 是由源所报告的内容构建的,而非由拦截流经的 内容构建的。
具体而言,一个源实现一个小接口——Open(一次性配置)、Gather(运行,发出)、Close(释放)——
并在 Gather 期间通过一个 sink 一次一条地把观测结果交给引擎。引擎掌握调度:流式源(日志 tail、
接收端)在 Gather 中阻塞并持续发出,直到被取消;批处理源完成其工作后返回,由引擎决定何时再次
运行它。连接器从不拥有自己的计时器。
源可以发出的观测结果恰好只有四种:
| 观测结果 | 它携带什么 | 由谁使用 |
|---|---|---|
edge |
某个发起方(智能体 / 身份 / 会话)以读/写模式触及了某个资源 | R/RW access map |
cost |
模型/提供商用量成本 | FinOps |
finding |
一项 guardrail / 红队 / 取证发现 | 安全 |
metric |
非成本的度量值 | 生产力和采用情况指标 |
这个集合是经设计封闭的——第三方无法引入新的观测种类。引擎将每条发出的观测结果提升(lift) 到进程内事件总线上,模块在那里消费它,而无需与产生它的源耦合。具体到 access map,引擎会把连接器 的字符串引用解析为实体,并把观测结果合并进一条持久化的 access edge。
连接器采用 Apache-2.0 且从不导入 core
Section titled “连接器采用 Apache-2.0 且从不导入 core”一个连接器导入连接器 SDK,并且不从产品中导入其他任何东西。它从不导入 /core(AGPL 引擎)。
该边界在 CI 中强制执行,正是它让连接器得以在 Apache-2.0 下发布,也让第三方得以构建自己的连接器
而无需面对 copyleft 的摩擦。同一个连接器二进制无论在进程内还是通过 gRPC 在进程外运行,行为完全一致。
完整边界参见 开放内核与许可。
同一连接器 kind 的多个源现在可以同时登记并运行(CHANGELOG.md [26.9.0]
Fixed)。运行时曾用连接器的 Descriptor 名作为每个源的键,因此同 kind 的第二
行名册会被持久化并列出——但引擎拒绝它。源现在按操作者自己的名称(名册行的
name)登记,连接器 descriptor 放在旁边。grok-home-a 与 grok-home-b 各自
打开自己的配置和凭证引用,运行自己的连接器实例和进程,并独立轮换、失败和停
止。sources plan / validate 不再宣布引擎已停止应用的“每种连接器一个实例”
限制。由一个连接器服务的两条身份记录(okta 与 entra 共享 idp)在
as_source: true 时现在会接好两者。这本身不会端到端分开两个提供商会话或配置
主目录——那是
运行提供商会话。
来源与置信度:为什么源很重要
Section titled “来源与置信度:为什么源很重要”每条 edge 都记录是哪个源产生了它以及一个置信度级别,且产品同时展示二者,而不是把它们
合并掉。一条 pg_audit READ 与一条 mcp_annotation 提示并非同等证据,绝不会被当作同等看待。
这两个置信度级别是诚实的,而非粉饰:
attributed——该访问被牢固地系到其发起方上(例如,审计轨迹中存在的某个每智能体身份)。approximate——归因是推断出的或有损的(共享的服务账户,或一个其审计无法干净地区分调用者 的存储)。
访问模式是 unknown、read、write、readwrite 之一。unknown 是显式的、从不臆测——产品宁可
显示“我们无法对此分类”,也不会编造一个读/写标签。
第一方源的类别,按信号划分
Section titled “第一方源的类别,按信号划分”第一方源因其携带的信号而不同。请按你所观测的系统能够诚实地告诉你的内容来选择源。
pg_audit——PostgreSQL READ/WRITE
Section titled “pg_audit——PostgreSQL READ/WRITE”pgAudit 源 tail PostgreSQL 自身的结构化审计日志,并为每一次受审计的数据访问发出一条 edge。读/写
模式逐字取自 pgAudit 的 CLASS 字段(READ、WRITE、DDL)——从不从 SQL 文本中推断。发起方是日志将
该访问归因到的角色或 application_name。该连接器对日志文件是只读的;它从不连接到数据库,也从不
向数据库写入。这是干净层:一个在其原生轨迹中对访问进行分类的对象/关系型存储。
cloudtrail——AWS S3 readOnly
Section titled “cloudtrail——AWS S3 readOnly”CloudTrail 源读取 CloudTrail 日志文件并为每个 S3 事件发出一条 edge。读/写模式逐字取自 CloudTrail
的 readOnly 字段,从不推断。发起方是 CloudTrail 将该调用归因到的 IAM 主体。一个被许多调用者共享
的 assumed role 会被刻意标记为 approximate,因为轨迹无法区分其背后真正的调用者。
otel——协作式智能体
Section titled “otel——协作式智能体”这是协作路径:一个发出 OpenTelemetry 工具遥测的智能体报告它做了什么,引擎将其摄取。Claude Code 是 这里的标准第一方源,它把 OTLP 遥测与 MCP 内省结合起来——参见 连接 Claude Code。协作式遥测在存在时是保真度最高的信号,但它 取决于智能体是否协作,这正是为什么存在一个内核兜底。
ebpf——Tetragon 内核兜底(非协作路径)
Section titled “ebpf——Tetragon 内核兜底(非协作路径)”eBPF 源是这张图的反规避一半:协作路径看到智能体报告了什么,而这一半看到内核实际做了什么——文件 读/写和网络连接——即使在某个智能体关闭了自己的遥测时也能看到。它运行在智能体的控制之外。
两条诚实的约束界定了它:
- 它不自行加载 eBPF 程序。内核捕获由 Tetragon 完成,后者作为一个单独的、经加固的服务部署; 本源是 Tetragon 事件流的只读消费者,自身不需要任何内核能力。
- 它对 TLS 体是盲的。它观测访问关系,绝不观测载荷。
它的 edge 始终是 approximate,原因很具体:内核把一次访问归因到一个进程或容器——一个运行时身份——
而非一个已解析的智能体。访问本身是 ground truth(系统调用确实发生了);置信度限定的是归因,一旦
access-map 模块把该身份系到某个智能体上,归因便会被升级。
mcp_annotation——不可信
Section titled “mcp_annotation——不可信”MCP 内省源列出一个服务器的工具、资源和提示词,并从每个工具的 readOnlyHint / destructiveHint
推导出一个读/写提示。按照 MCP 规范,除非服务器本身可信,否则客户端必须把这些注解视为不可信,
且其默认值是非对称的。因此这个信号是一个声明的能力提示,绝非已观测的访问:每一条这样的 edge
都是 approximate,且被标记为既非已观测也非已许可。它提供用于做差异比对的能力表面——而不是任何
事情确实发生过的证据。它必须由一个已观测的源加以佐证,绝不能单独信任。
硬性依赖:每智能体身份
Section titled “硬性依赖:每智能体身份”归因的优劣只取决于底层系统所记录的身份。原生审计把一次访问归因到一个凭据或角色,而非一个智能体。
如果许多智能体共享一个服务账户或一个连接池,每一次已观测的访问都会塌缩到那单一身份上,归因便变成
approximate——产品会如实说明,而不是假装它能区分这些智能体。
要获得 attributed 的 edge,请给每个智能体各自的身份。这是通往治理的桥梁:签发或强制执行每智能体身份
正是让 access map 变得锐利的关键。
分层覆盖——务实一点
Section titled “分层覆盖——务实一点”覆盖按一个系统的审计表面能诚实支持到何种程度来分层:
- 干净(Clean)——原生地对访问分类的 SQL 数据库、对象存储和数仓(Postgres、S3 及同类)。读/写 逐字取用。
- 有损(Lossy)——其审计无法干净地区分读与写、或区分调用者与调用者的存储(文档存储和向量存储)。
edge 仍会落地,但常为
approximate。 - 被动方式不可能(Impossible passively)——没有可用被动审计表面的系统(内存缓存、嵌入式单文件 数据库)。没有诚实的 read-first 信号可供捕获;产品不会假装不是这样。
请有意地挑选层级。一个具备每智能体身份的干净层存储,是 access map 最锐利之处。
连接一个真实的源
Section titled “连接一个真实的源”真实(非演示)源通过一个名为环境变量 OLIVARES_SOURCES_CONFIG 的单一运维配置文件连接,该文件
在引擎启动之前被读取。该配置是一个 JSON 文档;密钥存放于该文件中(按值引用),且从不由引擎
持久化。
该文档声明一个源的列表。每个源条目按 kind 选择一个连接器,命名其观测结果所属的租户,并携带连接器 自身的设置。其总体形态为:
{ "sources": [ { "name": "prod-postgres", "kind": "pgaudit", "tenant": "acme", "config": { "...": "connector-specific settings" } } ]}每连接器 config 块之上的字段——一个源名称、连接器 kind、所属 tenant,以及批处理源的一个可选
轮询间隔——构成稳定的连接契约。
一个未配置的源会如实告警
Section titled “一个未配置的源会如实告警”启动时会区分未设置的变量和已指定的配置文件:
- 如果
OLIVARES_SOURCES_CONFIG未设置,引擎在没有任何源的情况下启动。 - 如果指定的文件缺失、不可读或不是有效 JSON,
olivares serve会以退出码1退出。错误以load sources operator config: OLIVARES_SOURCES_CONFIG开头,并包含refusing to start instead of silently omitting operator configuration。 - 如果源列表为空,引擎会告警:没有连接器会进行摄取,并且该 estate 正在没有任何实时流量的情况下 运行。
如果已指定文件,请修复路径、读取权限或 JSON,然后重启。引擎拒绝静默省略运维方配置。
这在哪里运行
Section titled “这在哪里运行”数据平面——运行这些源的采集器——始终运行在客户基础设施上,无论 control plane 是单个 self-hosted 二进制、分布式部署,还是 air-gapped。源在本地观测,引擎进行摄取。产品没有强制遥测,控制平面默认也 不产生出站流量。只有你明确配置为跨越边界的内容才会跨越你的边界——对你的模型 API 的调用、你接入的 SIEM/webhook 输出,以及你配置时使用的外部嵌入提供商。部署拓扑参见 自托管 与 气隙安装。
- 连接 Claude Code——端到端的协作式
otel路径。 - 模块概览——消费这些观测结果的模块(清单、R/RW access map、 FinOps、安全)。
- 架构概览——连接器 SDK、事件总线与 access map 在设计中 所处的位置。