资讯动态

RocketRide tool_crustdata 实战:为 Agent 构建基于 Crustdata 的 B2B 公司与人物过滤搜索工具

发布时间:2026/9/25 15:13:13 来源:尧图企业网站定制
【免费下载链接】rocketride-serverHigh-performance AI pipeline engine with a C core and 50 Python-extensible nodes. Build, debug, and scale LLM workflows with 13 model providers, 8 vector databases, and agent orchestration, all from your IDE. Includes VS Code extension, TypeScript/Python SDKs, and Docker deployment.项目地址https://gitcode.com/gh_mirrors/ro/rocketride-server点击查看免费下载本文基于 RocketRide 开源引擎中的tool_crustdata工具节点文档与源码完整讲解该节点暴露的crustdata.company_search/crustdata.person_search两个 Agent 工具的过滤语法、操作符体系、分页游标、配置与认证方式并结合节点实现、共享重试层与单元测试说明其请求构造、容错降级与实验性边界的工程细节。读完后你可以掌握如何在 RocketRide 管道中接入 Crustdata 的 B2B 索引检索能力以及如何写出符合其{op, conditions}过滤语法的搜索条件。一、节点定位面向条件的 B2B 索引检索而非单条查询tool_crustdata是 RocketRide 的一个无数据通道no data lanes工具节点它为 Agent 提供对 Crustdata B2B 公司与人物索引的基于过滤条件filter-based的搜索能力。它的选型场景很明确当 Agent 需要按条件发现符合条件的客户accounts或联系人contacts时使用它如果 Agent 只是要查询一家已知公司或一个已知人物的单条记录它不是合适选择。从节点元数据 services.json 可以确认其定位lanes为空对象第 57 行即节点不参与数据管道的 lane 流动只作为可被调用的工具存在capabilities声明为[invoke, experimental]第 24 行——节点被标记为实验性请求与响应形态来自 Crustdata 已发布的版本化 API 参考但尚未有真实账户做过端到端验证对应仓库 issue #2129classType为toolprefix为crustdata这就是 Agent 侧函数名的服务器名前缀。Crustdata 本身是一个 B2B 数据供应商维护着公司与人物的索引数据库公司侧覆盖公司特征firmographics、融资、人员规模与招聘信号人物侧覆盖工作经历、教育与联系方式。它通过面向销售、招聘与市场研究团队的 REST API 出售访问权限而不是提供自己的应用。选择该节点而非通用 HTTP 工具的理由在于Crustdata 的过滤语法、取值上限与游标分页已经被节点封装处理完毕反之如果目标是开放网络内容而非索引化的 B2B 记录应改用网络搜索或抓取类节点。二、两个注册工具company_search 与 person_search服务器名前缀为crustdata节点注册了两个函数函数说明crustdata.company_search搜索 Crustdata 中匹配一个或多个过滤条件行业、地区、人员规模、融资、当前公司及其他的公司。返回结构化公司记录公司特征、融资历史、人员规模与招聘信号。用于按条件寻找潜在客户或调研客户账户而不是按名称查询一家已知的公司。crustdata.person_search搜索 Crustdata 中匹配一个或多个过滤条件当前公司、当前职位、地区及其他的人物。返回结构化人物档案姓名、职位、工作经历、教育背景以及在可得情况下的已验证联系方式。用于按条件发现或富化人物信息。源码中这两个工具通过tool_function装饰器注册在 IInstance.pycompany_search请求https://api.crustdata.com/company/searchperson_search请求https://api.crustdata.com/person/search常量定义于第 59–61 行。两者最终汇入同一个私有方法_search(args, url..., records_key..., tool_name...)差异仅在于 URL、响应体中记录列表的顶层键公司端点为companies人物端点为profiles以及各自输入 schema 中的过滤条件操作符集合。三、过滤语法条件结构、操作符与 all_of 分组3.1 基本条件{field, type, value}两个函数都要求传入filters——一个非空数组。普通条件ordinary condition是{field, type, value}三元组field点分路径dotted path。公司示例如basic_info.primary_domain人物示例如experience.employment_details.current.title。type操作符见下表。value标量、数组或对地理操作符而言是一个对象。节点将条件数组包装成 Crustdata API 期望的{op, conditions}分组形式发出即使只有一个条件也始终发送分组形式这在 IInstance.py 的注释中有明确说明始终发送分组形式更简单且同样合法。3.2 操作符集合公司与人物的差异操作符含义适用/!相等 / 不等公司、人物///比较运算。注意是和不是和公司、人物in/not_in成员 / 非成员公司、人物is_null/is_not_null空值判断公司、人物(.)全文匹配。公司端是带拼写容错的模糊全词匹配人物端是不带拼写容错的全词匹配公司、人物语义不同[.]精确短语匹配公司、人物geo_distance/geo_exclude地理半径内 / 排除地理半径。value取{location, distance, unit}对象公司、人物has_all匹配必需的数组值仅人物(!)取反匹配仅人物从源码结构看这个差异是硬编码在操作符枚举中的IInstance.py 定义了_BASE_OPERATORS14 个基础操作符、_PERSON_OPERATORS追加has_all与(!)以及_PERSON_ALL_OF_OPERATORSall_of 分组内部的受限子集。单元测试 test_crustdata.py 直接断言了这一点公司端 schema 不含has_all/(!)人物端 schema 包含它们。3.3 人物搜索的有界all_of分组人物filters数组中的元素除了普通条件外还可以是一个{op: all_of, conditions: [...]}分组用于约束嵌套数组如工作经历、教育经历all_of的每个直接子条件可以匹配嵌套数组中不同的元素若要求多个谓词作用于同一个元素需要把它们包进一层and或or子分组。例如把职位title与公司名称company_name条件放进同一个and子分组两个谓词就绑定到同一条工作经历记录上all_of内部不支持嵌套all_of、has_all、(!)、!、not_in、is_null与geo_exclude。这个受限的子集同样由 schema 显式表达IInstance.py 的_PERSON_ALL_OF_OPERATORS只保留 10 个正向操作符。测试用例test_person_schema_advertises_bounded_all_of_groupstest_crustdata.py逐一断言了不支持的操作符确实不在分组枚举中test_person_all_of_group_is_forwarded_unchangedtest_crustdata.py则验证了含and子分组的all_of会被原样转发到请求体并被外层{op: and, conditions: [...]}正确包裹。3.4 为什么match只有两个取值顶层组合参数match只接受and或or缺省为and其余任何值都按and处理。原因在文档中解释得很清楚人物搜索的all_of不是顶层通用组合子——它把自己的子条件约束在某个嵌套数组路径如 employment、education上拒绝标量字段且不能包含否定或再嵌套一层all_of。这些约束与一个扁平的“组合任意条件”的match参数完全不合身因此all_of只作为filters内部的有界分组暴露永远不会成为match的取值。实现上IInstance.py 的判断只有一行if match not in (and, or): match and。测试test_match_selects_the_op_and_defaults_to_and与test_all_of_is_never_sent_as_the_top_level_optest_crustdata.py分别验证了or的透传、非法值的回退以及matchall_of会被降级为and而非原样发出。四、可选参数与请求构造除必需的filters外两个工具共享一组可选参数schema 定义见 IInstance.py参数类型说明matchand|or多个条件如何组合缺省andsorts{field, order}[]order取asc或desc。只要打算用游标分页就应显式传排序——翻页之间改变排序会使游标失效fields非空字符串数组 |null要返回的区段section或点分路径。省略或传null时公司搜索返回完整公司记录人物搜索返回Crustdata 的默认区段。可返回字段与可搜索字段是两套独立定义不支持的投影交由 API 拒绝limit整数 1–1000缺省为节点配置的 Default Result Limit每次调用的limit覆盖它并以同样的方式钳制cursor字符串上一次调用返回的next_cursor首页省略请求构造逻辑集中在_search方法中IInstance.py可以读出以下行为filters先做防御校验不是列表或为空时不发请求直接返回success: false与错误信息fields经optional_str_list校验必须是非空字符串列表非法值在发出请求之前就被拒绝测试test_invalid_fields_are_rejected_before_any_request用mock_post.assert_not_called()确认没有网络调用发生limit解析规则None用节点配置值否则经_coerce_limit钳制到 [1, 1000]且布尔值不会被当成 1/0Python 中bool是int子类{limit: True}必须回退到配置值——测试test_bool_limit_does_not_become_1_or_0专门覆盖了这一点sorts与cursor仅在非空时写入请求体缺省时请求体里不会出现这两个键。一个典型的请求体形态测试断言的实际 wire 格式见 test_crustdata.py{ filters: { op: and, conditions: [ {field: basic_info.primary_domain, type: , value: acme.com} ] }, limit: 10 }五、响应结构失败是数据不是异常每次调用返回一个统一形状的对象键类型说明successbool调用是否成功filtersarray原样回显的条件便于 Agent 审计自己发了什么countinteger本页记录数resultsobject[]Crustdata 返回的记录按接收原样透传不做逐字段重映射next_cursorstring | null响应含游标时附带total_countinteger | null响应含总数时附带errorstring失败时的错误说明失败路径被收敛为三种全部以success: falseerror字符串的形式返回Agent 看到的是作为数据的失败而不是抛出的异常filters缺失或为空、请求失败重试耗尽后的网络/HTTP 错误、以及非 JSON 响应体。记录抽取由纯函数_extract_recordsIInstance.py完成它的容错策略值得注意优先尝试该端点文档确认的键companies/profiles再回退尝试results与data两个合理键非字典元素被丢弃而不是抛出异常完全无法识别的响应形状返回空列表而非报错。这组行为有专门的测试类TestExtractRecords覆盖test_crustdata.py包括“已验证键优先于回退键”“裸顶层列表可接受”“不认识的形状返回空而非错误”。六、配置与认证节点只有两个配置字段services.json字段类型说明默认值tool_crustdata.apikeystringsecure: trueUI 使用ApiKeyWidgetCrustdata API Key在 crustdata.com 申请。必需字段值与CRUSTDATA_API_KEY环境变量均缺失时节点启动失败两者同时存在时配置字段优先tool_crustdata.defaultLimitinteger1–1000Agent 未传limit时搜索所用的缺省结果数106.1 启动时的配置读取与降级IGlobal.py 的beginGlobal展示了密钥解析顺序节点配置apikey→ 环境变量CRUSTDATA_API_KEY→ 两者皆空则记录错误并raise ValueError节点拒绝启动。defaultLimit则走_coerce_limitIGlobal.pyNone或布尔值回退默认 10非数值回退 10数值钳制到 [1, 1000]。源码注释解释了为什么必须“优雅降级”Config.getNodeConfig会原样返回用户可手工编辑的管道文件中的内容——字段声明的type: integer只约束 UI 表单约束不了手编文件或 SDK 调用方因此非法值不能从beginGlobal中抛出去拖垮整个节点。测试类TestCoerceLimittest_crustdata.py覆盖了空字符串、非数字字符串、布尔、数字字符串、越界值等全部降级路径。关于defaultLimit的调优建议继承自原文档当结果直接进入 Agent 上下文时保持小值——Crustdata 的原始记录很宽大页会迅速烧掉 token当 Agent 用宽泛过滤条件做批量扫描、否则必须反复翻页时再调大超出部分仍可用cursor继续翻。6.2 认证头密钥存放在API Key字段时静态加密、UI 中打码secure: true声明或者设在引擎主机的CRUSTDATA_API_KEY环境变量上配置字段优先。每个请求携带的头由_crustdata_headersIInstance.py构造{ accept: application/json, content-type: application/json, authorization: fBearer {apikey}, x-api-version: 2025-11-01, # 版本钉死 }x-api-version: 2025-11-01是该版本化 API 的强制头——源码注释指出 Crustdata 文档将/screener/*与/data_lab/*标注为此版本化 API 的旧版前身。测试test_headers_carry_bearer_auth_and_the_pinned_api_version断言了 Bearer 与版本头同时存在。七、请求处理30 秒超时与指数退避重试节点不使用 Crustdata SDK直接用requests发请求重试策略复用仓库共享层 http_retry.py 的post_with_retry超时30 秒timeout默认值重试条件_is_retryablehttp_retry.py超时、连接错误、HTTP 429 与 5xx策略tenacityRetryingstop_after_attempt(4)即最多 4 次尝试wait_exponential(multiplier2.0, max60.0)指数退避、最长等待 60 秒其他 4xx 立即失败不重试重试耗尽后最后一个异常被重新抛出429/5xx 最终是HTTPError传输故障是Timeout/ConnectionError再由_search捕获并转成success: false的结构化错误。这组策略在测试里用真实的post_with_retry源码直接加载执行而非重新实现只 mockrequests.post因此验证的就是生产实现test_retries_on_429_then_succeeds首次 429、第二次 200断言共调用 2 次且最终成功test_retries_on_5xx_then_gives_up_after_max_retries持续 503断言恰好 4 次调用初次 3 次重试后返回success: falsetest_timeout_is_reported_as_a_structured_error_not_raised与test_connection_error_is_reported_as_a_structured_error断言超时/连接错误也走满 4 次尝试最终以带异常类型名的error字符串返回如... Timeout。八、分页规则与实验性边界8.1 游标分页把某次响应的next_cursor作为下一次调用的cursor传入。两条端点规则不同公司搜索翻页之间filters、sorts、fields必须完全一致否则游标失效人物搜索filters与sorts必须一致fields与limit允许在页间变化这是 Crustdata 明确允许的。无论哪个端点只要打算分页都应显式传sorts——这条建议直接写进了输入 schema 对sorts的描述中IInstance.py“改变排序会使游标失效”。8.2 实验性状态与未验证项节点在services.json中被标记experimental。其端点、条件 schema 与游标分页来自 Crustdata 自己的版本化 API 参考公司搜索与人物搜索两份 referencex-api-version: 2025-11-01而非来自实时集成。未验证的内容有两项每个实体的完整可搜索字段列表以及某个 API key 的套餐是否包含 Crustdata 同时宣传的实时real-time变体。该事项在仓库中跟踪为 issue #2129IInstance.py 的模块 docstring 中也完整记录了同一边界声明。相应地services.json 中的自动化测试配置也刻意只用占位 key 做配置校验不发起真实 API 调用。九、延伸阅读相关仓库文件文件内容nodes/src/nodes/tool_crustdata/README.md节点官方文档本文主体来源nodes/src/nodes/tool_crustdata/IInstance.py两个tool_function工具、输入 schema、请求构造与响应解析nodes/src/nodes/tool_crustdata/IGlobal.pyAPI key 解析、defaultLimit钳制、配置校验nodes/src/nodes/tool_crustdata/services.json节点元数据能力、前缀、配置字段与测试配置nodes/test/tool_crustdata/test_crustdata.py无网络单元测试响应解析、limit 降级、请求构造、重试行为packages/ai/src/ai/common/utils/http_retry.py共享 tenacity 重试层post_with_retrynodes/src/nodes/tool_crustdata/requirements.txt节点依赖仅requests适用前提小结该节点要求可用的 Crustdata API key字段或CRUSTDATA_API_KEY环境变量请求固定使用x-api-version: 2025-11-01头由于标记为实验性上线前建议先以小规模过滤条件实测你的 key 套餐对目标字段的覆盖情况。赞分享【免费下载链接】rocketride-serverHigh-performance AI pipeline engine with a C core and 50 Python-extensible nodes. Build, debug, and scale LLM workflows with 13 model providers, 8 vector databases, and agent orchestration, all from your IDE. Includes VS Code extension, TypeScript/Python SDKs, and Docker deployment.项目地址https://gitcode.com/gh_mirrors/ro/rocketride-server点击查看免费下载相关推荐X96-Max Armbian 安装2瓦折腾手记X96 Max Armbian 安装2瓦折腾手记 如果你手头有台吃灰的 S905X3 电视盒想做一次 Armbian 安装把它变成常开的小服务器可以照着嵌入式开发工具构建工具操作系统ARIAKIT Combobox 搜索过滤实战用 setValue 与 startTransition 构建响应式搜索下拉ARIAKIT Combobox 搜索过滤实战用 setValue 与 startTransition 构建响应式搜索下拉 本文基于 ARIAKIT 仓库中的UI组件前端RocketRide tool_cognee 节点实战通过 Cognee 服务器为 Agent 构建持久化语义记忆RocketRide tool_cognee 节点实战通过 Cognee 服务器为 Agent 构建持久化语义记忆 RocketRide 的 tool_cog上一篇你的内存条真的在按BIOS设定跑吗用ZenTimings把AMD内存时序看个明明白白下一篇Velero 故障排查实战指南日志定位、debug 模式与已知问题处理v1.0.0 文档解析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