给编程 Agent 接入 GraphQL 模式记忆
作者为 Cognee 构建 GraphQL SDL 连接器,让 Agent 在生成查询和变更前检索相关模式定义。针对虚构字段、混淆输入输出类型、遗漏必填参数等问题,提供补充真实 API 上下文的实现思路。
AI 深度解读
让 AI 写一个获取用户资料的 GraphQL 查询,它可能顺手选用 profilePicture,而你的接口实际叫 avatarUrl。代码看着合理,却连校验都过不了。问题在于,模型熟悉常见 API 的写法,却未必知道当前项目的接口契约。
作者为 Cognee 编写了一个 GraphQL SDL 连接器,尝试把 schema 变成可检索的知识,让 Agent 先查定义再生成代码。这个方案值得关注,但原文提供的是架构与示例流程,没有给出错误率下降的实测数据,也没有证明检索可以替代校验。
为什么 GraphQL 不能靠模型猜字段
GraphQL 的 Schema Definition Language(SDL)规定了客户端能请求什么:对象有哪些字段、操作接受哪些参数、参数是否必填、返回结果能否为空。它还包含输入对象、枚举、联合类型、接口、指令和说明文档。
下面这段定义,足够解决开头的字段误用问题:
type User {
id: ID!
name: String!
avatarUrl: String
}
type Query {
user(id: ID!): User
}
要看清 user(id: ID!): User 这一行:参数叫 id,而且必须提供;返回的 User 却可能为空。User 内部的 id 和 name 非空,avatarUrl 可以为空。这几种约束不能混为一谈。
模型缺少这些信息时,容易沿用其他项目的习惯:把 avatarUrl 写成 profilePicture,把参数 where 写成 filter,混淆 input CreateUserInput 和 type User,或者在标量字段下面继续请求子字段。联合类型的成员也可能被凭空补出来。
生成 GraphQL 操作之前,Agent 需要拿到当前项目的真实类型定义。
把整个 schema 塞进提示词,是直接的办法。但 schema 较大时,每次重复传入会占用 token,也让相关定义淹没在大量无关内容中。作者提出的替代路径是:提前解析 SDL,需要时只检索相关操作及其依赖类型。
这里的「记忆」可以理解为一份供 Agent 查询的接口知识库,模型并没有因此永久学会你的 API。
连接器要保留的,除了字段还有关系
作者在 Mergetober 期间构建了 cognee-community-connector-graphql,入口是 schema.graphql 或 schema.gql 文件。连接器解析类型、字段、输入对象、枚举和参数,再交给 Cognee 做知识处理与检索。
Cognee 在文中被描述为一个开源 AI 记忆框架,支持结构化知识和检索。开发者可以用自然语言询问「哪个 mutation 更新组织订阅,需要哪些参数,返回什么」,再把检索结果交给编码 Agent。
这条链路能否有用,关键在于关系是否完整。只找到 updateSubscription 这个名称还不够,Agent 还需要知道参数 orgId: ID!、plan: SubscriptionPlan!,以及返回的 SubscriptionPayload! 包含什么。
原文用一种便于阅读的表示列出了:
success: Boolean!表示操作结果。subscription: Subscription指向订阅对象。errors: [String!]表示错误字符串列表。
这种表示不是合法 SDL,而是供检索和理解使用的摘要。[String!] 的列表元素不能为 null,但列表本身可以为 null;如果摘要丢掉类型修饰符,接口约束就会失真。
作者还提出用 graphql:{kind}:{name} 作为确定性标识,例如 graphql:type:user、graphql:input:createuserinput、graphql:enum:role 和 graphql:mutation:updatesubscription,帮助重复导入时识别同一实体。
不过,标识稳定不等于自动去重。是否覆盖已有记录、是否保留重复关系,仍取决于实现。原文也没有说明,多份 schema 中的同名实体如何隔离。
更新同样重要。作者提到可考虑 write_disposition="replace" 这种快照替换策略,但没有承诺它一定清除旧数据。真正需要验证的是:schema 删除一个字段后,检索结果里对应定义和关联关系是否一起消失。否则,Agent 只是从凭经验猜错,变成根据过期知识写错。
示例流程怎么接,哪些地方还不能照单运行
原文给出的安装命令是 pip install cognee cognee-community-connector-graphql。随后把 schema.graphql 和 index_schema.py 放在同一目录。
下面这段脚本展示了从加载 SDL 到自然语言搜索的完整调用顺序:
import asyncio
import cognee
from cognee_community_connector_graphql import graphql_source
async def main():
# 1. Load the GraphQL schema file
print("Loading schema.graphql into Cognee...")
source = graphql_source(
schema_path="./schema.graphql"
)
# 2. Ingest the schema into Cognee
await cognee.remember(
source,
dataset_name="graphql_api",
max_rows_per_table=0,
)
# 3. Process the ingested information
print("Building GraphQL knowledge...")
await cognee.cognify(
dataset_name="graphql_api",
)
# 4. Search for a relevant operation
print("Searching the GraphQL schema...")
results = await cognee.search(
"Which mutation updates a user's subscription, "
"and what arguments are required?",
dataset_name="graphql_api",
)
for result in results:
print(f"\n{result}")
if __name__ == "__main__":
asyncio.run(main())
要特别检查 max_rows_per_table=0 这一行。原文明确要求确认它在实际版本中的含义,不能直接把 0 理解成无限制,更不能据此断定整个 schema 已完整导入。
这段代码表达的是四步意图:graphql_source 加载文件,cognee.remember 导入数据,cognee.cognify 处理知识,cognee.search 搜索相关操作。它们都使用 dataset_name="graphql_api",把流程关联到同一数据集。
但作者没有提供包版本,导入路径、导出函数和 API 签名也要求使用者自行核对。因此,这是一份接入示例,不能当作已经验证过的运行记录。
文末的 mutation UpdateBilling 同样只是示意:使用 $orgId: ID! 和 $plan: SubscriptionPlan! 调用 updateSubscription,选择 success、errors,以及 subscription 下的 id、plan、renewalDate。这些嵌套字段必须真实存在,操作才可能有效。前面的摘要只指出 subscription 返回 Subscription,并不足以证明它包含全部三个字段。
我的判断
这个方向说得对:给 Agent 提供项目事实,比要求它「不要幻觉」更具体。尤其当问题需要跨操作、输入对象和返回类型查找时,检索系统有机会减少人工翻 schema 的工作。
但收益有前提。schema 必须及时更新,检索必须找到足够完整的类型链路,生成后的操作还要对照当前 schema 校验。少了任何一环,知识库都可能给错误增加一层可信外观。
与直接提供相关 SDL 相比,这套方案增加了导入、知识处理、同步和检索的维护成本。对于 schema 较小、目标操作明确的项目,先把相关定义放进上下文,可能已经够用。对于大型 schema 或多个 API,检索更有吸引力,但原文没有给出两种方式在准确率、token 用量和延迟上的对照数据。
作者也没有展示连接器的实际检索输出、端到端测试结果或错误率统计。相关贡献指向 Cognee Community PR #495 和 Cognee issue #6308,具体实现仍需进一步检查。
目前更适合把它看作值得试验的上下文方案,而不是已经证明能消除 GraphQL 幻觉的成品。
另外,schema 能说明操作是否合法,却不能单独证明业务行为正确。作者保留了最后的测试环节,这个边界是合理的。
能拿来做什么
- 在前端或 Node 项目的 AI 编程流程里,把「查相关 SDL」放到生成 query、mutation 之前,至少提供目标操作、参数、返回对象及需要访问的嵌套类型。
- 如果准备试用连接器,先核对包的实际导出、API 签名和
max_rows_per_table=0的语义,再检查搜索结果是否包含必填参数、非空约束和完整返回路径。 - 用一次删除字段的 schema 更新验证同步行为,重新导入后搜索旧字段,确认过期定义和关系都被清理。
- 保留「检索、生成、对照当前 schema 校验、运行测试」的流程,并记录字段误用、参数错误等失败案例,再判断引入知识库是否值得。