首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >当 WorkBuddy 接上 Elastic(下):用 MCP 把任务"点兵点将"地交给 AI Agent

当 WorkBuddy 接上 Elastic(下):用 MCP 把任务"点兵点将"地交给 AI Agent

原创
作者头像
点火三周
发布2026-08-03 15:46:00
发布2026-08-03 15:46:00
2831
举报

本文是《当 WorkBuddy 接上 Elastic:用 A2A 把一群各管一摊的 Agent 拧成一支团队》的姊妹篇。上一篇讲了怎么让多个专业 Agent 在背后协作;这一篇讲另一条更轻、更直接的路径——当任务不复杂到需要一整支团队、又确实想甩给集群上的 Agent 时,WorkBuddy 怎么通过 MCP 把活"点兵点将"地派出去。


还是从那次 checkout 故障说起

上一篇里我们用 A2A 协议做了一次漂亮的多 Agent 协同——审计助手扫日志、SRE 助手查指标,最后在一个对话窗口里把因果链拼起来。那次的体感很好,但跑完之后我也发现,并不是每个问题都需要"开团队会"。

举个反例。同样是 checkout 服务的延迟告警,有时候我只是想看一眼现在告警消没消,问一句"当前有哪些 active alert"就够了。这时候再走一遍"Supervisor 拆任务 → A2A 派给 SRE Agent → Agent 加载技能 → 多步推理 → 异步轮询结果"的流程,就像为了喝口水而煮一锅汤。等结果那 45 秒里我明明可以一秒拿到结构化数据。

更有甚者。有时候我连 Agent 自己的推理都不想要——我知道我要查的是某条 ES|QL,我只想让集群上的 AI Agent 帮我把 LLM 调一次、回我个答案。这种场景下,A2A 那套"会话上下文 + 跨 Agent 协同"的设计反而是过度工程。

于是问题来了:该不该为这种轻量任务再写一套胶水代码?

答案是不需要。Elastic 早就把另一条更短的路给你留好了——它叫 MCP(Model Context Protocol)。这一篇我们就讲,怎么用 MCP 这条"短路径"把任务 delegate 到 Elastic AI Agent,以及 A2A 和 MCP 之间到底怎么分工。

MCP vs A2A:不是替代,是互补

先把这个最常见的误解掰扯清楚。

很多人问过我:"既然 Elastic 既有 A2A 又支持 MCP,那到底用哪个?是不是新出来的更先进?"

不是这层关系。A2A 和 MCP 解决的是两类不同的连通问题。打个比方:MCP 是 Agent 长手去够外部资源(数据库、API、文件),它让 Agent 自己变强;A2A 是 Agent 之间互相打电话,它让多个 Agent 协同。一个对物,一个对人,分工很清楚。在上篇里我写过同样这句话,这里再强调一次,因为下文都建立在这个前提上。

但这一篇里我们关注的,是 MCP 在一个更具体的位置——它不只是 Agent 自己连工具的接口,还可以是 Agent 暴露给外部调用方的接口。也就是说,Elastic 把它托管的那些 Agent 能力,自己也包成 MCP server 暴露出来了。你不用发 JSON-RPC 给 Agent,你直接以 MCP 客户端的身份,调一个又一个 tool 就行。

这就有意思了。同样是把任务 delegate 给 Elastic,你有两条路:

维度

A2A(上篇)

MCP(本篇)

通信协议

JSON-RPC 2.0 over HTTP

JSON-RPC 2.0 over stdio/SSE

调用粒度

发一条"消息"给 Agent

