摘要:本文从丰田生产方式的"自工程完结"理念出发,探讨如何将"安灯绳"机制引入AI Agent系统。通过流马(Gliding Horse)Agent操作系统的实践,展示了如何利用SHACL契约、系统调用门(Syscall Gate)和知识图谱追溯,实现AI产出的质量硬拦截,确保每个Agent工序"不制造、不流出缺陷",从根本上提升LLM的指令遵守能力。
关键词:自工程完结;安灯绳;AI Agent;LLM指令遵守;质量拦截;流马;Gliding Horse;系统调用门;SHACL契约;知识图谱
TPS的"自工程完结"教会了我一件事:别把Bug留给下一道工序
我之前在丰田的工厂里看到过一个场景,震撼至今:
流水线上,一个工人发现面前的车门有点歪,他直接拉下了头顶的一根红绳。整条生产线,停了。没有人骂他,反而他的工长跑过来,和他一起把问题解决掉,才让线重新动起来。
后来我才知道,这根红绳叫"安灯绳"(Andon Cord),是丰田生产方式里最核心的机制之一。背后的哲学叫**"自工程完结"**------每个工序必须确保自己的产出是百分百合格的,绝不把问题留给下一道工序。
因为问题发现得越晚,修复代价越高。在流水线上是这样,在软件工程里更是这样。
于是我在想:能不能把这根红绳,装到我的AI Agent系统里?
一、"自工程完结"到底在说什么?
丰田的"自工程完结"有三个核心原则:
- 不接收缺陷:上一道工序流过来的东西有问题,直接拒绝,不凑合着往下干。
- 不制造缺陷:自己这道工序产出的东西,必须符合质量标准,不能因为赶进度就糊弄。
- 不流出缺陷:自己检查出问题,立刻停下来修,绝不把有问题的东西传给下一道工序。
翻译成软件工程的人话就是:需求阶段的问题,别留到设计阶段;设计阶段的问题,别留到编码阶段;编码阶段的问题,别留到测试阶段;测试阶段的问题,别TM留到上线后。
听起来像废话?但你想想平时是怎么干活的------需求没搞清楚就开始写代码,代码写完一堆Bug丢给测试,测试来不及就"先上线再说"。每个环节都在把问题往下游甩,最后上线炸了,所有人一起加班修。
丰田告诉我们:这根红绳越早拉,代价越小。在设计文档里改一行字,成本是1;在代码里改一个逻辑,成本是10;上线后炸了再修,成本是1000。
二、我的流马(Gliding Horse)怎么装上这根红绳?
流马是一个Agent操作系统,它的核心是让多个AI Agent协作完成软件工程任务------需求Agent、设计Agent、编码Agent、测试Agent,各司其职,按阶段传递产出。
如果我让这些Agent像普通流水线一样,产出什么就往下一阶段丢,那结果一定是灾难:需求Agent漏了一个边界条件,设计Agent基于不完整的需求画了架构图,编码Agent照着有问题的设计写了几千行代码,最后测试Agent发现问题时,已经晚了。
所以,我决定把丰田的"自工程完结"机制,原封不动地装进流马的系统调用门(Syscall Gate)里。
具体怎么装?三个步骤:强约束、硬拦截、速反馈。
第一步:契约------提前定义"什么叫合格"
在流马里,每个阶段的产出物(需求文档、设计文档、代码、测试报告)都必须满足一个提前定义好的SHACL契约------一种结构化的质量标准。
比如,需求Agent产出的PRD文档,契约会规定它必须包含:功能模块列表(至少一个)、用户角色定义、核心业务流程图、明确的验收条件。编码Agent产出的代码,契约会要求所有函数有类型注解、所有公开API有文档注释、单元测试覆盖率不低于80%。
这些契约不是AI自己猜的,是人提前定好的。就像丰田工厂里每个工位都有一个明确的质量标准清单,工人在干活前就知道"什么叫合格"。
第二步:红绳------产出前必须过"系统调用门"
当需求Agent觉得自己"完成了",想把产出传递给设计Agent时,它不能直接扔过去。它必须先把产出提交给流马的系统调用门(Syscall Gate)。
这个Gate就是AI世界的"安灯绳"。它会自动执行SHACL校验,检查产出是否满足预设的契约。校验通过,Gate放行,产出物被打上数字签名,正式"出厂"。校验不通过,Gate直接拒收,把具体哪里不合格的信息,反馈给Agent。Agent必须自己修正,直到通过校验为止。
这里的关键是:不是下游Agent去检查上游的产出,而是上游Agent自己必须产出合格品。Gate只是拿契约去对照,合格就过,不合格就拦。责任在产出者,不在接收者。
第三步:追溯------所有"拉绳记录"都写进知识图谱
每一次Gate拦截,每一次Agent修正,都会作为一个"质量事件"写入流马的L0持久化知识图谱。哪个Agent、在哪个任务、犯了什么错、修正了几次才通过------全都有记录。
这带来了两个好处。首先是责任透明 :你可以精确知道哪个环节最容易出问题。其次是经验复用:下次有类似任务时,SA调度器会自动把历史上犯过的错注入给新Agent,告诉它"上次类似的PRD少了用户角色定义,这次注意补上"。
丰田工厂里,每次拉绳都会被记录和分析,用于持续改进产线。流马也一样------质量事件不是用来追责的,是用来让整个系统越来越聪明的。
三、这根红绳能提升LLM的指令遵守吗?
答案是:能,但不是让LLM变得更听话,而是让它犯不了错。
LLM的本质决定了它一定会产生幻觉、一定会偷懒、一定会遗漏边界条件。你没法通过"更好的Prompt"来根治这些问题,就像你没法通过"跟工人说认真点"来杜绝次品。
但你可以设计一套机制,让这些错误在产生的第一时间就被抓住、被拦截、被打回修正。这套机制不依赖AI的自觉,依赖的是契约、校验和硬拦截。
这是我从丰田学到的最大一课:质量不是检出来的,是"造"出来的。 每个工序都对自己的产出负责,每个工序都有明确的质量标准,每个工序都有权利和义务在发现问题时拉下红绳。
四、流马开源,欢迎来玩
流马(Gliding Horse)的所有核心代码都在GitHub上开源,用Rust写成,图数据库用Oxigraph,记忆系统借鉴了CPU缓存架构,现在又装上了丰田的安灯绳。
如果你也对"给AI套缰绳"这件事感兴趣,或者觉得自工程完结、系统调用门、知识图谱追溯这些概念有点意思,欢迎来star、提issue、一起搞。
最后说句心里话:AI现在还处于"连个按钮都画不准"的阶段,与其等它变聪明,不如先给它装根红绳。流马想做的,就是把丰田工厂里的那根红绳,装到每一个AI Agent的手边。
GitHub地址:github.com/doiito/glid...
五、实战:为需求Agent定义SHACL契约
下面用一个具体的例子,展示如何为"需求Agent"的PRD产出定义一个SHACL契约,并在系统调用门中执行校验。
5.1 定义SHACL契约(YAML格式)
yaml
# prd_shacl_contract.yaml
# 需求Agent产出的PRD文档必须满足以下约束
prefixes:
schema: "http://schema.org/"
prd: "http://glidinghorse.dev/prd#"
# 1. 功能模块列表:至少包含一个功能模块
shapes:
- targetClass: prd:PRDDocument
propertyConstraints:
- path: prd:hasFeatureModule
minCount: 1
description: "PRD必须至少定义一个功能模块"
errorMessage: "缺少功能模块定义,请至少添加一个功能模块"
# 2. 用户角色定义:至少包含一个用户角色
- targetClass: prd:PRDDocument
propertyConstraints:
- path: prd:hasUserRole
minCount: 1
description: "PRD必须至少定义一个用户角色"
errorMessage: "缺少用户角色定义,请至少添加一个用户角色"
# 3. 核心业务流程图:必须包含流程图节点
- targetClass: prd:PRDDocument
propertyConstraints:
- path: prd:hasBusinessFlow
minCount: 1
description: "PRD必须包含核心业务流程图"
errorMessage: "缺少核心业务流程图,请补充业务流程描述"
# 4. 验收条件:每个功能模块必须有明确的验收条件
- targetClass: prd:FeatureModule
propertyConstraints:
- path: prd:hasAcceptanceCriteria
minCount: 1
description: "每个功能模块必须定义验收条件"
errorMessage: "功能模块 '{moduleName}' 缺少验收条件,请补充"
# 5. 功能模块名称不能为空
- targetClass: prd:FeatureModule
propertyConstraints:
- path: schema:name
minLength: 1
maxLength: 100
datatype: xsd:string
description: "功能模块名称不能为空且不超过100字符"
errorMessage: "功能模块名称无效,请检查"
5.2 系统调用门校验逻辑(Python伪代码)
python
# syscall_gate_validator.py
# 流马系统调用门------SHACL契约校验器
from typing import Dict, Any, List
import yaml
from rdflib import Graph, URIRef
from pyshacl import validate
class SyscallGate:
"""系统调用门:负责校验Agent产出物是否满足契约"""
def __init__(self, contract_path: str):
# 加载SHACL契约
with open(contract_path, 'r') as f:
self.shacl_graph = Graph().parse(data=f.read(), format='yaml')
def validate_prd(self, prd_data: Dict[str, Any]) -> Dict[str, Any]:
"""
校验需求Agent产出的PRD文档
参数:
prd_data: 需求Agent产出的结构化PRD数据
格式示例:
{
"feature_modules": [
{"name": "用户登录", "acceptance_criteria": ["支持密码登录", "支持验证码登录"]}
],
"user_roles": ["普通用户", "管理员"],
"business_flow": "用户输入账号密码 -> 系统验证 -> 登录成功"
}
返回:
{
"passed": bool, # 是否通过校验
"errors": List[str], # 未通过的详细错误信息
"suggestions": List[str] # 修正建议
}
"""
# 1. 将PRD数据转换为RDF图
prd_graph = self._convert_to_rdf(prd_data)
# 2. 执行SHACL校验
conforms, results_graph, results_text = validate(
prd_graph,
shacl_graph=self.shacl_graph,
inference='rdfs',
abort_on_first=False
)
# 3. 解析校验结果
if conforms:
return {
"passed": True,
"errors": [],
"suggestions": ["PRD校验通过,可以传递给设计Agent"]
}
else:
# 提取具体错误信息
errors = self._parse_validation_results(results_graph)
return {
"passed": False,
"errors": errors,
"suggestions": self._generate_suggestions(errors)
}
def _convert_to_rdf(self, prd_data: Dict) -> Graph:
"""将结构化PRD数据转换为RDF图(简化实现)"""
g = Graph()
prd_uri = URIRef("http://glidinghorse.dev/prd/current")
# 添加功能模块
for module in prd_data.get("feature_modules", []):
module_uri = URIRef(f"http://glidinghorse.dev/prd/module/{module['name']}")
g.add((prd_uri, URIRef("http://glidinghorse.dev/prd#hasFeatureModule"), module_uri))
g.add((module_uri, URIRef("http://schema.org/name"),
Literal(module['name'])))
# 添加验收条件
for criteria in module.get("acceptance_criteria", []):
criteria_uri = URIRef(f"http://glidinghorse.dev/prd/criteria/{hash(criteria)}")
g.add((module_uri, URIRef("http://glidinghorse.dev/prd#hasAcceptanceCriteria"),
criteria_uri))
g.add((criteria_uri, URIRef("http://schema.org/text"),
Literal(criteria)))
# 添加用户角色
for role in prd_data.get("user_roles", []):
role_uri = URIRef(f"http://glidinghorse.dev/prd/role/{role}")
g.add((prd_uri, URIRef("http://glidinghorse.dev/prd#hasUserRole"), role_uri))
# 添加业务流程图
if prd_data.get("business_flow"):
flow_uri = URIRef("http://glidinghorse.dev/prd/flow/main")
g.add((prd_uri, URIRef("http://glidinghorse.dev/prd#hasBusinessFlow"), flow_uri))
g.add((flow_uri, URIRef("http://schema.org/description"),
Literal(prd_data["business_flow"])))
return g
def _parse_validation_results(self, results_graph: Graph) -> List[str]:
"""解析SHACL校验结果,提取可读的错误信息"""
errors = []
for s, p, o in results_graph.triples((None,
URIRef("http://www.w3.org/ns/shacl#resultMessage"), None)):
errors.append(str(o))
return errors
def _generate_suggestions(self, errors: List[str]) -> List[str]:
"""根据错误生成修正建议"""
suggestions = []
for error in errors:
if "功能模块" in error and "缺少" in error:
suggestions.append("请检查PRD中是否遗漏了功能模块定义")
elif "用户角色" in error and "缺少" in error:
suggestions.append("请补充至少一个用户角色(如:普通用户、管理员)")
elif "验收条件" in error:
suggestions.append("请为每个功能模块补充验收条件,确保可测试")
elif "流程图" in error:
suggestions.append("请补充核心业务流程描述,至少包含主要步骤")
return suggestions
# ========== 使用示例 ==========
if __name__ == "__main__":
# 初始化系统调用门,加载契约
gate = SyscallGate("prd_shacl_contract.yaml")
# 需求Agent产出的PRD(故意缺少验收条件)
incomplete_prd = {
"feature_modules": [
{"name": "用户登录", "acceptance_criteria": []} # 验收条件为空!
],
"user_roles": ["普通用户"],
"business_flow": "用户输入账号密码 -> 系统验证 -> 登录成功"
}
# 执行校验
result = gate.validate_prd(incomplete_prd)
if not result["passed"]:
print("❌ 校验未通过!错误信息:")
for err in result["errors"]:
print(f" - {err}")
print("\n💡 修正建议:")
for suggestion in result["suggestions"]:
print(f" - {suggestion}")
else:
print("✅ 校验通过,可以传递给设计Agent")
5.3 关键校验点说明
| 校验点 | 契约要求 | 拦截效果 |
|---|---|---|
| 功能模块数量 | minCount: 1 |
防止需求Agent产出空PRD |
| 用户角色定义 | minCount: 1 |
确保考虑不同用户视角 |
| 验收条件完整性 | 每个模块至少1条 | 避免模糊需求,确保可测试 |
| 业务流程图 | minCount: 1 |
强制梳理业务流程,防止遗漏关键路径 |
这套机制的核心思想是:不是等下游Agent发现上游的问题,而是让上游Agent在产出时就被契约拦住,自己修正。 就像丰田工厂里的安灯绳------问题发现得越早,修复代价越小。