【Agent Harness】TPS的“自工程完结”教会了我一件事:别把Bug留给下一道工序

摘要:本文从丰田生产方式的"自工程完结"理念出发,探讨如何将"安灯绳"机制引入AI Agent系统。通过流马(Gliding Horse)Agent操作系统的实践,展示了如何利用SHACL契约、系统调用门(Syscall Gate)和知识图谱追溯,实现AI产出的质量硬拦截,确保每个Agent工序"不制造、不流出缺陷",从根本上提升LLM的指令遵守能力。

关键词:自工程完结;安灯绳;AI Agent;LLM指令遵守;质量拦截;流马;Gliding Horse;系统调用门;SHACL契约;知识图谱

TPS的"自工程完结"教会了我一件事:别把Bug留给下一道工序

我之前在丰田的工厂里看到过一个场景,震撼至今:

流水线上,一个工人发现面前的车门有点歪,他直接拉下了头顶的一根红绳。整条生产线,停了。没有人骂他,反而他的工长跑过来,和他一起把问题解决掉,才让线重新动起来。

后来我才知道,这根红绳叫"安灯绳"(Andon Cord),是丰田生产方式里最核心的机制之一。背后的哲学叫**"自工程完结"**------每个工序必须确保自己的产出是百分百合格的,绝不把问题留给下一道工序。

因为问题发现得越晚,修复代价越高。在流水线上是这样,在软件工程里更是这样。

于是我在想:能不能把这根红绳,装到我的AI Agent系统里?

一、"自工程完结"到底在说什么?

丰田的"自工程完结"有三个核心原则:

  1. 不接收缺陷:上一道工序流过来的东西有问题,直接拒绝,不凑合着往下干。
  2. 不制造缺陷:自己这道工序产出的东西,必须符合质量标准,不能因为赶进度就糊弄。
  3. 不流出缺陷:自己检查出问题,立刻停下来修,绝不把有问题的东西传给下一道工序。

翻译成软件工程的人话就是:需求阶段的问题,别留到设计阶段;设计阶段的问题,别留到编码阶段;编码阶段的问题,别留到测试阶段;测试阶段的问题,别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在产出时就被契约拦住,自己修正。 就像丰田工厂里的安灯绳------问题发现得越早,修复代价越小。

相关推荐
烬羽1 小时前
中英文 token 数量差一倍?两段 JS 代码搞懂 LLM 底层是怎么"读"文字的
javascript·程序员·架构
白鲸开源4 小时前
一文读懂DolphinScheduler插件机制:如何轻松扩展任务类型与数据源
java·架构·github
棒槌开发师4 小时前
动态组件设计(elpis)
架构
得物技术9 小时前
从表单到 Agent:得物社区活动搭建的 AI 实践之路
人工智能·架构·agent
Ausra无忧9 小时前
记录在公司把单服务器升级成多服务器架构流程
前端·后端·架构
不好听6139 小时前
拆解 LLM Tool Use 的完整机制:从缸中大脑到 Agent 觉醒
架构·llm·agent
starsstreaming10 小时前
200K 的窗口,跑完 400K 的任务:Claude Code 上下文压缩机制全拆解
架构
禅思院10 小时前
前端部署“三层漏斗”完全指南:从CI/CD到自动回滚的工程化实战【基石】
前端·架构·前端框架