mcpField
A
add-context-gateway

add-context-gateway

github.com/redisAgent 工作流17411 次安装今天更新
代码仓库

关于 add-context-gateway

指导将 Agent 的 MCP 连接转由 Redis Context Gateway 路由,并配置上游服务和统一端点。自托管部署还可按需启用工具搜索、缓存及大型结果句柄。

主要功能

  1. 01盘点 MCP 服务及凭据
  2. 02配置 HTTP 上游服务
  3. 03完整暴露工具或通过搜索调用
  4. 04为只读工具设置缓存策略
  5. 05将大型结果作为句柄返回
  6. 06创建并检查 Gateway

适用场景

  1. 01用一个端点替代多个 Agent MCP 连接
  2. 02减少 Agent 可见的工具模式数量
  3. 03缓存可重复的只读查询
  4. 04处理大型导出、列表或日志

MCP 相关

该技能将 Gateway 配置为上游 HTTP MCP 服务的统一 MCP 端点。框架客户端可连接其 URL 并使用密钥;没有 MCP 客户端的 Agent 可通过 SDK 的模型工具或 hooks 接入。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/redis/agent-skills --skill add-context-gateway

安装后在 Claude Code 中输入/add-context-gateway确认已加载。

详细介绍

添加 Context Gateway

使用一个 MCP 端点和一个 Agent 密钥,替代 Agent 当前配置的所有 MCP 服务。Gateway 会保存每个上游的密钥,为工具名称添加命名空间以避免冲突;可以将大型目录以 search_tools 和 run_tool 的形式公开,而不是提供每个工具的架构;可以缓存你选择启用缓存的只读工具;还能将大型结果作为句柄返回。Agent 保留原有工具;改变的只有工具的访问入口。先询问,再配置,最后更换指向。

1. 调查

阅读项目:

  • 找出 Agent 配置的所有 MCP 服务:.mcp.json、.cursor/mcp.json、McpToolset、MCPServerStreamableHttp、MultiServerMCPClient、stdio_client,或手写的 MCP 客户端。记录每个端点及其密钥的来源。
  • 找出工具交给模型的位置,以及运行每轮对话的位置。
  • 根据导入内容识别框架,并确认它是否有自己的 MCP 客户端。
  • 记录仅支持 stdio 的服务:上游是一个 HTTP MCP 端点(streamable-http)。stdio 服务必须先通过 HTTP 提供服务,否则就留在 Gateway 之外。

首先询问 Gateway 的运行位置:

  • Redis Cloud(控制台)。 开发者在控制台中创建 Gateway 和上游,CLI 只与 Gateway 的 MCP 端点通信(第 3 步“在 Redis Cloud 中”)。Cloud 会关闭 Gateway 的缓存和压缩,因此跳过问题 3 和 4。
  • 自行管理(本地部署,或本地 Compose 堆栈)。CLI 配置所有内容(第 3 步)。

然后只问开发者以下五个问题,不要多问。对方若不确定,则采用默认值。

询问如果答案是配置
Agent 使用哪些 MCP 服务,它们的密钥存放在哪里?一组 HTTP 端点每个端点添加一个上游:upstream add --name NAME --endpoint URL,并使用 --bearer-secret env:VAR 或 --header NAME --header-secret env:VAR
Agent 要查询的 Redis 数据库Context Surface 上游:--kind context-surface --surface-database-id ID --data-model FILE(自行管理时,可以省略 ID,默认使用部署配置中的 ID。在 Redis Cloud 中,控制台的 Create Context Surface 会询问数据库)。先编写数据模型:参见“编写数据模型”
Agent 总共会看到多少个工具?几十个(默认)--tool-exposure-mode full:提供所有工具,并为名称添加命名空间
数百个,或工具架构让提示词过于拥挤--tool-exposure-mode search:模型会看到 search_tools 和 run_tool
哪些只读工具在参数相同时会返回相同结果?查询、搜索、参考数据使用启用 cache 的数据库创建 Gateway(参见“Gateway 开关和数据库”),然后针对每个工具设置 policy set UPSTREAM TOOL --cache-ttl DURATION
没有,或不确定不设置缓存策略
哪些工具返回的结果太大,无法一次性完整读取?导出、列表端点、日志使用 noeviction 数据库并启用 compression 创建 Gateway(参见“Gateway 开关和数据库”)。然后使用部署的句柄默认设置,或针对每个工具设置 --compression-ttl DURATION;对于必须始终返回完整结果的工具,使用 --compression-capture never
框架会自行连接 MCP 服务吗?会:Claude Code、Cursor、ADK、OpenAI Agents SDK、LangChain MCP adapters将其 MCP 客户端指向 Gateway URL 和密钥
不会,或 Agent 需要普通函数工具使用 SDK:gateway.model_tools() 或 gateway.hooks()

