# tool_crustdata

A RocketRide tool node that gives an AI agent B2B company and people search powered by
[Crustdata](https://crustdata.com)'s discovery API.

> Experimental: this node is marked `experimental` and may change. The endpoints and
> request/response schema here are read directly from Crustdata's versioned API
> reference (`x-api-version: 2025-11-01`), but no live account has exercised it
> end-to-end — see [#2129](https://github.com/rocketride-org/rocketride-server/issues/2129).

## What it does

When an agent calls `company_search` or `person_search`, the node runs a filter-based
search against Crustdata's `POST /company/search` or `POST /person/search` REST API and
hands back structured records: firmographics, funding, headcount, and hiring signals
for companies; title, work history, education, and verified contact info for people.

Filters are a list of `{field, type, value}` conditions (e.g. `{"field":
"basic_info.primary_domain", "type": "=", "value": "acme.com"}`) — the node wraps them
into Crustdata's `{"op": <match>, "conditions": [...]}` group form before sending, so
callers just supply a flat list plus an optional `match` ("and"/"or", default "and").
Company search's `op` enum only has those two values; person search's third value,
`all_of`, is a specialized nested-array operator (all conditions on one employment
or education path, matched across possibly-different array elements) rather than a
generic combinator, and isn't exposed here. This is a **search/discovery** tool
(find records matching criteria), not a single-entity enrichment lookup by domain
or email.

Pagination is cursor-based, per Crustdata's API: a response's `next_cursor` is passed
back as `cursor` on the next call. Crustdata's docs note that changing `filters` or
`sorts` between pages invalidates the cursor, so pass an explicit `sorts` when
paginating to keep ordering stable.

Implemented with the **requests** library, no Crustdata SDK is used. Requests time out
after 30 seconds and are retried up to 3 times with exponential backoff (2 s base delay)
on rate limits (HTTP 429), server errors (5xx), and timeouts. Failures are returned to
the agent as a structured `{"success": false, "error": ...}` result rather than raised.

The node has no pipeline lanes (`lanes` is `{}`). Only agent runtimes reach it, through
the `invoke` capability.

---

## Configuration

| Field | Type | Description |
|---|---|---|
| `apikey` | string | Default empty. Crustdata API key (from https://crustdata.com) |
| `defaultLimit` | integer | Default 10. Default maximum number of results per search (1-1000) |

The config values act as defaults; the agent can override `limit` per call.

---

## Available tools

### `company_search`

Search Crustdata's company index by filter criteria (industry, region, headcount,
funding, current company, and more). `filters` is the only required parameter.

### `person_search`

Search Crustdata's people index by filter criteria (current company, current title,
region, and more). `filters` is the only required parameter.

| Tool | Description |
|---|---|
| `company_search` | Search Crustdata for companies matching one or more filters. Returns structured company records: firmographics, funding history, headcount, and hiring signals. Use this to find prospects or research accounts by criteria, not to look up one already-known company by name. |
| `person_search` | Search Crustdata for people matching one or more filters. Returns structured profiles: name, title, work history, education, and verified contact info where available. Use this to find or enrich people by criteria. |

Both accept `filters` (required, a list of `{field, type, value}` conditions), plus
optional `match` (how conditions combine), `sorts`, `limit`, and `cursor`. Both return
an object with `success`, `filters` (echoed back), `count`, `results` (array of raw
Crustdata records — exact per-record fields aren't remapped), `next_cursor` and
`total_count` (from Crustdata's response, when present), and `error` on failure.

---

## Authentication

Drop your Crustdata API key into the **API Key** config field. The field is encrypted
at rest and masked in the UI. Alternatively, set the `CRUSTDATA_API_KEY` environment
variable on the engine host — the config field takes precedence when both are set. The
key is sent to Crustdata as `Authorization: Bearer <key>`, alongside a required
`x-api-version: 2025-11-01` header on every request.

Crustdata's documentation indicates real-time, live web-derived enrichment is an
enterprise/plan-gated feature separate from cached-database search results — which tier
a given API key unlocks isn't confirmed here (see #2129).

---

<!-- ROCKETRIDE:GENERATED:PARAMS START -->
<!-- Generated by nodes:docs-generate. Do not edit by hand. -->

## Schema

| Field | Type | Description | Default |
|---|---|---|---|
| `tool_crustdata.apikey` | `string` | **API Key**<br/>Crustdata API key (from https://crustdata.com) | `""` |
| `tool_crustdata.defaultLimit` | `integer` | **Default Result Limit**<br/>Default maximum number of results per search (1-1000) | `10` |

## Dependencies

- `requests`

## Source

[<svg viewBox="0 0 16 16" width="15" height="15" fill="currentColor" aria-hidden="true" style="vertical-align:-0.15em;margin-right:0.35em"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/></svg> View source](https://github.com/rocketride-org/rocketride-server/tree/develop/nodes/src/nodes/tool_crustdata)
<!-- ROCKETRIDE:GENERATED:PARAMS END -->
