Slickflow.AI 基于 Harness 工程规范的多智能体交互过程实现 日期: 2026-06-01 标签: 程序员 Slickflow.AI 基于 Harness 工程规范的多智能体交互过程实现 以上功能实现已包含在Slickflow5.0 企业版版本 目录 背景与目标 Harness 工程规范 核心架构设计 属性化工具注册(当前实现) 采购流程多智能体演示 落地路线图 近期:预置企业工具库 中期:声明式 HTTP 工具适配器 长期:MCP 协议集成 自然语言驱动多智能体全流程生成 现有基础与补充目标 三层生成架构 表单辅助配置层 Claude Code 工具类生成 三种交互模式对比 总结 1. 背景与目标 1.1 问题出发点 传统 BPM(业务流程管理)系统的核心是"人"驱动流程:人工节点负责决策,系统节点负责执行预定义规则。这一模型在面对复杂、动态、需要多步推理的企业场景时暴露出明显局限: 规则节点无法处理非结构化输入(自然语言需求、图片、文档) 复杂决策依赖大量 if-else 硬编码,维护成本高 多系统协作需要人工中转,效率低 1.2 多智能体的价值 将 LLM Agent 节点引入 BPM 流程,每个 Agent 节点具备: 推理能力:理解自然语言输入,分析上下文 工具调用能力(Function Calling):调用企业系统 API、数据库、外部服务 协作能力:通过共享上下文,多个 Agent 接力完成复杂任务 传统流程:用户 → 人工审核 → 系统执行 → 人工复核 → 结束 多智能体流程:用户 → Agent₁(需求分析) → Agent₂(方案搜索) → Agent₃(合规检查) → Agent₄(价格评估) → Agent₅(执行下单) → 结束 1.3 设计目标 目标 说明 流程驱动 Agent 行为由 BPMN 工作流定义驱动,不硬编码在程序里 工具解耦 工具实现与流程定义松耦合,通过 toolSetName 桥接 开发友好 业务开发者写普通 C# Service 类,不接触框架细节 可扩展 支持从代码工具逐步演进到声明式工具、MCP 协议工具 2. Harness 工程规范 Harness 是 Slickflow.AI 多智能体模块采用的工程架构规范,核心思想来源于 Claude 工程体系:以"注册→发现→执行"三段式管理智能体工具,使框架代码与业务代码完全分离。 2.1 核心思想 ┌───────────────────────────────────────────────────────────────────┐ │ Harness 三原则 │ │ │ │ 1. 声明在设计时(BPMN + 属性面板) │ │ toolSetName = "SupplierSearch" │ │ │ │ 2. 注册在启动时(应用/测试初始化) │ │ AgentToolSetRegistry.Global.Register() │ │ │ │ 3. 执行在运行时(引擎自动驱动) │ │ toolSetName → activityId → IReadOnlyList │ └───────────────────────────────────────────────────────────────────┘ 2.2 职责边界 角色 职责 代码位置 流程设计师 定义节点类型(Agent)、绑定 toolSetName、设置 System Prompt BPMN 设计器(数据库) 业务开发者 实现 [AgentToolSet] 服务类,写业务方法 ToolSets/*.cs 框架层 ReAct 循环、工具注册/发现、参数绑定、上下文管理 Slickflow.AI/Agent/ 引擎层 读取 BPMN 定义,驱动 Agent 节点执行 Slickflow.Engine/ 2.3 命名与注册规范 工具集命名(toolSetName)规则: ✅ 推荐:PascalCase,业务语义清晰 NeedsAnalysis / SupplierSearch / ComplianceCheck ❌ 避免:技术实现名称 AgentTool001 / Step2Handler / MyFunc 工具方法命名规则: // ✅ 动词+名词,描述行为 public Task RequestQuote(string supplierId, int quantity) // ❌ 不描述行为的名称 public Task Execute(JsonObject args) 注册时机:在应用程序/测试的入口点一次性注册,不在请求处理中动态注册: // Program.cs 或 测试入口 AgentToolSetRegistry.Global .Register() .Register() .Register(); 2.4 上下文传递规范 多 Agent 之间通过共享变量键(Variable Key)传递数据,键名在代码中集中定义为常量: // ✅ 在测试/应用入口集中定义 private const string VarPurchaseRequest = "PurchaseRequest"; private const string VarStructuredRequirements = "StructuredRequirements"; private const string VarSupplierQuotes = "SupplierQuotes"; // ✅ 数据流配置与工具注册分离 ["SupplierSearch"] = new(InputKey: VarStructuredRequirements, OutputKey: VarSupplierQuotes) 3. 核心架构设计 3.1 整体架构图 ┌──────────────────────────────────────────────────────────────────┐ │ Slickflow.AI 多智能体架构 │ │ │ │ ┌─────────────┐ ┌─────────────────────────────────────────┐ │ │ │ BPMN 设计器 │ │ Slickflow.Engine │ │ │ │ │ │ │ │ │ │ toolSetName ├───►│ WorkflowService → ProcessModelFactory │ │ │ │ SystemPrompt│ │ AIServiceExecutor → AgentMultiTurnService│ │ │ └─────────────┘ └──────────────┬──────────────────────────┘ │ │ │ │ │ ┌───────────────▼──────────────────────────┐ │ │ │ Slickflow.AI / Agent │ │ │ │ │ │ │ │ AgentToolSetRegistry │ │ │ │ toolSetName → IReadOnlyList│ │ │ │ │ │ │ │ │ AgentToolRegistry │ │ │ │ activityId → IReadOnlyList │ │ │ │ │ │ │ │ │ AgentNodeBase (ReAct Loop) │ │ │ │ Reason → Act → Observe → ... │ │ │ │ │ │ │ │ │ OpenAIToolCallLlmClient │ │ │ │ HTTP POST (tools + messages) │ │ │ └──────────────────┼───────────────────────┘ │ │ │ │ │ ┌──────────────────▼───────────────────────┐ │ │ │ 业务工具层 (ToolSets) │ │ │ │ │ │ │ │ [AgentToolSet("SupplierSearch")] │ │ │ │ class SupplierSearchService │ │ │ │ { │ │ │ │ [AgentTool("搜索供应商")] │ │ │ │ Task> SearchSuppliers()│ │ │ │ } │ │ │ └──────────────────────────────────────────┘ │ └──────────────────────────────────────────────────────────────────┘ 3.2 ReAct 循环 每个 Agent 节点执行 ReAct(Reason → Act → Observe) 循环,直到 LLM 给出最终答案: 用户输入 / 上一个 Agent 输出 │ ▼ ┌───────────────────────────────────────────────┐ │ Iteration 1 │ │ Reason: LLM 收到输入 + 工具定义 → 决策 │ │ Act: LLM 返回 finish_reason="tool_calls" │ │ → 调用 search_suppliers(category=IT) │ │ Observe: 工具返回 [SUP001, SUP002, SUP003] │ ├───────────────────────────────────────────────┤ │ Iteration 2 │ │ Reason: LLM 收到工具结果 → 继续决策 │ │ Act: 调用 request_quote(supplierId=SUP002) │ │ Observe: 返回报价 ¥2950×10=¥29500 │ ├───────────────────────────────────────────────┤ │ Iteration 3 │ │ Reason: LLM 综合所有结果 │ │ → finish_reason="stop"(最终答案) │ └───────────────────────────────────────────────┘ │ ▼ 最终文本输出 → 写入 OutputVariableKey → 下一个 Agent 的输入 循环保护:MaxIterations(默认 10)防止死循环,超出后返回降级答案。 3.3 工具注册体系 两层注册表实现"逻辑名 → 活动 ID"的解耦: AgentToolSetRegistry(名称注册) "SupplierSearch" → IReadOnlyList │ │ TryResolveToActivityRegistry(toolSetName, activityId) ▼ AgentToolRegistry(活动注册) "Activity_ABC123" → IReadOnlyList │ │ 引擎执行节点时调用 ▼ AgentNodeBase.ExecuteReActAsync() 这样做的好处:BPMN 定义里的 activityId 是运行时才知道的(每个流程实例可能不同),toolSetName 才是设计时确定的。两层注册表在运行时完成映射。 3.4 共享记忆(AgentConversationMemory) 多个 Agent 节点通过 AgentConversationMemory 共享输出,实现跨节点的上下文传递: // Agent₁ 写入 AgentConversationMemory.RecordOutput( processInstanceId, activityId, "StructuredRequirements", result); // Agent₂ 可以读取 Agent₁ 的输出(通过 sharedVars 传递) var input = sharedVars["StructuredRequirements"]; 记忆以 processInstanceId 为隔离键,流程实例结束后调用 Evict() 释放。 4. 属性化工具注册(当前实现) 4.1 问题与方案 问题:早期实现使用 lambda + 手写 JSON Schema,框架代码和业务代码混在一起: // ❌ 旧方式:开发者需要理解 JsonObject、AgentToolResult 等框架类型 .Register("quote_request", "向供应商请求报价", Schema("""{"type":"object","properties":{"supplierId":{"type":"string"},...}}"""), async (args, ct) => { var suppId = args["supplierId"]?.GetValue() ?? ""; return new AgentToolResult(true, JsonSerializer.Serialize(result)); }) 方案:通过 [AgentToolSet] / [AgentTool] 属性 + 反射引擎,业务开发者只写普通 Service 类: // ✅ 新方式:普通 C# 类,无框架代码 [AgentToolSet("SupplierSearch")] public class SupplierSearchService { [AgentTool("向指定供应商发起报价请求,返回单价、货期和总金额")] public async Task RequestQuote(string supplierId, int quantity) { // 纯业务逻辑 return new SupplierQuote { SupplierId = supplierId, UnitPrice = 2950m }; } } 4.2 反射引擎(AgentToolReflector)工作原理 AgentToolReflector.BuildToolsFromType() 扫描类的方法,自动完成: 框架任务 自动化方式 JSON Schema 生成 方法参数类型 → {"type":"string"/"integer"/"number"...} 工具名称 方法名 PascalCase → snake_case(RequestQuote → request_quote) 参数绑定 JsonObject args["supplierId"] → string supplierId 可选参数 default 值的参数不进入 required 数组 异步支持 Task → 自动 await,提取 Result 返回值序列化 强类型返回值 → JsonSerializer.Serialize() → LLM 可读字符串 CancellationToken 自动注入,不出现在 Schema 中 4.3 注册扩展:Register() 泛型重载 AgentToolSetRegistry 增加泛型重载,从属性读取 toolSetName,无需重复书写字符串: // AgentToolSetRegistry.Register() 内部实现 public AgentToolSetRegistry Register() where T : class, new() { var attr = typeof(T).GetCustomAttribute(); var toolSetName = attr.Name; // 从属性读 var tools = AgentToolReflector.BuildToolsFromType(typeof(T)); // 反射构建 _store[toolSetName] = () => tools; return this; } 5. 采购流程多智能体演示 5.1 业务场景 企业员工提交采购需求后,由 5 个 AI Agent 节点依次处理,全程无需人工干预,最终自动生成采购订单。 5.2 流程节点设计 用户提交采购需求 │ ▼ ┌──────────────────┐ │ NeedsAnalysis │ 分析需求,提取品类和规格 │ [Agent 节点] │ 工具:ClassifyCategory / ExtractSpecs └────────┬─────────┘ │ StructuredRequirements(结构化需求) ▼ ┌──────────────────┐ │ SupplierSearch │ 搜索供应商,获取报价 │ [Agent 节点] │ 工具:SearchSuppliers / RequestQuote └────────┬─────────┘ │ SupplierQuotes(供应商报价列表) ▼ ┌──────────────────┐ │ ComplianceCheck │ 合规审查(并行支持) │ [Agent 节点] │ 工具:CheckRegulations / CheckBlacklist └────────┬─────────┘ │ ComplianceReport(合规报告) ▼ ┌──────────────────┐ │ PriceEvaluation │ 综合评估,推荐最优方案 │ [Agent 节点] │ 工具:CalculateTco(总拥有成本) └────────┬─────────┘ │ PurchaseRecommendation(采购建议) ▼ ┌──────────────────┐ │ OrderExecution │ 在 ERP 中创建采购订单 │ [Agent 节点] │ 工具:CreatePurchaseOrder └────────┬─────────┘ │ PurchaseOrderId(订单号) ▼ 采购完成 流程图示例: 5.3 Agent 节点定义(Service 类) 需求分析服务: [AgentToolSet("NeedsAnalysis")] public class NeedsAnalysisService { [AgentTool("根据采购物品描述,识别采购类别代码")] public string ClassifyCategory(string description) { return description.Contains("router", StringComparison.OrdinalIgnoreCase) ? "IT_HARDWARE" : "GENERAL"; } [AgentTool("从采购描述中提取规格参数,返回数量、单位和技术规格")] public async Task ExtractSpecs(string text, string category) { await Task.Delay(5); // 实际场景:调用 NLP 服务或规格库 return new ItemSpec { Quantity = 10, Unit = "units", Specification = "5G/LTE, DIN rail, -40~70°C, IPX5" }; } } 供应商搜索服务: [AgentToolSet("SupplierSearch")] public class SupplierSearchService { [AgentTool("搜索供应商目录,返回符合条件的供应商列表")] public async Task> SearchSuppliers(string category, string specification = "") { // 实际场景:查询供应商数据库 return new List { new() { SupplierId = "SUP001", Name = "TechNet Industrial Ltd", Rating = 4.2 }, new() { SupplierId = "SUP002", Name = "GlobalRouter Solutions", Rating = 4.5 }, }; } [AgentTool("向指定供应商发起报价请求,返回单价、货期和总金额")] public async Task RequestQuote(string supplierId, int quantity) { // 实际场景:调用供应商门户 API 或 EDI 接口 return new SupplierQuote { SupplierId = supplierId, UnitPrice = 2950m, LeadTimeDays = 10, QualityScore = 4.5, TotalAmount = 2950m * quantity }; } } 5.4 数据流配置 private static readonly IReadOnlyDictionary RunConfigs = new Dictionary(StringComparer.OrdinalIgnoreCase) { ["NeedsAnalysis"] = new(InputKey: "PurchaseRequest", OutputKey: "StructuredRequirements"), ["SupplierSearch"] = new(InputKey: "StructuredRequirements", OutputKey: "SupplierQuotes"), ["ComplianceCheck"]= new(InputKey: "StructuredRequirements", OutputKey: "ComplianceReport"), ["PriceEvaluation"]= new(InputKey: "SupplierQuotes", OutputKey: "PurchaseRecommendation"), ["OrderExecution"] = new(InputKey: "PurchaseRecommendation", OutputKey: "PurchaseOrderId") }; 5.5 启动注册(一次性) // 应用启动时(Program.cs 或测试入口) AgentToolSetRegistry.Global .Register() .Register() .Register() .Register() .Register(); 5.6 BPMN 侧配置(设计器) 流程设计师在 BPMN 属性面板为每个 Agent 节点设置: 属性 值 说明 type Agent 节点类型 toolSetName SupplierSearch 与注册名称对应 system_prompt 存入 ai_activity_config 角色定义,可数据库配置 5.7 运行日志示例 === WorkflowDrivenProcurementTest === ProcessCode : SmartProcurement Version: 1 Model : qwen-plus [OK] Loaded process: 智能采购流程 (id=1001) [OK] Found 5 Agent node(s): [NeedsAnalysis] toolSetName=NeedsAnalysis id=Activity_001 [SupplierSearch] toolSetName=SupplierSearch id=Activity_002 [ComplianceCheck] toolSetName=ComplianceCheck id=Activity_003 [PriceEvaluation] toolSetName=PriceEvaluation id=Activity_004 [OrderExecution] toolSetName=OrderExecution id=Activity_005 ─── Agent 1/5: NeedsAnalysis [NeedsAnalysis] ─── [Agent] ReAct iteration 1/8 [Agent][LLM] POST ... model=qwen-plus tools=2 msgs=2 [Agent][LLM] tool_calls: classify_category id=call_001 [Agent] Calling tool 'classify_category' | args={"description":"...routers..."} [NeedsAnalysisService.ClassifyCategory] → IT_HARDWARE [Agent] ReAct iteration 2/8 [Agent][LLM] tool_calls: extract_specs id=call_002 [NeedsAnalysisService.ExtractSpecs] 提取规格中... [Agent] ReAct iteration 3/8 [Agent][LLM] text response (256 chars) [Agent] Final answer produced ─── Agent 2/5: SupplierSearch [SupplierSearch] ─── ... [SupplierSearchService.SearchSuppliers] 搜索中... [SupplierSearchService.RequestQuote] SUP002 → ¥2950×10 ... ─── Agent 5/5: OrderExecution [OrderExecution] ─── [OrderExecutionService.CreatePurchaseOrder] 已创建 PO-20260531-7823 ═══════════════════════════════════════ 采购完成 订单号:PO-20260531-7823 供应商:GlobalRouter Solutions 金额:¥29,500 ═══════════════════════════════════════ 6. 落地路线图 当前实现(属性化 Service 类)解决了"开发者写代码"的体验问题,但面向企业客户还有更深一层的问题:谁来为每家客户写那些 Service 类? 三个阶段的答案是:从"写代码"演进到"填配置",最终达到"零配置自发现"。 6.1 近期:预置企业工具库 核心思想:平台方提前实现 80% 的高频企业操作,客户只需选择并配置,不需要写代码。 工具库分类设计 Slickflow.AI.Enterprise.Tools/ ├── ErpTools/ │ ├── InventoryQueryTool 查库存 │ ├── PurchaseOrderTool 创建/查询采购订单 │ ├── GoodsReceiptTool 收货确认 │ └── VendorMasterTool 供应商主数据查询 │ ├── ApprovalTools/ │ ├── StartApprovalTool 发起审批(钉钉/企微/飞书/OA) │ ├── ApprovalStatusTool 查询审批状态 │ ├── ApprovalUrgerTool 审批催办 │ └── ConditionalBranchTool 条件判断(金额/部门/级别) │ ├── HrTools/ │ ├── EmployeeQueryTool 查询人员信息 │ ├── LeaveBalanceTool 假期余额查询 │ ├── OrgChartTool 组织架构查询 │ └── AttendanceTool 考勤记录查询 │ ├── NotifyTools/ │ ├── EmailSendTool 发送邮件 │ ├── DingTalkMsgTool 钉钉消息 │ ├── WeChatWorkMsgTool 企业微信消息 │ └── TodoCreateTool 创建待办事项 │ └── DataTools/ ├── SqlQueryTool 参数化 SQL 查询(只读) ├── FormDataWriteTool 写入表单数据 └── ReportQueryTool 报表数据查询 配置化设计(以 ERP 为例) 工具类通过配置文件或数据库读取连接参数,不硬编码: [AgentToolSet("ErpInventory")] public class InventoryQueryTools { private readonly ErpConfig _config; public InventoryQueryTools() { // 从 appsettings.json 或数据库读取 _config = ErpConfigLoader.Load("ERP_MAIN"); } [AgentTool("查询指定物料的当前库存数量和仓库分布")] public async Task QueryInventory(string materialCode, string warehouse = "") { // 调用配置的 ERP 接口 return await _config.ErpClient.GetInventoryAsync(materialCode, warehouse); } } // appsettings.json { "ErpConfigs": { "ERP_MAIN": { "BaseUrl": "http://erp.company.com/api", "ApiKey": "sk-xxx", "Timeout": 30 } } } 注册方式(集成时) // 客户集成时,只需选择需要的工具集并配置连接参数 AgentToolSetRegistry.Global .Register() // 平台预置 .Register() // 平台预置 .Register() // 平台预置 // 以下才是客户自己写的业务特定工具 .Register(); 覆盖范围预估 场景 预置工具覆盖率 采购申请审批 ~90% 费用报销 ~85% 员工入职 ~80% 合同审批 ~75% 客户拜访管理 ~70% 6.2 中期:声明式 HTTP 工具适配器 核心思想:为 REST API 类工具提供 JSON/数据库配置方式,业务人员在设计器里填写 API 地址和参数映射,不需要写任何 C# 代码。 工具描述格式(存储在数据库) { "toolSetName": "SupplierPortalTools", "tools": [ { "name": "search_suppliers", "description": "搜索供应商目录,返回符合条件的供应商列表", "type": "http", "method": "GET", "url": "http://supplier-portal.company.com/api/suppliers", "headers": { "Authorization": "Bearer {{config.ApiToken}}", "Content-Type": "application/json" }, "parameters": [ { "name": "category", "type": "string", "required": true, "in": "query" }, { "name": "specification", "type": "string", "required": false, "in": "query" } ], "responseMapping": "$.suppliers" }, { "name": "request_quote", "description": "向指定供应商请求报价", "type": "http", "method": "POST", "url": "http://supplier-portal.company.com/api/quotes", "body": { "supplierId": "{{args.supplierId}}", "quantity": "{{args.quantity}}" }, "parameters": [ { "name": "supplierId", "type": "string", "required": true }, { "name": "quantity", "type": "integer", "required": true } ] } ] } 框架层:HttpToolAdapter // 框架层新增,业务开发者不接触 public sealed class HttpToolAdapter : IAgentTool { private readonly HttpToolDescriptor _descriptor; private readonly IHttpClientFactory _httpFactory; public string Name => _descriptor.Name; public string Description => _descriptor.Description; public JsonObject InputSchema => BuildSchemaFromDescriptor(_descriptor); public async Task ExecuteAsync(JsonObject args, CancellationToken ct) { var url = ResolveTemplate(_descriptor.Url, args); var headers = ResolveHeaders(_descriptor.Headers); var body = _descriptor.Method == "POST" ? ResolveBody(_descriptor.Body, args) : null; var response = await _httpFactory .CreateClient() .SendAsync(BuildRequest(url, headers, body, _descriptor.Method), ct); var json = await response.Content.ReadAsStringAsync(ct); return new AgentToolResult(response.IsSuccessStatusCode, json); } } 注册方式(数据库驱动) // 框架启动时,从数据库加载所有声明式工具集 var toolSetDescriptors = await db.LoadHttpToolSetDescriptors(); foreach (var descriptor in toolSetDescriptors) { var tools = descriptor.Tools .Select(t => new HttpToolAdapter(t, httpFactory)) .ToList(); AgentToolSetRegistry.Global.RegisterTools(descriptor.ToolSetName, tools); } 设计器集成 BPMN 设计器新增"HTTP 工具配置"面板,业务人员直接在界面上: 填写 API Endpoint 拖拽参数映射 测试连接并保存 这一步实现后,新增一个企业系统集成的成本从"写代码+部署"降为"填表单+保存"。 6.3 长期:MCP 协议集成 核心思想:企业各系统各自部署 MCP Server(Model Context Protocol),Agent 节点通过标准协议动态发现和调用工具,平台侧零代码、零配置完成集成。 MCP 是由 Anthropic 推动的 AI 工具标准协议,OpenAI、Microsoft 等主流厂商均已跟进支持。 架构图 ┌─────────────────────────────────────────────────────────┐ │ Slickflow Agent 节点 │ │ │ │ AgentNodeBase (ReAct Loop) │ │ │ │ │ │ Tools = McpClientTool × N │ │ ▼ │ │ McpServerClient (已实现) │ │ │ │ │ │ JSON-RPC 2.0 │ └───────┼─────────────────────────────────────────────────┘ │ ├──► MCP Server (ERP 系统) │ tools/list → [query_inventory, create_order, ...] │ tools/call → 执行并返回结果 │ ├──► MCP Server (CRM 系统) │ tools/list → [get_customer, update_opportunity, ...] │ ├──► MCP Server (OA 审批系统) │ tools/list → [start_approval, get_status, urge_approval] │ └──► MCP Server (第三方供应商门户) tools/list → [search_suppliers, request_quote, ...] 项目现有基础:McpClientTool // 已实现:source/core/Slickflow.AI/Agent/Tools/McpClientTool.cs public sealed class McpClientTool : IAgentTool { // JSON-RPC 2.0 代理,自动发现并调用 MCP Server 暴露的工具 public Task ExecuteAsync(JsonObject args, CancellationToken ct) => _mcpClient.CallAsync(_toolName, args, ct); } 使用方式(设计时) // BPMN 节点配置 MCP Server 地址 // sf:AiService mcpServerUrl="http://erp.company.com/mcp" // toolSetName="ErpTools"(自动发现,不需要预注册) // 引擎运行时自动执行: var mcpClient = new McpServerClient(mcpServerUrl); var tools = await mcpClient.DiscoverToolsAsync(); // 自动获取工具列表 AgentToolRegistry.Global.Register(activityId, tools); MCP Server 部署参考(企业侧) 以 ERP 系统为例,企业只需在 ERP 旁边部署一个轻量 MCP Server(提供商已有 SDK): ERP 主系统 MCP Server(新增) │ │ │ 内部调用 │ JSON-RPC 2.0(供 Agent 使用) ◄──────────────────────────►│ │ ┌──────────┘ │ 暴露的工具: │ - query_inventory │ - create_purchase_order │ - check_vendor_status 三阶段能力对比 维度 近期(预置工具库) 中期(声明式 HTTP) 长期(MCP 协议) 接入新系统的工作量 写 C# Service 类 填 JSON 配置表单 部署 MCP Server 需要开发人员参与 是 否(配置即可) 否(标准协议) 工具更新方式 代码发布 修改数据库配置 MCP Server 动态更新 适用范围 高频标准场景 任意 REST API 任意支持 MCP 的系统 技术门槛 低(写普通类) 极低(填表单) 中(部署 MCP Server) 7. 自然语言驱动多智能体全流程生成 7.1 现有基础与补充目标 Slickflow 产品已具备自然语言 → BPMN 流程图的生成能力:用户用中文描述业务场景,LLM 自动生成对应的 BPMN XML,并在设计器中渲染出可编辑的流程图。 将这一能力延伸到多智能体场景,面临一个新问题: 现有能力(已有): "我需要一个采购审批流程" → LLM → BPMN 结构(节点 + 连线) 需要补充的能力(新增): BPMN 结构中的 Agent 节点 → 需要进一步配置: ① toolSetName(绑定哪个工具集) ② System Prompt(角色定义) ③ 输入/输出变量键(数据流) ④ MaxIterations、模型选择等参数 这些 Agent 专属配置无法完全从自然语言描述中一次性推断,需要一套分层生成 + 人工确认的补充方案。 7.2 三层生成架构 整体方案分三层,依次递进: ┌────────────────────────────────────────────────────────────────┐ │ 第一层:自然语言 → BPMN 结构(已有功能延伸) │ │ │ │ 用户输入:"我需要一个采购审批流程,包括供应商查询、合规审查 │ │ 和价格评估,金额超过 50 万需要人工审批" │ │ │ │ LLM 输出: │ │ ① BPMN XML(含 Agent 节点类型标记) │ │ ② 每个 Agent 节点的语义描述("供应商查询节点") │ │ ③ 初步推断的数据流(输入/输出变量名建议) │ └────────────────────────────────────────────────────────────────┘ │ ▼ ┌────────────────────────────────────────────────────────────────┐ │ 第二层:Agent 节点配置(AI 预填 + 表单确认) │ │ │ │ 对于 BPMN 中识别到的每个 Agent 节点,AI 自动: │ │ ① 从现有 toolSetName 注册表中模糊匹配,推荐最接近的工具集 │ │ ② 根据节点语义生成 System Prompt 草稿 │ │ ③ 推断 InputKey / OutputKey(基于上下游节点关系) │ │ │ │ 用户在属性面板:确认 or 修改(低成本,不需从零填写) │ └────────────────────────────────────────────────────────────────┘ │ ▼ ┌────────────────────────────────────────────────────────────────┐ │ 第三层:缺失工具集的代码生成(Claude Code CLI) │ │ │ │ 当第二层推荐的 toolSetName 不存在(注册表中没有匹配项时): │ │ ① 用户在设计器中点击"生成工具类"按钮 │ │ ② 填写 API 描述或上传 OpenAPI Spec │ │ ③ 调用 Claude Code 生成 [AgentToolSet] C# 代码 │ │ ④ 开发者 Review → 注册到工具库 → 回填 toolSetName │ └────────────────────────────────────────────────────────────────┘ 7.3 表单辅助配置层 第二层的核心是一个智能预填的属性面板,在 BPMN 设计器中每个 Agent 节点的侧边栏展示。 AI 预填逻辑(服务端) // 当 BPMN 中检测到 Agent 节点时,后端自动执行预填推断 public sealed class AgentNodeConfigSuggester { private readonly AgentToolSetRegistry _registry; private readonly ILlmClient _llm; /// /// 为一个 Agent 节点生成配置建议 /// 输入:节点的语义描述 + 上下游节点信息 + 已有注册表 /// 输出:预填的 AgentNodeConfig(用户可在面板中修改) /// public async Task SuggestAsync( string nodeDescription, // "查询供应商并获取报价" string upstreamOutputKey, // 上游节点的 OutputKey(如 "StructuredRequirements") string downstreamHint) // 下游节点的语义(如 "合规审查") { // 1. 从注册表中获取所有可用 toolSetName var availableToolSets = _registry.GetAllToolSetNames(); // 2. 让 LLM 从中选择最匹配的,并生成其他配置 var prompt = $""" 已注册的工具集列表:{string.Join(", ", availableToolSets)} 当前 Agent 节点描述:{nodeDescription} 上游节点的输出变量:{upstreamOutputKey} 下游节点的用途:{downstreamHint} 请输出 JSON,包含: - toolSetName: 从已注册列表中选择最匹配的(没有匹配时输出 null) - systemPrompt: 根据节点描述生成的角色定义(100字以内) - inputKey: 建议的输入变量名 - outputKey: 建议的输出变量名 - confidence: 推荐置信度(high/medium/low) 只输出 JSON。 """; var json = await _llm.CompleteAsync(prompt); return JsonSerializer.Deserialize(json)!; } } public sealed record AgentNodeConfigSuggestion( string? ToolSetName, // null 表示未找到匹配,需要生成 string SystemPrompt, string InputKey, string OutputKey, string Confidence); // "high" / "medium" / "low" 属性面板 UI 行为 Agent 节点属性面板(设计器侧边栏) ┌─────────────────────────────────────────┐ │ 节点名称:供应商查询 │ │ │ │ 工具集 (toolSetName) │ │ ┌─────────────────────────┐ [生成代码] │ │ │ SupplierSearch ✓ AI推荐 │ │ │ └─────────────────────────┘ │ │ 置信度:● 高 ( 可从下拉列表选其他 ) │ │ │ │ System Prompt │ │ ┌─────────────────────────────────┐ │ │ │ 你是供应商查询专家,负责根据采购 │ │ │ │ 规格搜索合适供应商并获取报价... │ │ │ └─────────────────────────────────┘ │ │ [AI 重新生成] │ │ │ │ 输入变量:StructuredRequirements │ │ 输出变量:SupplierQuotes │ │ │ │ 最大迭代:10 模型:claude-sonnet │ │ │ │ [确认配置] [重置] │ └─────────────────────────────────────────┘ ⚠ 当 toolSetName = null 时,面板显示: ┌─────────────────────────────────────────┐ │ ⚠ 未找到匹配的工具集 │ │ 请选择: │ │ ○ 从预置库选择(近似功能) │ │ ● 声明式 HTTP 配置(填写 API 地址) │ │ ○ 生成 C# 工具类(Claude Code) │ └─────────────────────────────────────────┘ 7.4 Claude Code 工具类生成 当没有现成工具集时,第三层方案是通过 Claude Code CLI 直接生成符合 Slickflow Harness 规范的 [AgentToolSet] C# 代码。 两种触发方式 方式一:设计器内嵌调用 在属性面板点击"生成工具类"后,设计器将用户填写的接口描述组装成 Prompt,通过后端调用 Anthropic API,在界面中实时展示生成的代码供 Review: // 后端:AgentToolCodeGenerator.cs public sealed class AgentToolCodeGenerator { private readonly ILlmClient _claude; public async Task GenerateToolSetAsync(ToolGenerationRequest request) { var prompt = $""" 请生成一个符合 Slickflow Harness 规范的 C# AgentToolSet 类。 工具集名称:{request.ToolSetName} 业务描述:{request.Description} API 信息:{request.ApiDescription} 规范要求: 1. 类上标注 [AgentToolSet("{request.ToolSetName}")] 2. 每个方法标注 [AgentTool("工具功能描述")] 3. 使用强类型参数和返回值,不使用 JsonObject 4. 异步方法返回 Task 5. 通过构造函数注入 HttpClient 或配置类 参考现有规范: [AgentToolSet("SupplierSearch")] public class SupplierSearchService {{ [AgentTool("搜索供应商目录,返回符合条件的供应商列表")] public async Task> SearchSuppliers(string category) {{ ... }} }} 只输出 C# 代码,不要额外解释。 """; return await _claude.CompleteAsync(prompt); } } public sealed record ToolGenerationRequest( string ToolSetName, string Description, string ApiDescription); // 用户填写的 API 说明,或上传的 OpenAPI Spec JSON 方式二:Claude Code CLI 命令行 开发者也可以在终端直接调用 Claude Code,适合在本地开发环境中快速生成: # 基于描述生成工具类 claude "根据以下 Slickflow Harness 规范,生成一个 C# AgentToolSet 类。 工具集名称:InventoryQuery 业务场景:查询 SAP 库存系统,支持按物料编码查询库存数量和仓库分布。 API endpoint:GET http://sap.company.com/api/inventory/{materialCode} 参考规范:[AgentToolSet] + [AgentTool] 属性化注册,强类型返回值,构造函数注入 HttpClient。" # 基于 OpenAPI Spec 文件生成工具类 claude "读取 ./supplier-portal-openapi.json,为 Slickflow Harness 框架生成 对应的 [AgentToolSet] C# 类,仅包含 GET /suppliers 和 POST /quotes 两个接口, 类名为 SupplierPortalTools。" 生成结果示例 // Claude Code 生成的代码(开发者 Review 后直接使用) [AgentToolSet("InventoryQuery")] public class InventoryQueryService { private readonly HttpClient _http; public InventoryQueryService(IHttpClientFactory httpFactory) { _http = httpFactory.CreateClient("SapInventory"); } [AgentTool("查询指定物料编码的当前库存数量,支持按仓库筛选")] public async Task QueryStock( string materialCode, string warehouse = "") { var url = string.IsNullOrEmpty(warehouse) ? $"/api/inventory/{materialCode}" : $"/api/inventory/{materialCode}?warehouse={warehouse}"; var response = await _http.GetFromJsonAsync(url); return new InventoryResult { MaterialCode = materialCode, Quantity = response?.Quantity ?? 0, Warehouse = response?.Warehouse ?? warehouse, Unit = response?.Unit ?? "EA" }; } [AgentTool("批量查询多个物料的库存汇总,返回可用/缺货状态")] public async Task> QueryBatchStock(List materialCodes) { var tasks = materialCodes.Select(code => QueryStock(code)); return (await Task.WhenAll(tasks)).ToList(); } } 生成后的接入流程 ① 设计器界面点击"生成工具类",填写接口描述 │ ▼ ② 后端调用 LLM(或 Claude Code CLI),生成 C# 代码 │ ▼ ③ 设计器弹出代码预览窗口,开发者 Review + 小改 │ ▼ ④ 开发者将代码保存到 ToolSets/ 目录,提交并部署 │ ▼ ⑤ 在 Program.cs 注册:AgentToolSetRegistry.Global.Register() │ ▼ ⑥ 设计器属性面板的 toolSetName 下拉列表中出现新工具集,回填到 Agent 节点 │ ▼ ⑦ 全流程配置完成,可以执行 7.5 三种交互模式对比 根据用户角色和场景复杂度,自然语言生成多智能体流程有三种落地模式: 模式 适用场景 操作路径 工具集来源 A. 全自动模式 需求完全匹配预置工具库 NL → BPMN → AI 预填配置 → 一键确认 预置工具库 B. 表单辅助模式 工具集存在但需自定义 HTTP API NL → BPMN → 表单填写 API 地址 → 保存 声明式 HTTP 适配器 C. 代码生成模式 需要全新工具集 NL → BPMN → Claude Code 生成类 → Review 注册 AI 生成 C# 代码 预期用户体验: 普通业务人员(无代码): 用自然语言描述 → 流程图自动生成 → 从预置工具库选择 → 确认 → 运行 全程 5-10 分钟,零代码 集成工程师(低代码): 自然语言生成框架 → 填写 HTTP API 表单 → 测试连通 → 保存 全程 30 分钟,零 C# 代码 开发者(有代码能力): 自然语言生成框架 → Claude Code 生成工具类 → Review + 小改 → 注册 全程 1-2 小时,大量代码由 AI 生成 当前可实现程度: 子能力 现状 所需工作 NL → BPMN 结构 ✅ 已有 增加 Agent 节点类型识别 AI 预填 toolSetName 🔧 可实现 接入注册表的模糊匹配 API AI 生成 System Prompt 🔧 可实现 复用现有 LLM 调用能力 表单式 HTTP 工具配置 🔧 规划中(6.2 章节) 中期工作 Claude Code 工具类生成 🔧 可实现 接入 Anthropic API,增加代码预览组件 生成代码自动注册 ⚠ 需谨慎 安全评估后再考虑自动化 8. 总结 8.1 核心设计决策 决策 原因 ReAct 循环代替单次 LLM 调用 复杂任务需要多步推理和工具协作,单次调用无法完成 两层注册表(SetRegistry + Registry) toolSetName 是设计时名称,activityId 是运行时名称,两者必须解耦 属性化工具注册代替 lambda 业务开发者不应接触框架细节,Service 类可读性更高、可测试性更强 BPMN 驱动代替硬编码节点顺序 流程结构由设计师在 BPMN 里调整,不需要改代码 共享变量传递上下文 Agent 之间通过键值对共享状态,避免强耦合 8.2 开发者工作量变化 框架代码 | 业务代码 | 旧方式(lambda) ████████ | ██ 新方式(属性化) ░░░░░░░░ | ████████ 近期(预置库) ░░░░░░░░ | ██(选配置) 中期(声明式) ░░░░░░░░ | █(填表单) 长期(MCP) ░░░░░░░░ | ░(零代码) NL 生成(新增) ░░░░░░░░ | ░(自然语言描述) 本文档描述的所有代码均已在 source/core/Slickflow.AI/Agent/ 和 source/test/Slickflow.ConsoleTest/MultiAgent/ 目录下实现并通过编译验证 " 原文地址: https://www.cveoy.top/t/topic/qGMH 著作权归作者所有。请勿转载和采集! 免费AI点我,无需注册和登录