使用 StreamAssist API 调用特定代理

如需调用特定注册代理,请在 streamAssist REST API 请求或客户端库调用中提供可选的 agentsSpec 字段。AgentsSpec API 定义了用于处理请求的代理的规范。助理会将查询直接路由到该智能体,并在多轮对话中保留会话上下文。

概览

规范 详细信息
API 方法 projects.locations.collections.engines.assistants.streamAssist
端点版本 v1alpha 用于发现智能体 ID;v1 用于调用 streamAssist
关键参数 agentsSpec.agentSpecs[].agentId
支持的代理类型 Core Assistant、Deep Research、Workflow Builder 对话智能体(以前称为低代码智能体)和 Workflow Builder 工作流(请参阅调用工作流)
所需的 IAM 权限 discoveryengine.assistants.assist
所需的 OAuth 范围 https://www.googleapis.com/auth/cloud-platform

准备工作

  1. 在 Google Cloud 项目中启用 Discovery Engine API (discoveryengine.googleapis.com)。
  2. 确保您的主账号(用户账号或服务账号)拥有授予 discoveryengine.assistants.assist IAM 权限的角色,例如 Discovery Engine Editor (roles/discoveryengine.editor) 或 Gemini Enterprise Admin (roles/discoveryengine.agentspaceAdmin)。
  3. 验证您的 Gemini Enterprise 应用(引擎)是否已创建,并且至少包含一个已注册的代理。
  4. 如果您使用应用默认凭据 (ADC) 进行身份验证,请确保您的客户端发送配额项目标头:-H "X-Goog-User-Project: PROJECT_ID"。

查找应用 ID 和位置

streamAssist 网址需要您的引擎 ID 及其位置(global、us 或 eu)。如果您只知道应用的显示名称,请列出项目中的引擎,以找到底层 ID:

curl -X GET \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
"https://LOCATION-discoveryengine.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/collections/default_collection/engines"

在响应中,引擎 name 格式为 projects/{project}/locations/{location}/collections/default_collection/engines/{ENGINE_ID}。ENGINE_ID 段是调用中所需的 APP_ID。

查找智能体 ID

agentId 是 Discovery Engine API 中代理的完整资源名称的最后一部分:

projects/{project}/locations/{location}/collections/{collection}/engines/{engine}/assistants/{assistant}/agents/{AGENT_ID}

已注册的代理使用长数字 ID(例如 15492003793394502655),而不是易记的显示名称。在请求中仅提供此最终 {AGENT_ID} 数字字符串。

如需列出已注册到应用的代理并发现其数字 ID,请在 v1alpha 端点上调用 agents 集合:

curl -X GET \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
"https://LOCATION-discoveryengine.googleapis.com/v1alpha/projects/PROJECT_ID/locations/LOCATION/collections/default_collection/engines/APP_ID/assistants/default_assistant/agents"

返回的每个代理资源都包含以下字段:

  • name:以 {AGENT_ID} 结尾的完整资源路径。
  • displayName: Google Cloud 控制台中显示的人类可读名称。
  • state:运行状态(例如 ENABLED 或 PRIVATE)。
  • 一个定义对象,用于指示代理类型(例如 a2aAgentDefinition、lowCodeAgentDefinition 或 workflowAgentDefinition)。

如需查看完整的代理资源架构,请参阅 agents REST API 参考文档。

向代理发送查询

如需向特定智能体发送查询,您必须使用适当的 agentsSpec 构建请求,并使用 REST 或客户端库执行该请求。

请求正文结构

如需将查询路由到特定智能体,请在 POST 请求正文中添加可选的 agentsSpec 对象:

{
  "query": {
    "text": "QUERY_TEXT"
  },
  "session": "SESSION_RESOURCE_NAME",
  "agentsSpec": {
    "agentSpecs": [
      {
        "agentId": "AGENT_ID"
      }
    ]
  }
}

字段参考

  • agentsSpec (对象,可选):用于处理请求的代理的规范。
  • agentsSpec.agentSpecs[] (数组,可选):代理规范列表。您可以在此数组中指定多个代理。
  • agentsSpec.agentSpecs[].agentId (字符串,规范中必需):用于标识已注册智能体资源的 ID。必须符合 RFC-1034 标准,且长度上限为 63 个字符。

