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

# search_notes

> 一致したノートを主要ドキュメントとともに返す、深いキーワード検索

## 概要

`search_notes` はノート探索の深い階層です。**必須のキーワード**を受け取り、一致したノートに主要ドキュメント（ワンページャー、カスタム）を付与して返します。LLM が、単に一致するノートを見るだけでなく、**トピックの背後にあるコンテキスト**（決定事項、アクションアイテム、結論）を理解する必要があるときに使用してください。

軽量なメタデータのみの一覧表示（例: 「フォルダ X にはどのノートがありますか」）には、代わりに [`list_notes`](./list-notes) を使用してください。

**主なユースケース:**

* 「OKR Q2 についてチームは何を決めたのか?」 — トピックで検索し、ドキュメントをインラインで読む。
* 「この決定のソースノートはどこか?」 — キーワードでノートを見つけ、ドキュメントがコンテキストを与える。
* 「네이버 について書いたものをすべて見せて」 — 韓国語のキーワード検索をコンテンツ付きで。

**主な特長:**

* キーワード必須。結果は全文検索の関連度（同点の場合は `createdAt` の降順）で並べ替えられます。
* 一致した各ノートには、主要ドキュメント（ワンページャー、カスタム）がインラインで付きます。
* ドキュメントのコンテンツから HTML を除去します。5,000 文字を超えるドキュメントは打ち切られ、フラグが付きます。
* 検索インデックスが利用できない場合の優雅な縮退。

<Warning>
  **`list_notes` より重い。** 各結果にはドキュメントのコンテンツが含まれます（ノートあたり \~1,500 トークン）。デフォルトのページサイズは `50`、最大 `200` です。メタデータのみが必要な場合は [`list_notes`](./list-notes) を使用してください。
</Warning>

## パラメータ

| Parameter              | Type   | Required | Description                                                                                                                                   |
| ---------------------- | ------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `keyword`              | string | **Yes**  | 検索キーワード（1 文字以上）。タイトルと段落のコンテンツに対して全文一致します。                                                                                                     |
| `pagination.cursor`    | string | Optional | 将来の使用のために予約。深い検索 endpoint は現在 `null` を返します。                                                                                                   |
| `pagination.size`      | number | Optional | 1 ページあたりの結果数（デフォルト `50`、最大 `200`）。                                                                                                            |
| `workspaceGuid`        | string | Optional | ワークスペース GUID（`list_workspaces` から取得）。省略するとアクセスできるすべてのワークスペースを横断して検索します — workspace-scoped key は自動的に自身のワークスペースを検索します。指定すると検索を単一のワークスペースに限定します。 |
| `filter.folderId`      | string | Optional | フォルダに限定（再帰的 — 子孫フォルダを含みます）。                                                                                                                   |
| `filter.createdAtFrom` | string | Optional | ISO 8601 形式の日時。`createdAt` の下限（その値を含む）。                                                                                                       |
| `filter.createdAtTo`   | string | Optional | ISO 8601 形式の日時。`createdAt` の上限（その値を含まない）。                                                                                                     |

### keyword (required)

検索語です。サーバー側でトークン化され、韓国語テキストは形態素解析されます（例: `네이버` → `[네, 버]`）。空または空白のみのキーワードは `400` を返します。

