Agent 系统常维护两份 schema(推理层和 UI 层),导致漂移和适配器蔓延;解决方案是用同一份 schema 驱动两层。
你的 agent 不知道什么是 Booking。它可以猜测——通常也能猜得很对——但一旦它组织工具调用、验证操作或向人类呈现结果,猜测就成了 bug。
本体论为模型提供了你的领域的类型化契约:什么存在、什么与什么相关、什么是允许的。它也说明了为什么直接添加到普通应用会失败,以及这次如何让它真正有效。
问题开始于当你把本体论接入常规代码库时。你最后得到两份契约:一份给 agent(RDF 三元组、JSON-LD 上下文、SHACL 形状),一份给 UI(props、组件、验证)。漂移是必然的。agent 产生一个 Reservation,API 暴露一个 Booking,UI 期望一个 ReservationViewModel。六个月后,你的团队有一半人在编写适配器,连接本应一致的各层。问题不在于 schema;问题在于有两个 schema。
核心论点是:给 agent 奠基的 schema 应该是给 UI 类型标注的同一个文件。当这成立时,本体论就不再是研究工件,而成为产品表面。
语言模型把每个 prompt 视为一串全新的令牌。它对类型、身份、关系没有一级概念——只有统计相似度。本体论给它一些可以依靠的东西:一个具有显式语义的词汇表、一个类型化关系的图,以及一组约束。
{
"@context": {
"@vocab": "https://schema.otf-kit.dev/booking#",
"schema": "https://schema.org/",
"Customer": "schema:Person",
"startsAt": { "@id": "schema:startDate", "@type": "schema:DateTime" },
"endsAt": { "@id": "schema:endDate", "@type": "schema:DateTime" }
},
"@type": "Booking",
"@id": "booking:42",
"name": "Sauna slot — Friday",
"Customer": { "@id": "person:7", "name": "M. Vargas" },
"startsAt": "2026-06-05T18:00:00Z",
"endsAt": "2026-06-05T19:00:00Z"
}
这里有两点很重要。首先,@context 声明 agent 必须遵守的 schema——那是契约。其次,每个字段都是 URI,这意味着 SPARQL 端点、SHACL 验证器和你的组件层都可以不经翻译地使用同一形状。agent 不是在创造结构;它在填充一个类型化的表单。
收益不是"AI 理解你的数据"。收益是 agent 的错误变得可恢复。形式不合的 startsAt 被 SHACL 拒绝。缺失的 Customer 违反 schema。虚幻的字段在到达用户前被拒绝。
推销成功了。工程开始。三样东西首先崩溃:
三元组存储在读路径上很慢。SPARQL 端点和具名图存储非常适合联邦和推理。当移动客户端需要在 100ms 内渲染 200 个 booking 列表时,它们糟透了。
Schema 漂移。agent 的 Reservation 成为 API 的 Booking,成为 UI 的 ReservationViewModel。每层都创造自己的类型别名,因为没什么东西强制收敛。
移动客户端无法承载一个图。2 GB 的 RDF 转储不是手机的有效载荷。你需要一个平铺的、反范式化的投影,但仍然尊重 schema。
这些不是特殊问题——它们是每个类型化系统遇到无类型邻居时都会碰到的同样集成问题。修复是一直以来的修复:在接缝处钉死契约,让每个使用者从它读取。
停止在两个地方存储 schema。把它放在一个文件里,让 agent 和 UI 都从中读取。agent 读它作为接地的 JSON-LD 上下文;UI 读它作为组件的类型系统。
// schema.otf.ts — 每层都导入的文件
export const BookingSchema = {
"@context": "https://schema.otf-kit.dev/booking",
"@type": "Booking",
fields: {
id: { type: "id", required: true, uri: "schema:identifier" },
name: { type: "string", required: true },
customer: { type: "ref:Person", required: true, uri: "schema:customer" },
startsAt: { type: "datetime", required: true, uri: "schema:startDate" },
endsAt: { type: "datetime", required: true, uri: "schema:endDate" },
status: { type: "enum", values: ["pending","confirmed","cancelled"] },
},
} as const;
agent 获得 @context 和字段映射作为系统指令。组件层获得同一映射作为 TypeScript 类型。schema 文件是真实来源;构建从它发出两个工件——一个给模型,一个给运行时。
[[DIAGRAM: schema.otf.ts → JSON-LD context for the agent, TS types for the UI, SHACL shape for validation — all three consumers reading one file]]
SPARQL 端点仍然可以支持数据;UI 从不说 SPARQL。schema 文件成为投影规范——一个图的类型化视图,不是图本身。
如果 schema 是契约,SHACL 形状就是契约的免疫系统。它们在形式不合的图进入你的管道前拒绝它们。关键是在 agent 穿过的边界处运行验证,而不是深入应用内部。
ex:BookingShape a sh:NodeShape ;
sh:targetClass ex:Booking ;
sh:property [
sh:path schema:startDate ;
sh:datatype xsd:dateTime ;
sh:minCount 1 ;
] ;
sh:property [
sh:path ex:status ;
sh:in ( "pending" "confirmed" "cancelled" ) ;
] .
agent 产生 JSON-LD;SHACL 验证器接受或拒绝它。组件层信任验证器返回的东西。移动客户端只承载经验证的有效载荷——这是为什么一个 200 行的列表保持小而可预测,大约每条记录 200-400 个令牌,并快速渲染。
这是收益加倍的地方:验证、类型检查和渲染都读取同一个 schema。没有第二个真实来源来漂移。
一旦 UI 绑定到类型化的实体而不是自由形式的 props,跨平台问题就解决了。Booking 在 web、iOS 和 Android 上都是 Booking——同样的字段名、同样的验证、同样的状态枚举。组件层读取 schema 并渲染实体;表面适配。
<BookingCard
booking={entity} // type: Booking (from schema.otf.ts)
onCancel={() => mutate(status)} // status enum from schema
/>
没有 <BookingCardWeb> 和 <BookingCardNative> 有不同的字段期望。当 schema 获得一个 cancellationReason 字段时,类型系统标记每个使用者——包括 agent 的工具定义——组件渲染它而无需分别向每个平台提交 PR。同样的组件名 + props + 外观在来自一个代码库的每个表面上渲染。
[[COMPARE: freeform props invented per platform vs schema-bound entities locked to one file]]
这是当模型改变时不改变的部分。schema 文件的寿命超过任何特定的 LLM。组件层的寿命超过任何特定的 agent 框架。验证规则的寿命超过任何特定的工具运行器。
这是接缝:agent 是 schema 的使用者,UI 是 schema 的使用者,schema 是持久表面。工具在变——今天的模型、明天的 MCP 服务器、下季度的编排器——但契约就是契约。
当 AI 配置与 schema 并存——组件层读取其类型的同一个地方——agent 扩展工具包而不是重新生成它。一个已文档化的 CLAUDE.md、一个 .cursorrules 和一组经过测试的 ai/prompts/ 给 agent 与 schema 给运行时的同样接地。agent 和应用最终在同一个世界上推理。
[[CONCEPT: the schema file as the single source of truth — one file, two consumers, zero drift]]
这是不会变的部分。你交换模型,schema 保留。你交换 agent 框架,schema 保留。组件渲染 schema 说可渲染的任何东西,在你发送到的任何表面。
Agent 错误失败很响亮,不沉默。SHACL 在形式不合的 startsAt 打到用户前拒绝它。UI 永远不必防御坏数据,因为坏数据永远不会到达。
移动保持快速。booking 的平铺、经验证的投影大约是 200-400 个令牌。承载一个图是替代方案,它装不进手机——100ms 列表渲染胜过联邦 SPARQL 查询。
重构只接触一个文件。添加 cancellationReason 更新 schema、agent 的工具定义、SHACL 形状和组件类型于一举。diff 是局部的;爆炸半径是一个文件。
语义网不是研究转向——它是一个等待 agent 的类型化契约模式。困难部分不是本体论。困难部分是让 schema 成为触及它的每层的真实来源。那是大多数团队跳过的部分,那是后来让他们付出六个月代价的部分。
钉死契约。让其他所有东西都在变。
更多行动,你可以考虑屏蔽这个人 /或报告虐待