> ## Documentation Index
> Fetch the complete documentation index at: https://docs.userintuition.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Search research

> Runnable TypeScript example: search research, with inputs, output, source code, and execution limits.

[Raw TypeScript source](https://raw.githubusercontent.com/user-intuition/examples/main/examples/search-research/index.ts) · [Workflow walkthrough](https://github.com/user-intuition/examples/tree/main/examples/search-research) · [All examples](/api-reference/developer-examples)

## Run locally

Requires Node.js 22.18 or later. Run from the cloned repository; this file imports the shared client and contracts in `src/`. The default uses fictional local fixtures with no credentials, network calls, invitations, or spending.

```sh theme={null}
git clone https://github.com/user-intuition/examples.git
cd examples
npm run search
```

For live calls, supply `USERINTUITION_API_KEY` securely in the environment and explicitly select `--live`. Follow the walkthrough for action-specific arguments and approvals. The B2/C1 adapters are illustrative pending [release verification](https://github.com/user-intuition/examples/blob/main/docs/release-check.md). Passing fixture checks does not establish live contract compatibility.

## Inputs

Use --query with the research question. Optional --study, --cursor, --limit, and --fetch-source constrain or extend retrieval. Fixture mode returns a fixed match and does not execute the query.

## Expected output

JSON containing mode, request, and response. The response includes results, next\_cursor, and coverage. With --fetch-source, a second object contains source\_kind and source or explains that there are no matches.

## Side effects

Retrieves existing evidence; does not create studies, regenerate reports, invite people, or launch recruitment.

## Failures

Invalid limits, missing live credentials, HTTP errors, invalid response shapes, and unresolved sources are failures. A successful empty results array is distinct from these errors.

## Complete source file

The following is generated from `examples/search-research/index.ts`, not maintained as a separate snippet. SHA-256: `36c6a387b1ff89d12e48f9ae22f0f867e47424cb6214cfe40b7fb680e7f148d8`.

```typescript theme={null}
import { args, limit } from "../../src/args.ts";
import {
  ResearchClient,
  fixture,
  output,
  releaseNotice,
} from "../../src/client.ts";
import {
  routes,
  type SearchRequest,
  type SearchResponse,
} from "../../src/contracts.ts";
const options = args();
const request: SearchRequest = {
  query:
    options.query ?? "What makes people think the product is too expensive?",
  limit: limit(options.limit),
  cursor: options.cursor ?? null,
  filters: {
    content_types: ["study_finding", "participant_response"],
    ...(options.study ? { study_ids: [options.study] } : {}),
  },
};
if (options.live) releaseNotice();
const response = options.live
  ? await new ResearchClient().request<SearchResponse>(
      "POST",
      routes.search,
      request,
    )
  : await fixture<SearchResponse>("search");
if (!Array.isArray(response.results))
  throw new Error(
    "Unexpected search response: results is not an array. Check the released contract.",
  );
output({
  mode: options.live
    ? "live"
    : "fictional fixture; query is illustrative, not executed",
  request,
  response,
});
// Fetch a source with routes.report(result.study.id) or routes.interview(result.source.interview_id).
// Paginate with the same query/filters and next_cursor. No new study is created by this example.

if (options["fetch-source"]) {
  const result = response.results[0];
  if (!result) {
    output({ source_status: "No search matches; no source was fetched." });
  } else {
    const interviewId = result.source.interview_id;
    const source = options.live
      ? await new ResearchClient().request(
          "GET",
          interviewId
            ? routes.interview(interviewId)
            : routes.report(result.study.id),
        )
      : interviewId
        ? (
            await fixture<Array<{ id: string; messages: unknown[] }>>(
              "interviews",
            )
          ).find((item) => item.id === interviewId)
        : await fixture("report");
    if (!source)
      throw new Error(
        "Search source was not found; do not infer its contents.",
      );
    output({
      result_id: result.result_id,
      source_kind: interviewId ? "interview" : "report",
      source,
      instruction:
        "Check source context and report version before citing. This is one result, not exhaustive coverage.",
    });
  }
}
```