2. 从 MCP 获取当前信息

编写代码前先执行此操作。切勿凭记忆猜测框架 API。

  • 框架文档:查询可用的文档 MCP(Context7,或框架自带的文档 MCP),了解已安装版本的 MCP 客户端如何接收 streamable HTTP URL 和 Authorization 请求头。
  • Redis 文档:如果已连接 Redis 文档 MCP,请使用它了解 Context Gateway 概念(上游、暴露模式、缓存、句柄)。
  • 没有可用的 MCP:阅读虚拟环境中已安装的软件包源码,并在报告中说明。

3. 配置

安装 CLI
pip install redis-iris

需要 Python 3.11 或更高版本。在 LangGraph 上,请安装 redis-iris[langgraph]。如果在搜索模式的 Gateway 上设置了 Gateway ID(--gateway-id 或 IRIS_CONTEXT_GATEWAY_ID),但运行 tools call crm__lookup_customer 时因 tool_not_found 失败,这是因为已安装的版本会在第一个 . 处分割工具名称:请升级 redis-iris,或在设置 IRIS_CONTEXT_GATEWAY_URL 且不设置 Gateway ID 的情况下运行 tools call,这样 CLI 就会通过 search_tools 解析名称。

在 Redis Cloud 中

Redis Cloud 目前还没有用于设置 Gateway 的 API。控制平面只接受控制台会话,因此 cloud 配置文件会对 service、upstream 和 policy 命令返回 cloud_unsupported,Agent 也无法进行配置。开发者需在控制台中操作:

  1. Iris → Context Gateway:创建 Gateway,或打开现有 Gateway。
  2. 在 Gateway 中,进入 Upstreams:为问题 1 中的每个 HTTP 服务选择 Add MCP server,或为 Redis 数据库选择 Create Context Surface(先编写数据模型:参见“编写数据模型”)。
  3. 在连接步骤中,复制 MCP 端点并创建 Agent 密钥。
  4. 将它们设置为 Agent 环境或其 .env 中的 IRIS_CONTEXT_GATEWAY_URL 和 IRIS_CONTEXT_GATEWAY_API_KEY。这些值由开发者设置,绝不能由 Agent 设置:不要在聊天中索要密钥,也绝不要回显、运行 cat 或 grep 查看环境文件。

在 .env.example 中添加这两个名称,并将值留空;绝不要提交 .env。然后跳过本步骤的其余内容,转到步骤 4。Cloud 会关闭缓存和压缩,因此无需设置策略或句柄。

自行管理

请让用户导出 IRIS_CONTEXT_GATEWAY_SERVICE_URL、IRIS_CONTEXT_GATEWAY_SERVICE_TOKEN、IRIS_IDENTITY_URL 和 IRIS_IDENTITY_TOKEN。对于本地 Compose 堆栈,在命令后添加 --local(service list --local)会提供服务 URL 和令牌,但不会提供 Identity URL,因此 create 仍需要 IRIS_IDENTITY_URL。

Identity 令牌。 每个产品的 chart 都可以运行自己的 Identity Service。此时请设置该产品自己的 IRIS_CONTEXT_GATEWAY_IDENTITY_TOKEN(以及 IRIS_CONTEXT_GATEWAY_IDENTITY_URL,或配置文件中的 identity_url),并取消设置 IRIS_IDENTITY_URL:它会覆盖配置文件中每个产品的 identity_url。在共享一个 Identity Service 的套件中,IRIS_IDENTITY_TOKEN 和 IRIS_IDENTITY_URL 适用于所有产品。CLI 按以下顺序获取令牌:--identity-token、IRIS_CONTEXT_GATEWAY_IDENTITY_TOKEN、IRIS_IDENTITY_TOKEN,最后是该产品的服务令牌;只有两个令牌是同一个密钥时,最后一种方式才有效。