如需查看完整的请求架构,请参阅 streamAssist REST API 参考文档。

调用 streamAssist

REST

以下 curl 命令使用 REST API 向特定代理发送查询:

curl -X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
"https://LOCATION-discoveryengine.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/collections/default_collection/engines/APP_ID/assistants/default_assistant:streamAssist" \
  -d '{
    "query": {
      "text": "List all contact cards."
    },
    "agentsSpec": {
      "agentSpecs": [
        {
          "agentId": "AGENT_ID"
        }
      ]
    }
  }'
    

替换以下占位符:

  • LOCATION:主机名和资源路径的多区域(global、us 或 eu)。如果您的应用位于 global 位置,请省略主机名中的位置前缀 (discoveryengine.googleapis.com)。
  • PROJECT_ID:您的 Google Cloud 项目 ID。
  • APP_ID:您的 Gemini Enterprise 引擎 ID(在查找应用 ID 和位置中发现)。
  • AGENT_ID:数字代理 ID(在查找代理 ID 中发现)。

Python

此 Python 示例使用 google-cloud-discoveryengine 客户端库调用 streamAssist:

# Install library: pip install google-cloud-discoveryengine
from google.api_core.client_options import ClientOptions
from google.cloud import discoveryengine_v1 as discoveryengine

# TODO(developer): Replace placeholder values with your project and agent details.
project_id = "PROJECT_ID"
location = "LOCATION"          # For example: "us", "eu", or "global"
engine_id = "APP_ID"
agent_id = "AGENT_ID"          # The numeric agent ID
query_text = "List all contact cards."

client_options = (
    ClientOptions(api_endpoint=f"{location}-discoveryengine.googleapis.com")
    if location != "global"
    else None
)
client = discoveryengine.AssistantServiceClient(client_options=client_options)

assistant_path = client.assistant_path(
    project=project_id,
    location=location,
    collection="default_collection",
    engine=engine_id,
    assistant="default_assistant",
)

request = discoveryengine.StreamAssistRequest(
    name=assistant_path,
    query=discoveryengine.Query(text=query_text),
    agents_spec=discoveryengine.StreamAssistRequest.AgentsSpec(
        agent_specs=[
            discoveryengine.StreamAssistRequest.AgentsSpec.AgentSpec(
                agent_id=agent_id,
            )
        ]
    ),
)

for response in client.stream_assist(request=request):
    for reply in response.answer.replies:
        # Filter out model reasoning fragments (thought: true)
        if hasattr(reply, "grounded_content") and reply.grounded_content.content:
            print(reply.grounded_content.content.text, end="", flush=True)

print()
    

了解流式响应

streamAssist 端点会通过 REST 返回 JSON 分块流,或在客户端库中返回响应对象的迭代器:

  • 回答文本:增量回答文本会到达 answer.replies[].groundedContent.content.text。按接收顺序串联这些文本片段,即可重构完整回答。
  • 推理片段:标有 "thought": true 的片段表示模型的内部推理过程。在向最终用户呈现最终输出时,请滤除这些片段。
  • 执行状态:answer.state 字段从 IN_PROGRESS 变为最终状态:
    • SUCCEEDED:请求已完成并生成了回答。
    • SKIPPED:查询被忽略或绕过。检查 assistSkippedReasons 以了解详情(例如,NON_ASSIST_SEEKING_QUERY_IGNORED 表示简短问候语)。
    • FAILED:调用遇到执行错误。
  • 会话连续性:终端分块包含 sessionInfo.session(会话资源名称)和 assistToken。

在同一会话中继续对话

为了在多轮对话中保持上下文,请在后续请求中传递 sessionInfo 中的 session 字符串:

curl -X POST \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
-H "Content-Type: application/json" \
"https://LOCATION-discoveryengine.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/collections/default_collection/engines/APP_ID/assistants/default_assistant:streamAssist" \
  -d '{
    "session": "projects/PROJECT_ID/locations/LOCATION/collections/default_collection/engines/APP_ID/sessions/SESSION_ID",
    "query": {
      "text": "Who is John Doe?"
    },
    "agentsSpec": {
      "agentSpecs": [
        {
          "agentId": "AGENT_ID"
        }
      ]
    }
  }'