直接调某个 tool(如 observability_get_alerts

推理方在哪

Elastic 端的 Agent

谁调谁推理,或 Elastic 端的 LLM

上下文

完整会话,跨轮保持

单次工具调用,无状态

延迟

重型 Agent 几十秒到几分钟

大多几百毫秒到几秒

稳定性

易 502,需要异步轮询兜底

稳定,简单 RPC

适用任务

跨 Agent 协同、长链路分析、多步推理

单步查询、点对点调用、结构化数据取回

这张表才是真正的判断依据。不是哪个"更先进",而是哪个更匹配你眼前这个任务。

什么时候用 A2A:业务链条长(要查 → 要分析 → 要交叉验证)、能力分散在多个 Agent 上、需要多轮上下文、需要 Agent 自己规划工具调用序列。典型例子是上一篇里"先扫审计日志再交叉看指标"那条流水线,没人能在一句话里讲完。

什么时候用 MCP:你就想要一份具体数据,知道要调哪个工具。比如"现在有哪些活跃告警"、"这台主机最近一小时的 CPU"、"列出最近的 ES 索引"——这些问题不需要 Agent 帮你推理,只需要它帮你查,用 MCP 一调一个准。

但这里还有个第三档场景,我们今天会专门讲:当你确实想让 Agent 帮忙推理(不是裸调工具),但又不需要会话上下文,也不想要 A2A 那套异步轮询机制。比如让 Agent 用 ES|QL 查个数据、用自然语言回答你——这种"轻推理 + 单轮"的任务,MCP 的 tools 不能直接做(因为 tool 只返回结构化数据,没有 LLM),A2A 又太重。这时候,Elastic 给你留了一个新的中间档端点,叫 converse,下面会详细讲。

先讲两条已经成熟的路,再讲这条新中间档。

第一步:在 Elasticsearch 上拿到 MCP server 的地址

要让 WorkBuddy 当 MCP 客户端去调 Elastic,先得知道 Elastic 这个 MCP server 长在哪。

如果你的 Elastic 是自建集群,Kibana 的 URL 通常是 http://your-kibana-host:5601;如果是 Elastic Cloud,那 URL 长这样:https://<deployment-name>.kb.<region>.aws.elastic-cloud.com。比如我这个 demo 是 https://lex-demo.kb.ap-east-1.aws.elastic-cloud.com

MCP server 的端点路径是固定的,挂在 Kibana URL 下:

代码语言:json
复制
https://<kibana-url>/s/<space-id>/api/agent_builder/mcp

其中 <space-id> 是 Kibana 的 Space 名,默认就是 default。所以我的环境完整的 MCP server 地址就是:

代码语言:json
复制
https://lex-demo.kb.ap-east-1.aws.elastic-cloud.com/s/default/api/agent_builder/mcp

这个地址不需要你翻文档去抄——直接在 Kibana 里走 代理→ 工具 → 管理 MCP → 复制MCP服务器URL(不同版本菜单略有差异),复制即可。

光有地址还不够。Elastic 的 MCP server 是受保护的,必须带鉴权。最方便的方式是去 Stack Management → Security → API Keys 创建一个 API Key,要带 read_agent_builder 之类的权限(如果你想 converse 也能跑,再加 agent_builder_api)。创建完之后,一定要复制 Encoded 那个长 base64 串——只有它可以直接拼到 Authorization: ApiKey <encoded> 这个 HTTP 头里用。

一个工程小贴士:API Key 这个东西很多人图省事,写代码里、写 shell 历史里、push 到 git 里。Elastic 的审计日志会按 key 记身份,如果你把同一个 key 同时用在五台机器十个项目上,出了问题没法分锅。给每个调用方单独建一个 key,是真正能落地的最小安全单位。

到这里你已经拿到两个值:MCP server 的 URL,和一个 API Key。下面去 WorkBuddy 里把它们配上。

第二步:在 WorkBuddy 里配置 Elastic MCP server,并拿到 tools

WorkBuddy 的 MCP 配置都在一个文件里:~/.workbuddy/mcp.json。所有接入的 MCP server 都写在 mcpServers 这个对象下,每条对应一个 server。

针对 Elastic 的 MCP server,配置长这样(API Key 已脱敏):

代码语言:json
复制
{
  "mcpServers": {
    "lex-demo-agent-builder": {
      "command": "npx",
      "args": [
        "mcp-remote",
        "https://lex-demo.kb.ap-east-1.aws.elastic-cloud.com/s/default/api/agent_builder/mcp",
        "--header",
        "Authorization: ApiKey <把你的 encoded key 粘这里>"
      ],
      "disabled": false
    }
  }
}

为什么要套一层 npx mcp-remote

这其实是个工程细节。MCP 协议本身支持两种传输:stdio(本地进程间)和 http/sse(远程 HTTP)。WorkBuddy 本地客户端默认按 stdio 跟 MCP server 对话,但 Elastic 的 MCP server 是远程的 HTTP/SSE 端点。mcp-remote 这个 npm 包就是个——它在本地启一个 stdio MCP server,背后把请求转成 HTTP 发给 Elastic,再把 SSE 流转回 stdio。这样 WorkBuddy 端只需要会"说 stdio",不用关心对面是不是远程。

好处说一下:这套桥接不要求 WorkBuddy 自己支持 HTTP/SSE 传输,等于一份客户端代码通吃了"本地 stdio MCP"和"远程 HTTP MCP"两类服务端,新增 server 的成本只剩写配置文件。这正是协议设计者把传输层做成可插拔的本意——你不需要为每一种 transport 都做适配。

配置写完保存,WorkBuddy 会自动重连这个 server,并把 server 上暴露的所有 tools 拉下来注册。你可以直接在对话里看 tools 列表(用 ToolSearch 这种内部接口,或通过 Help 菜单)。接上之后我这边能看到的 tools 大致是这几类:

  • platformcore 系列:execute_esqlsearchlist_indicesgenerate_esqlget_index_mappingcreate_visualization——核心数据查询和索引管理。
  • platformworkflows 系列:get_connectorsget_step_definitionsget_trigger_definitionsworkflow_*——和 Elastic 的 Workflow(流程编排)相关,下面会专门讲其中一个。
  • observability_ 系列:get_alertsget_servicesget_hostsget_tracesget_logsget_anomaly_detection_jobs——可观测性数据查询。
  • platformstreams 系列:list_streamsget_streamget_data_quality——数据流管理。
  • security_ 系列:search_entitiescreate_detection_rule——安全实体检索和检测规则。

注意一个关键点:这些 tool 大多返回的是结构化数据,不是自然语言回答。你调 observability_get_alerts 拿到的就是一个告警对象数组,里面是 status / started_at / payload 这些字段。它不会帮你"分析"这些告警意味着什么。如果你想让它分析,就走到 LLM 那条路了,那就是接下来要讲的 converse 端点。

工程上的取舍:tool 直接返回结构化数据,意味着调用方(WorkBuddy)拿到的是干净的、可程序化处理的数据,不是一段需要再解析的人话。这让它非常适合做自动化监控、数据汇总、报表生成这种"我已知要什么"的场景。代价是:你要先知道你要调哪个 tool、传哪些参数。这对不知道精确参数名的新手不友好——A2A 那条路让 Agent 自己规划工具序列,对模糊需求更友好。

光有 tools 还不能 converse。converse 端点要求你额外提供一个叫 connector_id 的字段,它是底层 LLM 的标识。这个值怎么拿?看下一步。

第三步:用 platform.workflows.get_connectors 拿到 connector id

Elastic 把"调哪个 LLM"这件事抽象成了 Connector 这个概念——一个 connector 就是一份预配置好的、能跑 LLM 推理的资源,它后面可能是 Anthropic Claude、可能是 Google Gemini、可能是 OpenAI GPT、可能是 Bedrock 上的某个 Claude、甚至可能是你自建的 OpenAI 兼容端点(比如混元)。

这些 connector 不是写死的,是在 Kibana 里由管理员配置的,列表随时可能变。所以 converse 之前,你必须先动态查一下当前环境里有哪些 connector 可用

这就轮到 MCP 出场了。WorkBuddy 配好 Elastic MCP 之后,可以直接调 platform_workflows_get_connectors 这个 tool,参数都不用传(空对象就行):

代码语言:bash
复制
工具:mcp__lex-demo-agent-builder__platform_workflows_get_connectors
参数:{}

返回大致这样(截短示例):

代码语言:json
复制
{
  "count": 30,
  "totalAvailable": 34,
  "connectors": [
    {
      "id": "elastic-cloud-email",
      "name": "Elastic-Cloud-SMTP",
      "actionTypeId": ".email",
      "stepTypes": ["email"]
    },
    {
      "id": "0cc46266-...-6ef7b4f783cb",
      "name": "gpt4",
      "actionTypeId": ".gen-ai",
      "stepTypes": ["gen-ai.run", "gen-ai.invokeAI", ...]
    },
    {
      "id": "Anthropic-Claude-Sonnet-4-5",
      "name": "Anthropic Claude Sonnet 4.5",
      "actionTypeId": ".inference",
      "stepTypes": ["inference.unified_completion", "inference.completion", ...]
    },
    {
      "id": "Google-Gemini-2.5-Pro",
      "name": "Google Gemini 2.5 Pro",
      "actionTypeId": ".inference",
      ...
    },
    {
      "id": "OpenAI-GPT-5-2",
      "name": "OpenAI GPT-5.2",
      "actionTypeId": ".inference",
      ...
    },
    ...
  ]
}

返回里几个字段要会读:

  • id:connector 的唯一标识,这就是 converse 端点要的那个 connector_id。注意它可能是 UUID(自己建的 connector)、可能是带版本号的名字(如 Anthropic-Claude-Sonnet-4-5)、也可能是带前缀点的(如 .openai-gpt-5.4-chat_completion),格式不统一,但都是字符串。
  • name:人类可读的名字,方便你挑。
  • actionTypeId:底层类型,决定了能调用哪些 stepTypes。.inference 是统一推理端点,gen-ai 是通用生成式 AI,.bedrock 是 AWS Bedrock,.mcp 是连外部 MCP 的桥接 connector,.email 是发邮件。
  • stepTypes:这个 connector 支持的步骤类型清单。一般你不需要关心,除非你要用 workflow 编排高级场景。

我环境里返回了 30 个 connector,覆盖了 Anthropic Claude 全系列(Haiku 4.5 → Opus 4.8)、Google Gemini(2.5 → 3.5)、OpenAI GPT(5.2 → 5.5、OSS 120B/20B),还有腾讯的混元、AWS Bedrock 上的 Claude、Jina 和 Tavily 的 MCP connector。这个阵容基本可以满足任何类型的推理需求。

一个值得说的工程细节:Elastic 的 connector 概念把"调哪个模型"这件事彻底配置化了。这意味着同一个 Agent 配置不动,只要换 connector_id,就能从"用 Sonnet 4.5 跑"切到"用 GPT-5.5 跑"——你不需要改 Agent 的 prompt,不需要改 Agent 的工具集,也不需要重新部署。这对 A/B 测试模型、对降本(白天用 Sonnet、夜里用 Haiku)、对容灾(某家 API 挂了切另一家)都是天然支持。用 connector_id 而不是 model name 是这套设计的关键——它能解耦"用谁"和"怎么用"。

到这里你已经知道了"有哪些 connector 可用"。下面把它们组合起来,把任务真正 delegate 出去。

第四步:用 POST kbn://api/agent_builder/converse 把任务 delegate 出去

这是本文要重点讲的新中间档端点。它的路径是:

代码语言:http
复制
POST /s/<space-id>/api/agent_builder/converse

完整 URL 形如 https://<kibana>/s/default/api/agent_builder/converse。请求头要带:

代码语言:http
复制
Authorization: ApiKey <encoded-key>
Content-Type: application/json
kbn-xsrf: true

请求体非常简洁:

代码语言:json
复制
{
  "input": "Hi",
  "agent_id": "elastic-ai-agent",
  "connector_id": "Anthropic-Claude-Sonnet-4-5"
}

三个字段意思都很直白:

  • input:你这次想说什么,是个字符串。
  • agent_id:派给哪个 Agent。这就是上一篇里我们 discover 出来那 7 个 Agent 的 ID(elastic-ai-agentsre_agentaudit_agent 等)。
  • connector_id:底层用哪个 LLM,就是上一步 get_connectors 拿到的那个 id

返回结构信息量很丰富,我实际跑了一次 "input": "Hi" 的调用,返回大概长这样(截短):

代码语言:json
复制
{
  "conversation_id": "6a6a99f6-f35e-4e1f-9846-a5d9b3867bed",
  "round_id": "1e9c2ab4-dce1-4a5b-8a77-ba0627a461ed",
  "started_at": "2026-08-03T06:55:55.990Z",
  "time_to_last_token": 13215,
  "model_usage": {
    "connector_id": "Anthropic-Claude-Sonnet-4-5",
    "llm_calls": 3,
    "input_tokens": 38019,
    "output_tokens": 385,
    "model": "gp-llm-v2"
  },
  "steps": [
    {
      "type": "reasoning",
      "reasoning": "The user said 'Hi' which is a casual opener. Based on the skill instructions, I should load the elasticsearch-onboarding skill..."
    },
    {
      "type": "tool_call",
      "tool_id": "filestore.read",
      "params": { "path": "/skills/search/elasticsearch-onboarding/SKILL.md" },
      "results": [{ "tool_result_id": "J8oUH3", "data": { ... } }]
    }
  ],
  "response": {
    "message": "I'm set up to help you build search with Elasticsearch — from mapping your data to a working API. To get started, tell me what you're building. For example:\n\n- 'I want to use Elasticsearch as a vector database for my AI app'\n- 'I need product search with filters and autocomplete for an e-commerce site'\n..."
  }
}

几个字段读法:

  • conversation_id:本次会话的 ID。如果你下次带同样的 conversation_id 继续发,就能续上之前的对话——但 converse 的设计本意是单轮,多轮建议走 A2A。
  • round_id:本次回复的轮次 ID。
  • model_usage:LLM 调用的统计。llm_calls=3 说明 agent 内部调了三次 LLM(一次推理要不要加载 skill、一次根据 skill 决定行为、一次生成最终回复)。input_tokens=38019 看着吓人,是因为它把 onboarding skill 的全文都拼进了 prompt——这是 agent 加载 skill 的代价。
  • steps:完整的执行链路。type=reasoning 是模型在想,type=tool_call 是模型决定调一个内部工具(这里是读 skill 文件)。这些 steps 不需要你解析,但保留下来非常有价值——你可以用它做 token 优化(看哪步最费钱)、做调试(看 Agent 是不是在某步卡住了)、做审计(看 Agent 有没有跑偏)。
  • response.message:最终回给你的人话,直接拿去给用户看就行。

注意一个有意思的点:我这次测试里,time_to_last_token 是 13.2 秒,期间 Agent 做了 3 次 LLM 调用、读了一次 skill 文件。同步等就能拿到完整结果,不需要 A2A 那种异步轮询。这就是 converse 比 message/send 在"轻推理"场景下的核心优势:省去了异步任务管理这整层复杂度

但代价是它会阻塞 HTTP 连接 13 秒。如果 Agent 推理更重、要 30 秒以上,云端的入口代理可能就掐断了。所以 converse 适合"知道大概几十秒能跑完"的任务,不适合重型分析

三条路怎么选?一张判断图

到这里你已经有三条 delegate 任务到 Elastic 的路:A2A message/send、MCP tools、converse。怎么选?

我画一个判断流程:

代码语言:markdown
复制
你的任务...
│
├── 想要的是结构化数据(告警列表、ES|QL 结果、索引清单)吗?
│   ├── 是 → MCP tools(最快、最稳、最便宜)
│   └── 否 → 继续
│
├── 想要 Agent 用自然语言回答,并且这个任务几十秒内能跑完吗?
│   ├── 是 → converse(指定 connector_id)
│   └── 否 → 继续
│
└── 任务需要多步推理、跨 Agent 协同、或要保留多轮会话上下文?
    └── 是 → A2A message/send(异步 + 轮询 + 持久化上下文)

更具体的例子:

你想干啥

该用哪条

查现在有哪些活跃告警

MCP observability_get_alerts

跑一段 ESQL 拿聚合结果

MCP platform_core_execute_esql

让 Agent 用 ESQL 查一下再用人话解释

converse

让 Agent 排障一次告警(查指标 + 查日志 + 给根因)

A2A

跨 Agent 协同(审计 + SRE 一起分析)

A2A

让 Agent 帮你写一段查询、写一篇报告

converse 或 A2A 都行,看会不会跨轮

异步提交一个可能跑几分钟的任务

A2A(异步)

一句话总结三条路的差异:MCP 拿数据,converse 拿人话,A2A 拿协同。 一句话里能说清的就用 MCP;想要 Agent 解释但不复杂的就用 converse;要开团队会就上 A2A。

和上一篇的关系:不是替代,是补全

写到这里我想把这一篇和上一篇的关系说清楚。

上一篇我们讲 A2A 时强调的是"团队作战"——多个专业 Agent 在背后协同,把上下文攒在 Supervisor 这边,每个 Worker 守着自己干净的工作记忆。那套架构解决的是"复杂跨域任务"。

但上一篇没解决一个很现实的问题:不是所有任务都复杂到需要团队。很多时候你只是想问个简单问题、想要 Agent 帮你解读一段数据、或者想直接拿到结构化结果。这种场景下还走 A2A 那套"派活 → 异步等 → 凭 ID 取回",就跟用卡车送外卖一样笨重。

这一篇补的就是这一块。MCP 这条路让你能像调本地函数一样调 Elastic 上的 tool,几秒钟拿到结构化数据;converse 这条路让你能指定底层 LLM,几十秒拿到 Agent 推理完的人话。三条路一起,才把 WorkBuddy → Elastic 这条 delegate 通道真正补全:

  • 轻量、单步、要数据:MCP
  • 轻量、单轮、要人话:converse
  • 重型、多步、要协同:A2A

实际工作中,最舒服的状态是三条路都连着,按任务挑。WorkBuddy 作为协调者,最重要的能力不是会用某一条路,而是知道什么任务该走哪条。这个判断做对了,用户体感上"什么都顺手";做错了,简单任务也变得啰嗦。

回到那个凌晨两点(二)

上一篇结尾我说,checkout 告警响了你不用挨个系统翻,在 WorkBuddy 里说一句"帮我看看现在什么告警没消",A2A 协调层去叫 SRE 助手,结论递回来。

但现实里这个场景可能再轻一点。如果你只想看一眼"现在有哪些告警",根本不需要 Agent 推理,MCP 一调 observability_get_alerts,几百毫秒拿到结构化结果。如果你想让 Agent 帮你看看告警是不是严重、要不要紧、要怎么处理,converse 一句话丢过去,几十秒拿到人话回复。如果你要真正排查根因(看指标、看日志、看依赖拓扑),那再上 A2A 派给 SRE 助手。

三条路对应三个粒度,三种成本,三种延迟。真正成熟的 Agent 调用模式不是只用一条,而是按需切换。

多 Agent 协同真正有价值的样子,是上一篇讲的:一支分工明确、用同一套语言沟通的团队,WorkBuddy 做项目经理,Elastic 提供一房间各有所长的工位。

而真正成熟的 Agent 调用通道,是这一篇讲的:不光有一支团队,还有"打电话叫工具"(MCP)和"一句话让 Agent 出人话"(converse)两条短路径。前者解决协同,后者解决效率。中间的对讲机叫 A2A,短波叫 MCP,扩音器叫 converse。

不是所有事情都要开团队会。但当你需要开会的时候,也别用对讲机喊。这就是这一篇想说的。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 还是从那次 checkout 故障说起
  • MCP vs A2A:不是替代,是互补
  • 第一步:在 Elasticsearch 上拿到 MCP server 的地址
  • 第二步:在 WorkBuddy 里配置 Elastic MCP server,并拿到 tools
  • 第三步:用 platform.workflows.get_connectors 拿到 connector id
  • 第四步:用 POST kbn://api/agent_builder/converse 把任务 delegate 出去
  • 三条路怎么选?一张判断图
  • 和上一篇的关系:不是替代,是补全
  • 回到那个凌晨两点(二)
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档