iris --json --no-input context-gateway service list
iris --json --no-input context-gateway service create --name support --tool-exposure-mode full --write-env .env
set -a; . ./.env; set +a; iris --json --no-input context-gateway service check <gatewayId from the result>

Gateway CLI 只会从环境变量中读取 IRIS_CONTEXT_GATEWAY_API_KEY,绝不会从 .env 中读取,因此在密钥位于命令的环境中之前,service check、tools 和 handle 都会因 configuration_error 失败。请像上面那样在同一条 Shell 命令中加载该文件(或使用 uv run --env-file .env iris ...),这样密钥就不会出现在输出中。

Gateway 开关和数据库

每个 Gateway 都有两个开关:cache 和 compression,它们的状态分别为 ENABLED 或 DISABLED。service show gw_0123456789abcdef0123456789abcdef 会显示这两个开关。若 Gateway 的 cache 为 DISABLED,则 --cache-ttl 策略会被拒绝并返回 400,因此请先启用 cache。当 compression 关闭时,压缩策略虽会保存,但不会生效。这两项功能还需要由运维人员启用部署开关(数据平面配置中的 cache.enabled 和 compression.enabled,默认关闭)。

创建方式cache 和 compression
使用数据库:--database-id ID,或使用本地部署的默认值 defaultDatabases.gatewayDb两者均为 ENABLED
不使用数据库两者均为 DISABLED。不指定数据库却发送 ENABLED,该字段会返回 400
使用无法进行压缩的数据库(见下文,或数据库不可访问),且省略 compressioncache 为 ENABLED,compression 保存为 DISABLED
功能生效条件
------
缓存Gateway 的 cache 为 ENABLED,工具可缓存(未标记 readOnlyHint: false 或 destructiveHint: true;未提供提示的工具也视为可缓存,因此只为确定为只读的工具启用),且设置了 --cache-ttl 策略
压缩Gateway 的 compression 为 ENABLED,且工具的策略不是 --compression-capture never

service create 和 service update 均接受 --cache enabled|disabled 和 --compression enabled|disabled,并会发送大写 API 值。省略标志会保留服务端默认值或现有值。之后添加数据库不会启用任何一项功能,因此请显式启用:

iris --json --no-input context-gateway service update gw_0123456789abcdef0123456789abcdef --database-id gateway-db --cache enabled --compression enabled

要分离数据库,请在一次更新中传入 --clear-database --cache disabled --compression disabled。过期的 --expected-revision 会返回 412 revision_conflict。请先重新读取资源,再决定是否重试。

数据库要求:

  • 压缩需要一个 maxmemory-policy noeviction 且已加载 JSON 模块的 Gateway 数据库。在其他策略下启用压缩(创建、更新,或压缩保持启用时更改 databaseId)会返回 400,且 errors[] 中会有一项指向 /compression,原因类似 database lru-db uses allkeys-lru, compression needs noeviction。发送 compression enabled 时,如果数据库无法访问,会返回 503:请重试。在不适用或无法访问的数据库上创建服务时,若省略 compression,请求不会被拒绝:系统会将 compression 设为 DISABLED,请使用 service show 读取确认。
  • 仅缓存适用于任何 Gateway 数据库。句柄和缓存条目共用该数据库,因此请为其预留足够的 maxmemory。对于采用驱逐策略的仅缓存数据库,Redis 会驱逐条目,且下方的共享内存限制不适用。
  • 句柄和缓存各自拥有独立的 maxmemory 份额。 句柄使用量上限为 compression.max_memory_share(默认值为 0.5),缓存使用量上限为 cache.max_memory_share(默认值为 0.4),两者合计最多为 0.95,因此不会占用对方的空间。两者还会在使用量超过 maxmemory 的 90% 时停止增长,但这只是对份额限制未能覆盖情况的兜底。
  • 句柄份额已满时,自动捕获会完整返回结果,而显式调用 run_tool_as_handle 会返回工具错误:handle storage is full, release handles or narrow the query。缓存份额已满时,只会跳过写入并返回结果。释放句柄会立即释放其份额,过期句柄则会在约 10 秒内释放份额。
  • 请根据 TTL 为 Gateway 数据库配置容量。 句柄和缓存条目会一直保留到 TTL 到期(句柄默认保留 15 分钟),因此每个份额都需要足够的空间来容纳 每秒创建数 x TTL x 存储大小。不要根据结果大小估算存储大小。请实际测量:service diagnose --metrics-url 会显示缓存和压缩计数器;skipped_low_memory 或 out_of_memory 结果不断增加,意味着对应份额已满。如果空间不足,请降低 --compression-ttl 或 --cache-ttl,或者提高 maxmemory 或运维人员设置的份额。
  • 本地部署时,数据库来自部署配置,绝不会来自 CLI:shared.config.databases 注册各个 ID,databaseConnections 提供 URL,defaultDatabases.gatewayDb 和 defaultDatabases.surfaceDb 指定默认值。若找不到某个 ID,请联系运维人员。启用压缩时,Gateway 数据库和 Surface 数据库应使用不同的 Redis 实例:否则 noeviction 也会应用于客户数据。

