使用 StreamAssist API 调用特定代理

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

概览

规范 详细信息
API 方法 projects.locations.collections.engines.assistants.streamAssist
端点版本 v1alpha 用于发现智能体 ID;v1 用于调用 streamAssist
关键参数 agentsSpec.agentSpecs[].agentId
支持的智能体类型 核心助理、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 编辑者 (roles/discoveryengine.editor) 或 Gemini Enterprise 管理员 (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。

在同一会话中继续对话

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

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 端点调用智能体。
  • 变异操作: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 错误结束 工作流具有手动触发器以及另一个触发器,或者具有多个手动触发器。 保留单个手动触发器。

后续步骤