
Envoy A2A HTTP 过滤器深度解析Agent-to-Agent 协议支持与 JSON-RPC 校验实战【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy导读A2AAgent-to-Agent是面向 AI Agent 间通信的开放协议其消息基于 JSON-RPC 2.0 封装。Envoy 通过envoy.filters.http.a2a过滤器为 HTTP 流量提供 A2A 协议支持它负责识别 A2A 请求、按 A2A 规范校验 JSON-RPC 消息结构、从请求体中按需提取关键属性并写入动态元数据dynamic metadata同时以可配置的流量模式透传或拒绝处理非 A2A 流量。读完本文你将掌握 A2A 过滤器的完整配置方法、每个配置字段的语义与取值范围、请求识别与校验的内部实现原理以及如何利用其统计指标和属性提取能力构建面向 AI Agent 网关的流量治理方案。A2A 过滤器概述A2A 过滤器定义在 a2a_filter.rst 中其对应的配置原型为 a2a.proto。该过滤器会对进入的 A2A 流量进行检测并提取属性底层复用 Envoy 的通用 JSON-RPC 字段提取器json_rpc_field_extractor.h与 JSON-RPC 解析配置json_rpc_parser_config.h实现流式、按需、可提前终止的 JSON 解析。需要说明的是该过滤器目前仍处于开发中状态proto 文件标注work_in_progress true配置字段与行为可能随版本演进使用时请以当前仓库api/envoy/extensions/filters/http/a2a/v3/a2a.proto为准。快速上手最小配置示例原文档给出了最精简的启用方式——仅指定过滤器名称与类型其余全部采用默认值http_filters: - name: envoy.filters.http.a2a typed_config: type: type.googleapis.com/envoy.extensions.filters.http.a2a.v3.A2a将该过滤器添加到 HTTP 连接管理器HCM的http_filters链中即可。默认行为下过滤器的traffic_mode默认为PASS_THROUGH对非 A2A 流量不校验、直接透传请求体缓冲上限默认为 8KB8192 字节storage_mode默认为NONE不存储任何解析出的属性。一个完整可运行的 listener 配置示例如下static_resources: listeners: - name: a2a_listener address: socket_address: { address: 0.0.0.0, port_value: 10000 } filter_chains: - filters: - name: envoy.filters.network.http_connection_manager typed_config: type: type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager stat_prefix: a2a_ingress route_config: name: local_route virtual_hosts: - name: a2a_service domains: [*] routes: - match: { prefix: / } route: { cluster: a2a_backend } http_filters: - name: envoy.filters.http.a2a typed_config: type: type.googleapis.com/envoy.extensions.filters.http.a2a.v3.A2a - name: envoy.filters.http.router typed_config: type: type.googleapis.com/envoy.extensions.filters.http.router.v3.Router注意A2A 过滤器通常应放置在路由器过滤器envoy.filters.http.router之前以便在路由转发前完成对请求的校验与属性提取。配置字段详解A2A 过滤器的完整配置由A2a消息定义a2a.proto承载包含五个字段traffic_mode、max_request_body_size、parser_config、storage_mode以及内部复用的解析器配置。下表汇总了全部配置项字段类型默认值说明traffic_modeenumTrafficModePASS_THROUGH0非 A2A 流量的处理方式透传或拒绝max_request_body_sizegoogle.protobuf.UInt32Value81928KB为 JSON-RPC 校验缓冲的请求体最大字节数超限返回 413最大可配 1048576010MB设为 0 表示不限制生产环境不推荐parser_configParserConfig见下文解析器的自定义配置用于方法分组与属性提取storage_modeenumStorageModeNONE0解析出的消息属性存储位置动态元数据、过滤器状态filter state或两者traffic_mode非 A2A 流量的处置策略TrafficMode枚举定义了两个取值PASS_THROUGH0默认不进行 A2A 规范检查直接将 HTTP 请求与响应代理转发。适合旁路观测场景——先分析流量、收集属性但不阻断任何请求。REJECT1拒绝不符合 A2A 规范的请求。从 a2a_filter.cc 的实现看拒绝时过滤器直接调用sendLocalReply返回400 Bad Request响应体为Only A2A traffic is allowed并累加requests_rejected计数器。两种模式的判定发生在decodeHeaders请求头解码阶段请求头不符合 A2A 识别规则见下文请求识别规则且流量模式为REJECT时立即拒绝若为PASS_THROUGH则直接放行。max_request_body_size请求体缓冲上限A2A 校验需要缓冲并解析请求体为防止内存被无界缓冲耗尽过滤器引入了请求体大小上限默认 8KB8192 字节足以覆盖绝大多数 A2A 消息头字段如jsonrpc、method、id等核心属性最大允许值 10MB10485760 字节由 proto 校验规则lte: 10485760约束设为 0 表示禁用限制但 proto 注释明确警告生产环境不建议这样配置。该限制对REJECT和PASS_THROUGH两种模式同时生效防止任何模式下出现无界缓冲。实现上过滤器通过decoder_callbacks_-setDecoderBufferLimit(max_size)设置解码器缓冲区上限a2a_filter.cc并在decodeData中逐片slice计数累计解析字节数bytes_parsed_。一旦累计达到上限即使请求未结束也会触发finishParse若请求体确实超限返回413 Payload Too Large响应体为request body is too large.并累加body_too_large计数器a2a_filter.cc。storage_mode属性存储位置StorageMode枚举定义了解析出的 A2A 消息属性写入何处取值名称行为0NONE不存储默认1DYNAMIC_METADATA仅写入动态元数据2FILTER_STATE仅写入过滤器状态3DYNAMIC_METADATA_AND_FILTER_STATE同时写入动态元数据与过滤器状态从当前源码看completeParsing 已实现动态元数据写入当提取的属性非空时通过streamInfo().setDynamicMetadata(filterConfigName, metadata)将解析结果写入以过滤器配置名为键的动态元数据中后续的下游过滤器、access log、限流或可观测性组件均可按该键读取。源码中留有 TODO 注释说明动态元数据的写入键与行为未来会进一步由配置控制。因此生产使用DYNAMIC_METADATA相关模式前建议以当前仓库源码行为为准验证。parser_config解析器自定义ParserConfiga2a.proto用于定制属性提取行为包含三个子字段字段类型说明method_configsmapstring, MethodParsingConfig按方法名如message/send配置分组与提取路径未配置的方法由内置分类规则按方法前缀分组并套用默认提取规则always_extract_attributesrepeated string无论哪个方法都始终提取的属性按 JSON 路径指定如params.idgroup_metadata_keystring方法分组名写入动态元数据所用的键如a2a_group为空则不写入分组信息其中MethodParsingConfiga2a.proto包含group为该方法指定的分组/类别名如tasks、message用于覆盖内置分类写入group_metadata_key指定的动态元数据键paths为该方法额外提取的属性列表按 JSON 路径指定如params.name。一个利用自定义解析配置的示例http_filters: - name: envoy.filters.http.a2a typed_config: type: type.googleapis.com/envoy.extensions.filters.http.a2a.v3.A2a traffic_mode: REJECT max_request_body_size: 262144 # 256KB storage_mode: DYNAMIC_METADATA parser_config: group_metadata_key: a2a_group always_extract_attributes: - params.id method_configs: message/send: group: messaging paths: - params.message.parts tasks/get: group: task_management请求识别规则什么是A2A 流量过滤器在请求头解码阶段判定请求是否为 A2A 流量规则集中于 isValidA2aGetRequest 与 isValidA2aPostRequest 两个方法GET 请求Agent Card 发现方法必须是GET路径去掉查询参数与 fragment 后必须等于/.well-known/agent-card.json。这是 A2A 发现标准对 Agent Card 已知 URI 的约定源码注释引用了 a2a-protocol 的发现策略文档注册表Registry与私有发现路径属于部署自定义内容过滤器无法推断因此仅校验 well-known 路径。POST 请求JSON-RPC 调用方法必须是POSTContent-Type必须以application/json或 A2A 专属媒体类型application/a2ajson开头允许其后跟;或空格如带 charset 参数的情况。带体的 GET 请求依据 RFC 7231GET 请求中的 payload 没有定义语义因此在REJECT模式下 GET 带体将被拒绝PASS_THROUGH模式下则放行。工作流程从请求头到解析完成结合 a2a_filter.cc 的实现A2A 过滤器在解码链路上的完整流程如下decodeHeaders请求头阶段若是合法的 A2A GETAgent Card 请求且end_stream为 true标记为 A2A 请求并直接放行无需体解析若是合法的 A2A POST若end_stream无请求体不进入 JSON-RPC 校验否则标记为 A2A 请求、设置解码器缓冲上限并返回StopIteration暂停迭代等待请求体到达若既不是 A2A GET 也不是 A2A POST且traffic_mode为REJECT则返回400拒绝并累加requests_rejected统计其余情况透传继续。decodeData请求体阶段仅对 A2A POST 请求执行解析完成后直接放行首次进入时惰性创建A2aJsonParser实例a2a_json_parser.cc内部基于ProtobufUtil::converter::JsonStreamParser做流式 JSON 解析配合A2aFieldExtractor继承自通用 JsonRpcFieldExtractor按需提取字段逐片解析请求体字节流并累计bytes_parsed_若所有目标字段已收集齐全isAllFieldsCollected()为 true触发提前终止解析early stop optimization立即进入完成阶段——这是为降低大请求体解析开销设计的优化若解析过程中出现 JSON 语法错误返回400not a valid JSON并累加invalid_json统计请求结束end_stream或达到大小上限时调用finishParse()若因大小上限终止返回413并累加body_too_large若 JSON 不完整返回400not a valid JSON (incomplete).并累加invalid_json解析完成后进入completeParsing()判定请求是否为合法 JSON-RPC 2.0 消息extractor_-isValidJsonRpc()若非法且为REJECT模式则返回400request must be a valid JSON-RPC 2.0 message for A2A否则将提取出的属性写入动态元数据键为过滤器配置名后继续转发。整体上A2A 校验的核心是验证 JSON-RPC 2.0 的必填字段jsonrpc版本号、method方法名等并非对每个业务字段做模式校验。属性提取内置方法规则与默认字段A2A 解析器的默认配置定义在 a2a_json_parser.cc 的initializeDefaults()中。它始终提取以下 JSON-RPC 核心字段jsonrpc协议版本method方法名id请求标识TODO 注释指出通知类消息中可能不存在id同时针对不同的 A2A 方法内置了默认的属性提取规则方法名提取的属性JSON 路径message/send、message/streamparams.taskId、params.message.taskId、params.message.contextId、params.message.messageId、params.message.role、params.message.kind、params.message.metadata、params.message.parts、params.configuration、params.metadatatasks/get、tasks/resubscribeparams.id、params.historyLength、params.metadatatasks/listparams.tenant、params.contextId、params.status、params.pageSize、params.pageToken、params.historyLength、params.lastUpdatedAfter、params.includeArtifactstasks/cancelparams.id、params.metadatatasks/pushNotificationConfig/setparams.taskId、params.pushNotificationConfig.id、params.pushNotificationConfig.url、params.pushNotificationConfig.token、params.pushNotificationConfig.authenticationtasks/pushNotificationConfig/get、tasks/pushNotificationConfig/listparams.id、params.metadata、params.pushNotificationConfigIdtasks/pushNotificationConfig/deleteparams.id、params.pushNotificationConfigIdagent/getAuthenticatedExtendedCard无内置提取规则空列表若在parser_config.method_configs中为某个方法指定了group或paths则以自定义配置为准覆盖内置规则未配置的方法则按方法前缀内置分类例如message/send归入message分组。字段提取由A2aFieldExtractor完成其关键特性是支持列表字段lists_supported()返回 true并针对 A2A 协议关闭了 JSON-RPC notification 语义isNotification()恒为 false。提取结果以Protobuf::Struct形式保存可通过metadata()获取或通过getNestedValue(params.message.role)这类点分路径按需读取。统计指标A2A 过滤器通过A2A_FILTER_STATS宏定义了三项计数器见 a2a_filter.h指标前缀为过滤器统计前缀加a2a.a2a_filter.cc指标名类型触发场景a2a.requests_rejectedCounter非 A2A 流量在REJECT模式下被拒绝a2a.invalid_jsonCounter请求体 JSON 语法错误或 JSON-RPC 结构不完整/非法a2a.body_too_largeCounter请求体超过max_request_body_size上限这些指标可通过 Envoy 的:8001/stats管理接口按前缀查询例如curl http://127.0.0.1:8001/stats?filtera2a用于观测网关上的 A2A 流量健康度与非法请求比例。测试与验证仓库为 A2A 过滤器提供了完整的单元测试与集成测试是理解其行为边界的最佳参考a2a_filter_test.cc覆盖过滤器在PASS_THROUGH/REJECT模式下的各类请求GET Agent Card、合法/非法 POST、带体 GET、超限请求体等的判定与响应a2a_json_parser_test.cc验证 JSON 流式解析、字段提取、提前终止与非法 JSON 处理a2a_filter_integration_test.cc以完整 Envoy 实例验证过滤器在真实请求链路中的行为如 413/400 响应、动态元数据写入等。如需在本地跑测试可在仓库根目录执行 bazel 测试需要 bazel 环境bazel test //test/extensions/filters/http/a2a:all典型应用场景与部署建议综合上述能力A2A 过滤器在当前项目中适合以下场景AI Agent 网关入口治理在暴露给 Agent 客户端的 ingress 上以REJECT模式部署确保只有符合 A2A/JSON-RPC 2.0 规范的请求进入后端 Agent 服务非法请求在边缘即被拦截Agent 流量观测以PASS_THROUGHstorage_mode: DYNAMIC_METADATA模式部署在不影响业务的前提下把message/send、tasks/*等方法的taskId、contextId、role等属性提取进动态元数据供 access log、遥测与后续限流/路由决策使用A2A 合规试点proto 文件仍标注work_in_progress建议先在测试环境验证storage_mode中 filter state 相关行为与当前源码版本的一致性再推向生产。部署时需重点确认的三件事traffic_mode是否会误伤非 A2A 的 HTTP 流量默认PASS_THROUGH相对安全max_request_body_size是否覆盖真实 Agent 消息的最大体积默认 8KB 偏保守以及启用DYNAMIC_METADATA后下游组件读取的元数据键当前为过滤器配置名。小结Envoy 的 A2A 过滤器以识别—校验—提取—存储四个环节为 AI Agent 间通信提供协议级网关能力通过/.well-known/agent-card.json与application/a2ajson识别 A2A 流量基于 JSON-RPC 2.0 校验消息合法性以可配置的路径规则流式提取关键属性并借助动态元数据打通下游可观测与治理链路。其配置核心是traffic_mode透传/拒绝、max_request_body_size缓冲上限、storage_mode属性去向与parser_config提取定制。由于该过滤器仍处于开发中建议持续关注 a2a.proto 的字段演进并结合 a2a_filter_test.cc 等测试用例验证实际行为。【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考