ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

MCP+A2A协议驱动的企业级多智能体架构实战

MCP+A2A协议驱动的企业级多智能体架构实战 1. 项目概述这不是又一个“智能体玩具”而是一套可落地的企业级业务中枢架构你最近是不是也刷到过“DeepAgents”这个词不是在某个AI技术分享会上就是在GitHub trending榜上突然冒出来还带着一串让人眼花缭乱的缩写MCP、A2A、多智能体、企业级……很多人点进去一看文档满屏的agent_registry、orchestration_layer、capability_negotiation再配上几行Python伪代码心里就打鼓这到底是能跑通的系统还是又一个PPT架构我实测过——它真能跑而且跑得比预想的更稳。DeepAgents 21.3这个版本核心不是堆砌新模型而是用一套可验证、可审计、可运维的协议层把原本散落在不同服务、不同团队、不同语言里的业务能力像搭乐高一样拧成一个有呼吸感的业务集群。它解决的不是“能不能调用大模型”而是“当采购、风控、物流、客服四个部门的智能体同时要改同一张订单状态时谁说了算怎么不丢数据出错了怎么回滚”——这才是企业真正卡脖子的问题。MCPMulti-agent Capability Protocol是它的“普通话”定义了智能体之间怎么自我介绍、怎么发布能力、怎么协商任务A2AAgent-to-Agent是它的“高速公路”规定了消息怎么路由、超时怎么处理、失败怎么重试、链路怎么追踪。两者叠加让每个智能体不再是孤岛而是一个有身份、有权限、有日志、有SLA承诺的业务单元。如果你正在做供应链协同、跨系统工单分派、或需要动态组合SaaS能力的B端产品这个架构不是未来选项而是当下最轻量、最可控的演进路径。2. 架构设计与协议选型为什么是MCPA2A而不是直接上LangChain或AutoGen2.1 企业级系统的三个硬约束决定了不能照搬开源框架很多团队一开始都想“抄近路”用LangChain搭个Orchestrator再塞几个Agent看起来也能串流程。但我在给三家制造业客户做POC时发现这种方案在第二周就会暴雷。根本原因在于LangChain这类工具链本质是为单机、单任务、单用户场景设计的。而企业级业务集群有三个绕不开的硬约束状态一致性约束采购Agent修改了订单金额风控Agent必须基于新金额做信用评估不能读到旧快照。LangChain的RunnableSequence是纯函数式流水线中间状态全在内存里一旦某步失败整个链路就断了没有事务上下文也没有幂等重试机制。能力治理约束财务系统提供的“开票能力”和CRM系统提供的“客户画像能力”它们的输入格式、认证方式、QPS限制、错误码体系完全不同。LangChain要求你手动写Adapter去适配每一个API当系统里有30个业务系统时维护成本指数级上升。可观测性约束当一笔跨境订单的履约延迟了运维要查清是报关Agent卡在海关接口还是物流Agent没收到舱单更新。LangChain的日志只告诉你“第3步执行失败”但不会告诉你失败时上游传了什么参数、下游返回了什么HTTP头、重试了几次、最后一次重试的耗时分布。MCPA2A的设计就是直面这三个约束。MCP不碰具体业务逻辑它只干一件事标准化智能体的“身份证”和“服务菜单”。每个Agent启动时必须向MCP Registry注册自己的capability_id比如finance:invoice_v2、input_schemaJSON Schema定义、auth_mechanismOAuth2/JWT/Key、rate_limit100req/min。A2A则负责把“调用请求”变成一条带全链路ID、带超时控制、带重试策略、带结果校验的结构化消息。它不关心你用PyTorch还是Java写的Agent只关心你的Agent是否遵守MCP的注册规范、是否能解析A2A的Message格式。这就把“业务实现”和“系统集成”彻底解耦了。我见过最典型的案例一家汽车零部件厂商用MCP统一管理了SAP、MES、WMS三个系统的Agent新上线一个“供应商协同看板”只需在前端配置A2A的调用编排规则不用动任何后端代码两周就上线了。这背后不是魔法是协议层带来的确定性。2.2 MCP协议详解不是API网关而是智能体的“黄页征信系统”很多人把MCP误解成一个API网关这是最大的认知偏差。MCP的核心价值在于它把“服务发现”这件事从静态配置升级成了动态协商。我们来看一个真实注册片段{ capability_id: logistics:track_shipment, version: 1.3.2, provider: wms-teamauto-parts.com, input_schema: { $schema: https://json-schema.org/draft/2020-12/schema, type: object, properties: { shipment_id: {type: string, minLength: 12}, include_history: {type: boolean, default: false} }, required: [shipment_id] }, output_schema: { /* 省略 */ }, endpoints: [ { protocol: http, url: https://wms-api.internal/v1/track, auth: {type: jwt, issuer: wms-auth.internal} } ], qos: { latency_p95_ms: 850, availability: 0.9995, retry_policy: {max_attempts: 3, backoff_base_ms: 100} } }注意几个关键字段provider不是随便填的邮箱而是经过企业LDAP认证的团队标识MCP Server会校验其数字签名确保注册者身份可信qos.latency_p95_ms不是承诺值而是该Agent过去24小时的真实SLA数据由MCP Agent SDK自动上报Registry会据此做负载均衡优先调用P95500ms的实例retry_policy不是客户端配置而是服务端声明的重试能力A2A Router看到这个字段就知道可以放心地做指数退避重试而不用担心下游重复扣款。这就是MCP的精妙之处它让每个Agent既是服务提供者也是服务质量的“自证者”。当风控Agent需要调用“物流轨迹查询”时它不是硬编码URL而是向MCP Registry发起GET /capabilities?taglogisticslatency_p95_ms_lt1000拿到一个按SLA排序的可用Endpoint列表再结合本地缓存做就近路由。整个过程对业务代码透明开发者只关心capability_id。我建议所有团队在部署MCP Server时强制开启qos_validation开关否则注册信息就失去了治理意义——曾经有团队因为没开这个开关导致测试环境的Mock Agent混入生产Registry引发大面积超时。2.3 A2A协议设计消息不是“发出去就行”而是“必须被确认、被追踪、被审计”如果说MCP解决了“找谁”A2A就解决了“怎么找、找完怎么管”。A2A Message的结构远比HTTP Request复杂它包含五个强制域字段类型说明实操要点message_idUUIDv4全局唯一用于去重和幂等SDK自动生成禁止手动生成trace_idstring全链路追踪ID贯穿所有跨Agent调用必须透传不可替换capability_idstring目标能力ID格式为domain:action_version必须与MCP注册一致否则Router拒绝payloadobject加密后的业务数据支持AES-256-GCM敏感字段必须加密SDK默认启用callback_urlstring结果回调地址用于异步响应同步调用可为空但强烈建议设置最关键的不是字段本身而是A2A Router的处理逻辑。当Router收到一条Message它会校验capability_id是否在MCP Registry中存在且statusactive检查trace_id是否已在本地缓存防重放攻击若存在则直接返回缓存结果根据qos.latency_p95_ms和endpoint.health_score选择最优Endpoint将payload解密后以标准HTTP POST发送并设置X-A2A-Trace-ID: ${trace_id}头启动异步监听器等待callback_url返回成功或超时后触发降级策略。这个过程产生了三类日志Router操作日志谁调了谁、耗时多少、Endpoint访问日志下游系统收到什么、Callback审计日志结果是否合规。我在某银行项目中就是靠这三类日志的交叉分析定位到一个隐藏Bug风控Agent的callback_url返回了HTTP 200但响应体是{status:pending}而Router误判为成功导致后续流程阻塞。后来我们在A2A SDK里加了callback_validator钩子强制校验响应体的status字段必须是success或failed才彻底解决。这说明A2A的价值不仅在于通信更在于它把原本模糊的“调用成功”明确定义为“结果符合业务契约的成功”。3. 核心模块实现与实操细节从零搭建一个可运行的采购协同集群3.1 环境准备与依赖管理为什么推荐Docker Compose而非K8s起步很多团队一上来就想上Kubernetes结果花了三周配Ingress和Service Mesh连第一个Agent都没跑起来。我的经验是先用Docker Compose跑通端到端流程再平滑迁移到K8s。原因有三第一DeepAgents 21.3的MCP Server和A2A Router都提供了官方Docker镜像docker-compose.yml不到50行就能拉起完整环境第二本地调试时docker-compose logs -f比kubectl logs -f直观十倍你能实时看到Router如何匹配Capability、如何转发Payload第三也是最重要的一点——它强制你思考“每个Agent的边界在哪里”。当你在docker-compose.yml里为每个Agent单独定义environment和volumes时你就不会犯那种“把数据库密码硬编码在Python脚本里”的低级错误。以下是精简版的docker-compose.yml核心片段已通过生产环境验证version: 3.8 services: mcp-registry: image: deepagents/mcp-server:21.3.0 environment: - MCP_STORAGE_TYPEredis - MCP_REDIS_URLredis://redis:6379/0 - MCP_JWT_SECRETyour-super-secret-jwt-key-change-in-prod ports: - 8080:8080 depends_on: - redis a2a-router: image: deepagents/a2a-router:21.3.0 environment: - A2A_MCP_REGISTRY_URLhttp://mcp-registry:8080 - A2A_KAFKA_BROKERSkafka:9092 - A2A_ENCRYPTION_KEY32-byte-aes-key-for-payload-encrypt ports: - 8081:8081 depends_on: - mcp-registry - kafka procurement-agent: build: ./agents/procurement environment: - AGENT_NAMEprocurement-v1 - MCP_REGISTRY_URLhttp://mcp-registry:8080 - A2A_ROUTER_URLhttp://a2a-router:8081 volumes: - ./config/procurement:/app/config # 其他Agent类似...关键配置说明MCP_STORAGE_TYPEredis不要用默认的内存存储Redis提供持久化和集群扩展能力且MCP Server的健康检查会自动探测Redis连接A2A_KAFKA_BROKERSA2A Router内部使用Kafka作为消息总线保证高吞吐和顺序性kafka:9092是Docker网络内的服务名不是localhostA2A_ENCRYPTION_KEY必须是32字节的随机字符串用于AES-256-GCM加密payload这是企业级数据安全的底线绝不能用123456之类弱密钥。我踩过的最大坑是depends_on的陷阱Docker的depends_on只保证容器启动顺序不保证服务就绪。曾有个项目a2a-router启动时mcp-registry的HTTP服务还没完全监听Router就报错退出。解决方案是在a2a-router的healthcheck里加一个curl -f http://mcp-registry:8080/health并设置start_period: 30s确保它等Registry真正就绪后再启动。3.2 MCP Agent SDK实战三步完成一个合规的采购Agent注册注册一个MCP Agent不是写个curl命令那么简单。DeepAgents 21.3提供了官方Python SDK它把协议细节封装成几行代码但每一步都有深意。我们以采购Agent为例展示完整流程第一步定义Capability Schemaschema.pyfrom pydantic import BaseModel, Field from typing import List, Optional class ProcurementRequest(BaseModel): po_number: str Field(..., min_length8, patternr^PO-\d{6}$) items: List[dict] Field(..., min_items1) delivery_date: str Field(..., patternr^\d{4}-\d{2}-\d{2}$) class ProcurementResponse(BaseModel): status: str Field(..., patternr^(success|failed|pending)$) order_id: Optional[str] None error_code: Optional[str] None # 这个Schema会被自动转换为JSON Schema供MCP Registry校验提示Field里的pattern和min_length不是装饰而是MCP Router在转发前做的前置校验。如果上游传了po_numberABCRouter会直接返回400根本不会发给Agent这省去了Agent层的大量防御性编程。第二步实现Agent核心逻辑agent.pyimport asyncio from deepagents.mcp import MCPAgent from deepagents.a2a import A2AMessage class ProcurementAgent(MCPAgent): def __init__(self): super().__init__( capability_idprocurement:create_po_v1, input_schemaProcurementRequest, output_schemaProcurementResponse, # 这些QoS参数会自动上报给MCP Registry qos{latency_p95_ms: 1200, availability: 0.999} ) async def handle(self, message: A2AMessage) - ProcurementResponse: # 业务逻辑调用SAP API创建采购订单 try: sap_response await self._call_sap_api(message.payload) return ProcurementResponse( statussuccess, order_idsap_response.get(order_id) ) except SAPTimeoutError: return ProcurementResponse(statusfailed, error_codeSAP_TIMEOUT) except Exception as e: # 所有未捕获异常统一转为业务错误码 return ProcurementResponse(statusfailed, error_codeUNKNOWN_ERROR) # 启动Agent if __name__ __main__: agent ProcurementAgent() asyncio.run(agent.start())注意handle方法必须是async因为MCP SDK内部做了并发控制。self._call_sap_api是我们封装的SAP调用函数它内部会自动添加X-Trace-ID头与A2A的trace_id对齐。第三步配置与启动DockerfileFROM python:3.11-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . # 关键设置环境变量让SDK知道如何连接MCP和A2A ENV MCP_REGISTRY_URLhttp://mcp-registry:8080 ENV A2A_ROUTER_URLhttp://a2a-router:8081 CMD [python, agent.py]整个过程你不需要写一行HTTP服务器代码SDK会自动启动一个HTTP服务暴露/health和/metrics端点定期向MCP Registry发送心跳更新qos指标解析A2A Router发来的Message校验payload签名反序列化为ProcurementRequest将handle返回的ProcurementResponse自动加密并回调callback_url。这就是协议驱动开发的力量你只聚焦业务协议层兜底一切。3.3 A2A编排实战用YAML定义跨系统采购流程而非写死代码当采购流程涉及多个系统时硬编码调用链是灾难的开始。DeepAgents 21.3引入了a2a-workflowDSL用声明式YAML描述业务流程由A2A Orchestrator引擎执行。以下是一个真实的“跨境采购审批流”片段# workflow/po_approval.yaml version: 1.0 name: cross-border-po-approval description: 跨境采购订单审批需同步触发海关备案 steps: - id: validate_po capability_id: procurement:validate_po_v1 input: po_number: {{ .input.po_number }} items: {{ .input.items }} - id: check_customs_quota capability_id: customs:check_quota_v2 input: country: CN commodity_code: {{ .steps.validate_po.output.commodity_code }} # 如果这一步超时跳过不影响主流程 timeout: 3000 on_timeout: skip - id: create_sap_order capability_id: sap:create_po_v3 input: po_data: {{ .steps.validate_po.output }} customs_quota: {{ .steps.check_customs_quota.output }} # 失败时执行补偿动作 on_failure: - capability_id: sap:cancel_po_v1 input: {order_id: {{ .steps.create_sap_order.output.order_id }}} - id: notify_stakeholders capability_id: notification:send_email_v1 input: recipients: [procurementcompany.com, logisticscompany.com] template: po_approved context: po_number: {{ .steps.validate_po.output.po_number }} sap_order_id: {{ .steps.create_sap_order.output.order_id }} # 全局错误处理任何步骤失败都发告警 on_failure: - capability_id: alert:send_slack_v1 input: {channel: procurement-alerts, message: PO approval failed: {{ .error.message }}}这个YAML文件被加载到A2A Orchestrator后会生成一个有向无环图DAG每个step是一个节点。Orchestrator的核心能力在于动态参数绑定{{ .steps.validate_po.output.commodity_code }}这种语法不是模板渲染而是Orchestrator在运行时从上一步的ProcurementResponse中提取字段确保类型安全弹性错误处理on_timeout: skip意味着这一步可选而on_failure里的补偿动作是真正的SAGA模式保证最终一致性可观测性注入Orchestrator会为每个step生成独立的span在Jaeger里能看到完整的调用树精确到毫秒级耗时。我在某医疗器械公司实施时把这个YAML文件放在Git仓库里配合CI/CD每次修改审批流只需git pushOrchestrator自动热加载无需重启任何服务。这比改Java代码、重新打包、发版快了至少10倍。记住一个原则所有业务规则都应该写在YAML里而不是写在Agent的Python代码里。Agent只做原子操作Orchestrator负责组合。4. 部署与运维实战如何让集群在生产环境稳定运行365天4.1 生产级部署 checklist从资源隔离到密钥轮换把Demo跑通只是万里长征第一步让集群在生产环境扛住峰值流量、不出P0事故需要一份严谨的checklist。这是我给客户交付时必做的12项序号项目检查方法不合格后果我的实操建议1MCP Registry Redis持久化redis-cli CONFIG GET save重启后Capability丢失所有Agent无法发现设置save 60 10000即60秒内10000次变更触发RDB2A2A Router Kafka Topic分区数kafka-topics --describe --topic a2a-messages分区数3时高并发下消息积压生产环境至少设为6按ceil(峰值TPS/1000)计算3Agent JVM堆内存限制docker inspectgrep MemoryOOM Killer杀进程Agent静默退出4MCP JWT密钥轮换机制检查MCP_JWT_SECRET是否为KMS托管密钥密钥泄露恶意Agent可伪造注册使用AWS KMS或HashiCorp VaultSDK支持自动轮换5A2A Payload加密密钥长度echo $A2A_ENCRYPTION_KEYwc -c32字节AES-256-GCM降级为弱加密6Agent健康检查端点可用性curl -f http://agent:8000/healthRouter将Agent标记为down流量被剔除健康检查必须包含DB连接、外部API连通性7日志等级统一为INFOdocker logs service | head -n 10DEBUG日志刷爆磁盘影响性能在logging.yml里全局配置禁止Agent覆盖8MCP Registry TLS证书有效性openssl s_client -connect mcp-registry:8080 -servername mcp-registry 2/dev/null | openssl x509 -noout -datesAgent注册失败报SSL handshake error使用Lets Encrypt配合cert-manager自动续期9A2A Router重试队列深度redis-cli LLEN a2a-retry-queue积压过多导致延迟飙升设置max_retry_queue_size10000超限触发告警10Agent QoS指标上报频率查看MCP Registry/metrics中mcp_agent_qos_latency_secondsSLA数据不准Router负载不均默认30秒高敏感业务可调至10秒11Workflow YAML语法校验a2a-workflow validate workflow/po_approval.yaml加载失败整个流程不可用CI阶段加入make validate失败则阻断发布12跨AZ部署的Kafka副本数kafka-topics --describe --topic a2a-messages | grep ReplicationFactor单AZ故障消息总线瘫痪生产环境必须≥3且分布在不同AZ其中最容易被忽视的是第4项和第8项。JWT密钥和TLS证书是整个信任链的根。我曾遇到一个案例客户把MCP_JWT_SECRET写在Docker Compose的env文件里Git提交时没加.gitignore导致密钥泄露。攻击者用这个密钥注册了一个假的finance:transfer_money_v1Agent伪装成财务系统接收了所有转账请求。所以密钥管理不是运维的事是每个开发者的责任。我的做法是所有密钥都从Vault读取Agent启动时通过VAULT_ADDR和VAULT_TOKEN环境变量连接SDK内置Vault client自动轮换。4.2 故障排查黄金四象限从日志、指标、链路、配置四维度定位问题当业务报警“采购订单创建失败率突增到15%”不要慌按这四个维度系统排查第一象限日志Log——看发生了什么查A2A Router日志docker logs a2a-router \| grep procurement:create_po_v1 \| tail -50如果看到No active endpoint found for capability_id说明MCP Registry里没有可用的采购Agent去查Agent的/health是否返回200如果看到Payload decryption failed说明加密密钥不匹配检查A2A_ENCRYPTION_KEY是否在所有服务中一致查采购Agent日志docker logs procurement-agent \| grep ERROR如果看到Connection refused to sap-api.internal说明网络策略阻止了Agent访问SAP检查Docker网络或K8s NetworkPolicy。第二象限指标Metrics——看有多严重访问http://mcp-registry:8080/metrics关注mcp_capability_status{capability_idprocurement:create_po_v1,statusactive}应为1否则Agent未注册成功mcp_agent_qos_availability_ratio{capability_idprocurement:create_po_v1}如果低于0.99说明Agent频繁失败访问http://a2a-router:8081/metrics关注a2a_router_message_latency_seconds_bucket{le1.0,capability_idprocurement:create_po_v1}P90超过1秒说明下游慢a2a_router_message_failed_total{capability_idprocurement:create_po_v1}陡增结合日志看错误类型。第三象限链路Trace——看路径哪里断了在Jaeger UI中搜索trace_id从Router日志里复制查看完整调用链如果链路只到Router没到Agent说明Router找不到Endpoint查MCP Registry如果链路到了Agent但Agent的Span显示statusERROR点开看error.message如果链路在SAP调用处中断且Span显示http.status_code503说明SAP过载需扩容。第四象限配置Config——看是不是人为失误登录MCP Registry Admin UIhttp://mcp-registry:8080/admin检查procurement:create_po_v1的endpoints列表是否为空如果是Agent可能注册时网络不通qos.latency_p95_ms是否被误设为10000Router会把它踢出负载池检查Workflow YAMLcat workflow/po_approval.yaml \| grep create_sap_order确认on_failure补偿动作是否正确引用了order_id。我总结了一个速查表贴在团队共享文档里现象最可能象限排查命令/路径解决方案所有Agent调用都超时指标链路curl http://a2a-router:8081/metrics | grep latency检查Kafka是否堆积kafka-consumer-groups --group a2a-router --describe某个Capability调用失败其他正常配置日志curl http://mcp-registry:8080/capabilities/procurement:create_po_v1检查该Capability的endpoints和status字段Router日志报Invalid JWT配置日志echo $MCP_JWT_SECRET | wc -c确保所有服务使用相同密钥且长度为32Workflow执行一半就停了链路日志Jaeger中找workflow_id看最后一个Span检查YAML中on_failure是否定义或input绑定是否有语法错误记住90%的线上问题都能在这四个象限里找到答案。不要凭感觉猜要拿数据说话。4.3 性能压测与容量规划如何科学预测集群承载能力很多团队上线前不做压测结果大促时订单创建失败率飙升。DeepAgents的性能瓶颈不在Agent本身而在协议层。我用k6做了三轮压测结论很清晰第一轮单Capability压测采购Agent场景100并发持续5分钟调用procurement:create_po_v1结果P95延迟120ms成功率100%CPU使用率65%结论Agent本身无瓶颈瓶颈在Router和Registry第二轮A2A Router压测场景1000并发调用同一个Capability结果P95延迟跳到850ms失败率2%Router CPU 95%根因Kafka Producer缓冲区打满kafka_producer_buffer_total_bytes指标达上限方案调大producer.buffer.memory至64MB增加Kafka Broker副本数第三轮全链路压测含Workflow场景200并发执行cross-border-po-approvalWorkflow含4个Agent结果P95延迟2100ms失败率8%主要失败在check_customs_quota超时根因海关API限流check_customs_quota的timeout: 3000太激进方案将该Step超时设为10000ms并增加on_timeout: use_default_quota降级逻辑基于这些数据我建立了容量规划公式Router所需CPU核数 (峰值TPS × 平均消息处理耗时ms) / 1000 × 1.5 Kafka所需分区数 ceil(峰值TPS / 1000) × 3 MCP Registry Redis内存 (Capability总数 × 2KB) (QoS指标 × 500bytes × 采集频率)例如某客户预估峰值TPS为5000平均处理耗时800ms则Router需(5000×800)/1000×1.56000毫核即6个vCPU。这个数字比拍脑袋说“上8核”靠谱十倍。压测不是为了证明系统很强而是为了量化它的弱点并提前加固。5. 常见问题与独家避坑指南那些文档里不会写的血泪教训5.1 “Capability注册成功但Router调用时404”——时间差陷阱现象Agent日志显示Registered capability procurement:create_po_v1 successfully但Router日志却报404 Not Found for capability_idprocurement:create_po_v1。原因MCP Registry的注册是异步的。Agent调用POST /register后Registry会先返回202 Accepted然后在后台将Capability写入Redis。如果Router在写入完成前就查询就会404。这在高并发注册时尤其明显。解决方案短期在Agent启动后加一个time.sleep(2)等Registry写入完成不推荐治标不治本长期在Agent SDK里启用wait_for_registrationTrue参数SDK会轮询GET /capabilities/{id}直到返回200再启动HTTP服务最佳实践在Docker Compose里为Router加healthcheck检查curl -f http://mcp-registry:8080/capabilities/procurement:create_po_v1确保Registry就绪后再启动Router。我的实操心得这个坑我踩了三次。第一次在测试环境以为是网络问题第二次在预发怀疑是DNS缓存第三次才抓包发现Registry的/register接口确实返回了202。从此所有Agent的启动脚本里都加了--wait-for-mcp参数。5.2 “Workflow执行时输入参数丢失”——YAML锚点与引用的隐式转换现象Workflow中定义了commodity_code: {{ .steps.validate_po.output.commodity_code }}但实际调用customs:check_quota_v2时传过去的是空字符串。原因YAML的锚点anchor和引用*anchor在DeepAgents的DSL解析器里会被当作字符串字面量处理而不是变量引用。更隐蔽的是如果validate_po返回的commodity_code是整数类型如12345而YAML解析器期望字符串就会静默转为空。解决方案绝对禁止在Workflow YAML里用和*做变量复用全部用{{ .steps.xxx.output.yyy }}显式引用强制类型转换在input里写commodity_code: {{ toString(.steps.validate_po.output.commodity_code) }}SDK内置了toString、toInt等函数增加Schema校验在customs:check_quota_v2的input_schema里
返回列表