service diagnose gw_0123456789abcdef0123456789abcdef 会报告 Gateway 的数据库(no Gateway database 表示每次调用都会绕过缓存)、每个 Upstream 的目录以及缓存策略。添加 --metrics-url 可查看缓存和压缩计数器;eviction_policy、skipped_low_memory 或 out_of_memory 结果不断增加,意味着句柄无法被保留。

将 CLI 用作 Agent
  1. 始终将 --json --no-input 放在产品名称之前。标准输出会返回一个 JSON 值,标准错误会返回一个 JSON 值作为错误,并且不会显示提示。
  2. 先读取,再写入。service create 没有 --dry-run,因此先运行 service list:它能验证服务 URL 和令牌;如果那里出现 configuration_error、unauthenticated 或 forbidden,则在创建任何内容之前交由他人处理(步骤 4)。
  3. 始终使用 --write-env PATH(或在 service key 中使用 --write PATH)交付密钥。绝不要在没有文件的情况下使用 --json 运行 create 或 key:这会将密钥打印到对话记录中。
  4. 遇到 configuration_error、unauthenticated 或 forbidden 时,停止操作。告知对方需要设置哪个变量(见错误消息或 details.env),并在存在 details.obtain 时附上链接。绝不要在聊天中索要机密、在命令行中传递机密,也不要回显、使用 cat 或 grep 查看环境变量文件。
  5. 上游机密只能通过引用传入:env:NAME、file:PATH 或 -。请对方导出变量;绝不要自行写入机密。
  6. 遇到 resource_exists 时,询问对方是使用 --reuse 复用 details.gatewayId,还是选择其他名称。绝不要为了重试而删除资源。如果 create 失败且 details.created: true,则使用 --reuse --write-env 重新运行。

每个错误都会以一个 JSON 值的形式输出到标准错误,并包含 error.code;凭据错误还会包含 details.env 和 details.obtain,但绝不会包含凭据值。出现第一个故障时立即停止并转达:

error.code由谁处理操作
credential_required对方在 Agent 的 shell 中设置 details.env 指定的变量。请参阅上文“身份令牌”。
unauthenticated对方details.source 中的令牌被拒绝:令牌已过期或属于其他部署。请签发新令牌。
forbidden对方令牌有效,但缺少所需角色或租户。请为该产品使用具有正确角色的令牌。
configuration_error对方或 Agent缺少 URL,例如 url。请将其添加到配置文件。
invalid_requestAgentHTTP 400。请修正错误消息中指出的请求。
resource_exists对方决定是使用 --reuse 重新运行以接管 details.gatewayId,还是选择其他名称。
unavailable对方无法访问该跳点。请检查 URL、入口和服务的 Pod。
check_failed对方details.hop 和 details.cause 会指出故障跳点。请修复并重新运行检查。
cloud_unsupported对方配置文件的 kind = "cloud"。请按照控制台中的 details.steps 操作。
input_error, usage_errorAgent修正命令。在 --no-input 下执行破坏性命令,需要对方提供 --yes。