キーワード検索は、user-scoped と workspace-scoped のどちらの API key も受け付けます。`workspaceGuid` を省略するとアクセスできるすべてのワークスペースを横断して検索します — workspace-scoped key は自動的に自身のワークスペースを検索します。特定のワークスペースに検索を限定するには、明示的な `workspaceGuid`（[パラメータ](#パラメータ)を参照）を渡してください。

### filter.folderId (optional)

`list_notes` と同じ意味です。再帰的なフォルダ範囲で、サーバー側で認可されます。

### pagination (optional)

`{ cursor, size }`。デフォルト `size: 50`、最大 `200`。この上限は、結果あたりのコストが高いこと（各ノートがドキュメントを伴うこと）を反映しています。

## レスポンス形式

### 成功レスポンス

```json theme={"system"}
{
  "notes": [
    {
      "noteGuid": "abc-123-def",
      "title": "OKR Q2 Planning",
      "webUrl": "https://platform.tiro.ooo/notes/abc-123-def",
      "createdAt": "2026-04-15T10:00:00Z",
      "updatedAt": "2026-04-15T11:30:00Z",
      "recordingDurationSeconds": 3625,
      "sourceType": "live-voice",
      "participants": [
        { "name": "Alice Kim", "email": "alice@example.com" }
      ],
      "matchedSnippets": null,
      "documents": [
        {
          "documentGuid": "7821",
          "templateId": 12,
          "templateTitle": "One Pager",
          "content": "## 결정 사항\n- 자동 ingest 우선...\n## Action Items\n- ...",
          "truncated": false,
          "updatedAt": "2026-04-15T11:30:00Z"
        }
      ]
    }
  ],
  "nextCursor": null,
  "degraded": false,
  "degradedReason": null
}
```

**フィールドの説明:**

| Field                               | Type              | Description                                                                                           |
| ----------------------------------- | ----------------- | ----------------------------------------------------------------------------------------------------- |
| `notes[]`                           | array             | 一致したノート。全文検索の関連度（同点の場合は `createdAt` の降順）で並べ替えられます。                                                    |
| `notes[].matchedSnippets`           | string\[] \| null | ハイライトスニペット用に予約。現在は `null` で、「ハイライトが未実装」と「検索したがハイライトが一致しなかった」を区別します。                                   |
| `notes[].documents[]`               | array             | ノートの主要ドキュメント。ノートにドキュメントがない場合は空配列。                                                                     |
| `notes[].documents[].documentGuid`  | string            | 安定したドキュメント識別子。                                                                                        |
| `notes[].documents[].templateId`    | number \| null    | 数値のテンプレート ID。唯一の安定した判別子です。                                                                            |
| `notes[].documents[].templateTitle` | string            | 表示用ラベル（例: `"One Pager"`、`"회의록"`）。**ロケール依存で、カスタムテンプレートではユーザーが編集可能**です。この文字列で判別しないでください。                |
| `notes[].documents[].content`       | string            | HTML 除去済み、Markdown 対応のテキスト。5,000 文字で打ち切り。`truncated` を参照。                                             |
| `notes[].documents[].truncated`     | boolean           | コンテンツが打ち切られた場合は `true`。残りが必要な場合は [`get_note(include: ['documents'])`](./get-note) でドキュメント全文を取得してください。 |
| `nextCursor`                        | string \| null    | 将来の使用のために予約。現在は常に `null`。                                                                             |
| `degraded`                          | boolean           | 検索インデックスが利用できなかった、または失敗した場合は `true`。                                                                  |
| `degradedReason`                    | string \| null    | `degraded=true` の場合: `"search_index_unavailable"` または `"search_index_degraded"`。                      |

<Warning>
  **`templateTitle` で判別しないでください。** これは表示用ラベルであり、enum ではありません。ブール値のチェック（「これはワンページャーか?」）には、既知の管理済みテンプレート ID に対して `templateId` を使用するか、両方のフィールドを提示して UI にラベルで選ばせてください。
</Warning>

### 縮退レスポンス

検索インデックスが利用できない場合、レスポンスは `degraded=true` を設定し、空の `notes` 配列を返します。

```json theme={"system"}
{
  "notes": [],
  "nextCursor": null,
  "degraded": true,
  "degradedReason": "search_index_unavailable"
}
```

`degradedReason` は次のいずれかです。

* `search_index_unavailable` — この環境では検索インデックスが無効になっています。
* `search_index_degraded` — クエリの途中で検索インデックスがエラーを投げました。

リトライを延期したり結果を適切に解釈したりできるよう、これを LLM／ユーザーに提示してください。

## 使用例

### 例 1: トピック検索

**リクエスト:**

```json theme={"system"}
{
  "keyword": "OKR"
}
```

OKR に言及する最も関連度の高いノート 10 件を、それぞれの主要ドキュメントをインラインで付けて返します。

### 例 2: フォルダ限定の韓国語キーワード

**リクエスト:**

```json theme={"system"}
{
  "keyword": "네이버",
  "filter": {
    "folderId": "455765"
  },
  "pagination": {
    "size": 5
  }
}
```

フォルダ `455765`（とその子孫）の中だけで `네이버` を検索します。韓国語の形態素解析はサーバー側で実行されます。

### 例 3: 日付で区切った深い検索

**リクエスト:**

```json theme={"system"}
{
  "keyword": "release",
  "filter": {
    "createdAtFrom": "2026-04-01T00:00:00Z",
    "createdAtTo": "2026-05-01T00:00:00Z"
  }
}
```

## ベストプラクティス

<AccordionGroup>
  <Accordion title="Start with list_notes, switch to search_notes when content is needed">
    まず [`list_notes`](./list-notes) を使って、どのノートが一致するかを見つけてください。LLM が答えるためにドキュメントの内容をなお必要とする場合は、同じキーワードで `search_notes` に切り替えます。これが最も安価な段階的開示のパスです。
  </Accordion>

  <Accordion title="Use folderId to narrow the search universe">
    フォルダ限定の検索は、関連度の空間が小さくなるため、より高速で、より良くランク付けされた結果を返します。まず `list_notes(filter.folderId)` と組み合わせてフォルダ候補を見つけてください。
  </Accordion>

  <Accordion title="Don't loop on `nextCursor`">
    深い検索 endpoint は現在 `nextCursor: null` を返します。30 件の結果で足りない場合は、ページネーションするのではなく、キーワードを絞り込む（より具体的に）か、folderId／dateRange で範囲を限定してください。
  </Accordion>

  <Accordion title="Watch the `degraded` flag">
    `degraded=true` のレスポンスは正直です。検索インデックスが実行できなかったのです。空の `notes` 配列を「一致なし」と扱わないでください。代わりに、リトライのタイミングを適切に計れるよう、縮退をユーザー／LLM に提示してください。
  </Accordion>
</AccordionGroup>

## よくあるエラー

### 空のキーワード

<Error>
  ```json theme={"system"}
  {
    "error": "keyword must not be blank",
    "code": "BAD_REQUEST",
    "statusCode": 400
  }
  ```
</Error>

## トークン使用量

**ノートあたり（ドキュメント付き）:** 平均 \~1,500 トークン。打ち切られたドキュメントは、元のサイズにかかわらず \~1,500 トークンで頭打ちになります。

<Tip>
  **`get_note_transcript`（会議 1 時間あたり \~3,000–5,000 トークン）と比べて**、`search_notes` は通常 10 倍コンパクトで、同じ重要な決定事項をカバーする、整理されたドキュメントを返します。話された言葉そのものが必要なときにのみトランスクリプトを使ってください。
</Tip>