如果您省略 session 字段或指定 - 作为会话 ID,API 会自动生成一个新的隔离会话。

调用工作流

如需运行 Workflow Builder 工作流,请发送相同的请求,并在 agentsSpec.agentSpecs[].agentId 中添加工作流的 ID。每次调用都会启动工作流的手动运行。

  • 运行的版本:如果工作流已发布,则调用会运行其已发布版本。在 Workflow Builder 中保存但尚未发布的更改不会影响 API 调用方,直到您发布这些更改。如果工作流从未发布过,则该调用会运行其草稿。
  • 谁可以调用它:工作流的所有者和管理员可以调用它。其他用户在获得已发布工作流的共享权限后,可以调用该工作流。只有所有者或管理员才能调用从未发布过的工作流;其他调用方会收到 HTTP 403。
  • 触发器:工作流必须只有一个手动触发器。如果工作流将手动触发器与任何其他触发器组合在一起,或者具有多个手动触发器,则调用会失败。
  • 输入:您无法通过 streamAssist 设置手动触发器的输入变量。如果手动触发器有必需输入,则即使输入有默认值,运行也会失败。可选输入为空,并且不会应用其默认值。查询文本会传递到工作流的 LLM 节点,因此您可以在其中添加数据,但它不会填充输入变量。

限制

使用 streamAssist 调用智能体时,存在以下限制:

  • 不支持的代理类型:streamAssist 不支持向 Gemini Enterprise 应用注册的 A2A 或 ADK 代理。如需使用 A2A 智能体的注册表端点直接调用该智能体,请参阅使用 A2A 智能体的注册表 A2A 端点调用该智能体。
  • 变更操作:streamAssist API 针对对话式查询和通过连接器进行的只读检索进行了优化。streamAssist 不支持以编程方式执行会产生变化的工具和操作(例如起草电子邮件、创建日历活动或发送聊天消息)。尝试调用执行变更操作的 Agentic Workflows 可能会导致静默失败或无依据的执行循环。

问题排查

请使用下表排查常见的 streamAssist 调用错误:

症状 可能的原因 解决方法
列出智能体时出现 HTTP 404 错误 在 v1 或 v1beta 端点上调用 agents。 改为向 v1alpha 端点发送列表请求。
尽管设置了 agentsSpec,但回答看起来仍很空泛 数字 agentId 无效,或者查询过于宽泛,无法触发网域行为。 从 v1alpha 代理列表中确认确切的数字 ID;发送特定领域的查询;检查回答文本中是否包含代理特有的措辞。
未返回错误,但目标智能体未执行 agentId 格式不正确,导致静默回退到默认编排。 验证 agentId 是否仅由数字组成,并且与注册表列表中的 ID 完全一致。
响应状态返回 SKIPPED 输入内容被评估为非寻求帮助的查询(例如简短的问候语)。 发送实质性任务查询;检查响应载荷中的 assistSkippedReasons。
HTTP 401 或 HTTP 403 Permission Denied 缺少 OAuth 范围、IAM 角色权限不足或缺少配额项目标头。 验证调用方是否具有 discoveryengine.assistants.assist;确保 OAuth 范围包含 cloud-platform;如果使用 ADC,请添加 -H "X-Goog-User-Project: PROJECT_ID"。
HTTP 403 - Only the agent owner or an admin can run a draft of this agent. 工作流从未发布过,且调用方不是其所有者或管理员。 在 Workflow Builder 中发布工作流,并与来电者共享。
HTTP 403 - User does not have permission to access the Agent. 工作流未与调用方共享。 与调用方共享工作流。
工作流的行为类似于旧版本 该调用会运行已发布的版本,而不是 Workflow Builder 中未发布的更改。 发布工作流。
工作流调用以 answer.state FAILED 和 INTERNAL 错误结束 工作流有一个手动触发器和另一个触发器,或多个手动触发器。 保留一个手动触发器。

后续步骤