--write-env .env 会写入 IRIS_CONTEXT_GATEWAY_URL(Gateway 的 MCP 端点)、IRIS_CONTEXT_GATEWAY_ID 和 IRIS_CONTEXT_GATEWAY_API_KEY。请将同样的三个名称以空值添加到 .env.example。绝不要提交 .env。

添加上游(问题 1)。IRIS_CONTEXT_GATEWAY_ID 不是机密;请使用 --gateway-id 传入 create 输出的 gatewayId(gw_ 加 32 个十六进制字符):

iris --json --no-input context-gateway --gateway-id gw_0123456789abcdef0123456789abcdef upstream add --name CRM --endpoint https://crm.example.com/mcp --bearer-secret env:CRM_TOKEN
iris --json --no-input context-gateway --gateway-id gw_0123456789abcdef0123456789abcdef upstream add --name Tickets --endpoint https://tickets.example.com/mcp --header X-Api-Key --header-secret env:TICKETS_KEY
iris --json --no-input context-gateway --gateway-id gw_0123456789abcdef0123456789abcdef upstream tools crm

upstream add 即使输出 initialCatalogFailure,也仍然创建了上游:422 表示上游拒绝了凭据(使用 upstream update 修复,然后运行 upstream refresh);424 表示发现失败(请检查控制平面是否能够访问端点);408 表示超时。对于 --kind context-surface 上游,422 表示 Surface 数据库拒绝了控制平面的登录,424 表示工具生成失败(例如 Redis 返回 NOPERM):这两种情况都需要在部署配置中修复,然后运行 upstream refresh。

编写数据模型

Context Surface 上游需要一个数据模型:用于说明 Agent 可以读取哪些记录以及如何建立索引的 JSON。Gateway 会根据它生成工具,因此请在执行 upstream add --kind context-surface 之前编写好。

级别成员
模型title、description、entities[]
实体name、description、redis_key_template(例如 order:{id},默认值为 <Name>:{id})、relationships[]、fields[]、可选的 document_type
字段name、type、description、is_key_component、redis_indices[];标签可选 allowed_values
关系name、target(一个实体)、description、source_field(此实体的一个字段)

规则:

  • 键模板中的每个 {placeholder} 都必须是 is_key_component: true 的字段。键字段不建立索引。第一个占位符之前的文本(order:)必须以 :、_、-、/ 或 . 结尾:这是索引前缀。
  • 字段 type 可以是 str、int、float、bool、list[str]、list[float]、geo、timestamp 或 object。object 不能建立索引。
  • 默认情况下,记录以 RedisJSON 格式存储。"document_type": "hash" 会将实体存储为 Hash:不能包含 object 字段,list[float] 仅可与向量索引搭配使用,键字段必须是标量。
  • Gateway 遇到 acl_field_mappings 会返回 400,因此请将其省略:每个有权访问 Gateway 的 Agent 密钥都能读取 Surface 的所有记录。iris 仓库中的示例文件包含此字段,请勿复制该文件。

根据 Agent 的查询方式选择索引:

索引字段类型用途生成的工具
tagstr、bool、list[str]精确筛选:状态、ID、类别。allowed_values 列出合法值filter_<entity>
textstr对名称、描述、备注进行全文检索。weight 用于字段排序,no_stem 用于关闭词干提取search_<entity>_by_text
numericint、float、timestamp范围查询和排序。除非设置 sortable: false,否则字段可排序;list_ 需要可排序字段,且 timestamp 不能设置为 sortable: falsefilter_<entity>、list_<entity>、summarize_<entity>
vectorlist[float]基于语义的搜索。需要 vector_dim 和 distance_metric(cosine、euclidean、dot_product),并且数据平面上需有嵌入服务。Redis Cloud 目前无法嵌入查询,因此这些工具目前在该平台上会失败当 source_field 指定要嵌入的文本字段时,生成 search_<entity>_by_<field>_semantic;否则生成 _similarity。如果该文本字段有 text 索引,且 Surface Redis 支持通过 RESP3 进行原生混合搜索,也会生成 search_<entity>_by_<field>_hybrid(同时对文本和向量进行排序)
geogeo查找指定半径内的记录find_<entity>_near_<field>

键模板只有一个占位符的实体还会生成 get_<entity>_by_id;count_<entity> 用于统计记录数。跨实体的集合工具 intersect_results、union_results、except_results 和 expand_results 可组合筛选结果并沿关系展开。每个工具均为只读,并以 <namespace>__<tool> 的形式显示,例如 orders__search_order_by_text。只有模型包含工具所需字段时,该工具才会生成:没有 text 索引,就不会有文本搜索工具。

最简订单模型:

{
  "title": "Orders",
  "description": "Customer orders",
  "entities": [
    {
      "name": "Order",
      "description": "A customer order",
      "redis_key_template": "order:{id}",
      "relationships": [],
      "fields": [
        {"name": "id", "type": "str", "description": "Order ID", "is_key_component": true, "redis_indices": []},
        {"name": "status", "type": "str", "description": "open, shipped or cancelled", "redis_indices": [{"type": "tag"}]},
        {"name": "notes", "type": "str", "description": "Free-text order notes", "redis_indices": [{"type": "text", "weight": 1.0}]},
        {"name": "total", "type": "float", "description": "Order total in dollars", "redis_indices": [{"type": "numeric", "sortable": true}]}
      ]
    }
  ]
}

将其保存为 orders.json,并使用 --surface-database-id ID --data-model orders.json 添加。记录以 JSON 文档形式存储在 order:<id>,字段名称与模型中的名称相同。执行 upstream add 后,运行 upstream tools orders 查看生成的工具。在 Redis 为现有键完成索引之前,搜索结果可能不完整(FT.INFO <index> 中的 percent_indexed 达到 1 即表示完成)。更改数据模型(upstream update)会重新建立索引,因此请在数据库有足够空间时操作。

设置策略(问题 3 和 4)。upstream tools 会指出哪些工具可以缓存;只有这些工具支持 --cache-ttl:

iris --json --no-input context-gateway --gateway-id gw_0123456789abcdef0123456789abcdef policy set crm search_customers --cache-ttl 5m
iris --json --no-input context-gateway --gateway-id gw_0123456789abcdef0123456789abcdef policy set crm export_orders --compression-ttl 1h
轮换密钥和机密
  • 新建 Agent 密钥:运行 service key gw_0123456789abcdef0123456789abcdef --write .env,即可生成密钥并将其写入文件。重启 Agent,使其读取新值。
  • 同一 Gateway 上的另一位开发者:运行 service env gw_0123456789abcdef0123456789abcdef --write .env,即可写入 URL 和 ID,而不会生成密钥;然后运行 service key 为其生成专属密钥。
  • 新建 Upstream 机密:让对方导出新值,然后运行 upstream update crm --bearer-secret env:CRM_TOKEN(或 --header-secret),再运行 upstream refresh crm。

完整参考:iris context-gateway <command> --help(例如 iris context-gateway upstream add --help)。

4. 重新配置 Agent

MCP 原生框架(问题 5,回答是)。将每个服务端条目替换为一个 Gateway 条目。connect 会写入从变量中读取的密钥,且不会打印密钥。在 Redis Cloud 中,使用 cloud 配置运行 connect,并且不指定 --gateway-id:它会从 IRIS_CONTEXT_GATEWAY_URL 获取端点。

iris context-gateway --gateway-id gw_0123456789abcdef0123456789abcdef connect --client claude-code --write .mcp.json
iris context-gateway --gateway-id gw_0123456789abcdef0123456789abcdef connect --client cursor --write .cursor/mcp.json
iris context-gateway --gateway-id gw_0123456789abcdef0123456789abcdef connect --client adk > gateway_tools.py
iris context-gateway --gateway-id gw_0123456789abcdef0123456789abcdef connect --client json

对于其他 MCP 客户端(OpenAI Agents SDK、LangChain MCP 适配器),使用 json 输出:其中包含 URL、streamable-http,以及值为 IRIS_CONTEXT_GATEWAY_API_KEY 的 Authorization: Bearer 标头。请在步骤 2 中确认客户端的参数名称。.env 文件不会传递给正在运行的客户端:该变量必须存在于启动客户端时使用的环境中。

SDK 工具(问题 5,回答否):

from redis_iris import ContextGateway

gateway = ContextGateway.from_env()
tools = gateway.model_tools()  # framework-free Tool objects, one per Gateway tool

TypeScript Agent:请参阅 @redis-iris/context-gateway API。

在 LangGraph 中,redis_iris.integrations.langgraph 提供的 langchain_tools(gateway.hooks()) 可为 ToolNode 创建 LangChain 工具。如果还接入了 Agent Memory 或 Agent Playbooks,可将它们叠加起来,让模型从一个位置获取每个产品的所有工具:

from redis_iris.hooks import stack
from redis_iris.integrations.langgraph import attach, langchain_tools

hooks = stack(memory.hooks(), playbook.disclosure(), gateway.hooks())
graph.add_node("tools", ToolNode(langchain_tools(hooks)))
app = attach(hooks, graph).compile()

gateway.call("crm__lookup_customer", id="cust-1042") 可直接调用工具(result.data、result.is_error);gateway.call_as_handle(...) 则会将大型结果作为 Handle 保存在 Gateway 上。读取操作由 Gateway 处理:gateway.page(handle, limit=5)、gateway.query(handle, ...)、count、aggregate、describe 和 gateway.release(handle)。异步版本包括 atools、acall、apage 等。

然后,移除由 Gateway 替代的内容:每个服务端对应的 MCP 条目、每个服务端对应的机密(现在由 Gateway 保存),以及任何手写的命名空间或工具筛选逻辑。

工具名称会改为 namespace__tool,例如 crm__lookup_customer。请更新任何提及工具名称的提示词文本或代码。

在搜索模式下,模型不会在 tools/list 中看到这些名称。它会使用 query(以及可选的 limit,默认值为 5)调用 search_tools,获取完整的 MCP 工具定义,然后通过 run_tool 运行其中一个工具:tool 包含匹配项中的 upstreamId 和 originalName,toolArgs 则包含参数。提示词文本应描述工具执行的任务,而不是写出工具名称。通过 SDK 和 CLI 按名称调用工具的代码仍可正常工作,因为它们会为你解析 namespace__tool。

Agent 端的句柄

启用 Gateway compression 后,两种暴露模式下的 tools/list 都会新增七个工具:run_tool_as_handle、describe_result、count_results、page_results、query_results、aggregate_results 和 release_results。如果工具结果超过 32 KiB,返回的将是一个小型存根,其中包含一个句柄(h_ 加 32 个十六进制数字)、预览内容和后续步骤,而非完整载荷。在完整模式下,声明了 outputSchema 的工具会返回完整结果。使用 --compression-capture never 的工具会返回完整结果,对它调用 run_tool_as_handle 则会产生工具错误,提示 Agent 直接调用该工具。请在提示词中告知 Agent 使用下方工具读取句柄,且不要再次请求完整载荷。

Agent 想要调用
无论大小,保留较大结果以供后续多次调用run_tool_as_handle(完整模式使用 name 和 toolArgs;搜索模式使用 tool、upstreamId、originalName 和 toolArgs)
了解句柄的形状、大小、字段和过期时间describe_result
统计项目总数,或按某个字段的值分组统计使用 jsonpath 或 groupBy 调用 count_results
计算数字的总和、最小值、最大值或平均值使用 jsonpath 调用 aggregate_results
只读取符合条件的项目使用 JSONPath(如 $[[email protected]=="open"])调用 query_results,并分页读取
按顺序读取项目,或按字节读取文本结果使用 offset 和 limit 调用 page_results
提前释放内存release_results

当 run_tool_as_handle 返回 handle storage is full, release handles or narrow the query 时,Agent 应对不再需要的句柄调用 release_results,然后使用范围更窄的查询重试,或直接调用该工具。

句柄会在部署的 TTL(默认 15 分钟)或工具的 --compression-ttl 之后过期,读取不会延长其有效期。已过期、已释放或属于其他键的句柄会被 Gateway 拒绝,拒绝原因是 unknown_handle;CLI 的 handle 命令会将其报告为 handle_not_found(退出码 1):请重新调用该工具获取新句柄。不完整句柄(较长结果中的一页)会在其 completeness 和 warning 中说明这一点。要读取下一页,请再次调用 run_tool_as_handle 并提供分页参数。Context Surface 捕获会自行读取所有页面,最多达到部署限制(10,000 行),因此单个大型 Surface 查询可能占满句柄存储(已知问题 MOD-20735)。禁用 compression(DISABLED)后,tools/list 中将不再包含这七个工具。使用 SDK 时,gateway.call_as_handle(...) 会返回一个 Handle,而 redis_context_gateway.mcp.HANDLE_TOOLS 会列出这七个名称。

5. 验证

检查 1、3、4、6 和 7 需要在命令的环境中提供 Agent 密钥:在同一个 shell 命令中运行 set -a; . ./.env; set +a; iris ...,切勿打印该文件。

在 Redis Cloud 中,不带 --gateway-id 运行 3、4、8 和 9:tools 命令使用 IRIS_CONTEXT_GATEWAY_URL 和 Agent 密钥。其他检查会调用控制平面或需要缓存和句柄,而云端不提供这些功能。

  1. iris context-gateway service check gw_0123456789abcdef0123456789abcdef 通过所有步骤:令牌、Gateway、Identity Service、Agent 密钥,以及使用 Agent 密钥执行一次 tools/list。
  2. iris --json context-gateway service show gw_0123456789abcdef0123456789abcdef 显示 cache 和 compression 符合问题要求:每项正在使用的功能都显示为 ENABLED,并且存在 databaseBinding。如果某项功能显示为 DISABLED,而 Agent 并未选择禁用它,则说明数据库缺失或拒绝压缩(第 3 步“Gateway 开关和数据库”)。
  3. iris context-gateway --gateway-id gw_0123456789abcdef0123456789abcdef tools list 会显示所有 Upstream 的工具都带有命名空间(完整模式),或者显示 search_tools 和 run_tool(搜索模式)。启用压缩后,还会列出七个句柄工具。
  4. iris context-gateway --gateway-id gw_0123456789abcdef0123456789abcdef tools call crm__lookup_customer --arg id=42 会直接返回服务端返回的内容。
  5. iris context-gateway --gateway-id gw_0123456789abcdef0123456789abcdef policy list crm 会显示问题 3 和 4 中的缓存和压缩策略。
  6. 缓存命中:使用具有缓存策略的工具,将同一命令 iris --json context-gateway --gateway-id gw_0123456789abcdef0123456789abcdef tools call crm__search_customers --arg query=acme 连续运行两次。第二次结果的 _meta["com.redis.context-gateway/invocation"] 包含 "cache": {"status": "hit", ...},而第一次结果中没有 cache 条目。
  7. 句柄往返:tools call crm__export_orders --as-handle 会打印一个包含 h_... 的存根,随后 handle describe h_...、handle page h_... --limit 5 和 handle release h_... 都会返回结果。对已释放的句柄再次运行 handle describe 会以 handle_not_found 退出,退出码为 1。
  8. 让 Agent 执行一次会使用 Gateway 工具的任务,并展示调用经过了 Gateway(跟踪记录或日志中出现带命名空间的名称)。
  9. 取消设置 IRIS_CONTEXT_GATEWAY_API_KEY,并确认 SDK 会抛出指出该变量名的 ConfigurationError,或者 MCP 客户端会报告身份验证失败。

iris context-gateway service diagnose gw_0123456789abcdef0123456789abcdef 会说明导致失败的 Upstream、缓存或句柄设置问题,以及 Gateway 数据库缺失的问题。

6. 报告

列出 Gateway 的运行位置(Redis Cloud 或自托管)、五个问题的答案、添加的每个 Upstream(名称、命名空间、端点、密钥变量名,绝不包含密钥值)、暴露模式、设置的每项策略、Gateway 的 cache 和 compression 值及其所用的数据库、写入的数据模型、修改的文件、写入的客户端配置、添加和移除的环境变量、验证输出,以及任何无法通过 MCP 确认的事项。

评论

支持 Markdown