메인 콘텐츠로 건너뛰기

개요

search_notes는 노트 디스커버리의 심층 단계예요. 필수 keyword를 받아 주요 문서(one-pager, custom)와 함께 채워진 매칭 노트를 반환해요. 어떤 노트가 매칭되는지만 보는 게 아니라, LLM이 주제 이면의 결정, action item, 결론 등 맥락을 이해해야 할 때 사용하세요. 가벼운 메타데이터만 필요한 목록 조회(예: “폴더 X에 어떤 노트가 있지”)는 대신 list_notes를 사용하세요. 주요 사용 사례:
  • “OKR Q2에 대해 팀이 무엇을 결정했지?” — 주제로 검색하고 문서를 inline으로 읽어요.
  • “이 결정의 출처 노트가 어디 있지?” — keyword로 노트를 찾고 문서가 맥락을 줘요.
  • “네이버에 대해 우리가 쓴 걸 다 보여줘” — 내용까지 포함한 한국어 keyword 검색.
핵심 기능:
  • keyword 필수. 결과는 전문 검색 관련도(동점 시 createdAt 내림차순)로 정렬돼요.
  • 매칭된 각 노트는 주요 문서(one-pager, custom)를 inline으로 담아요.
  • 문서 내용에서 HTML이 제거돼요. 5,000자보다 큰 문서는 잘리고 표시돼요.
  • 검색 인덱스를 사용할 수 없을 때 우아하게 성능 저하(graceful degradation)해요.
list_notes보다 무거워요. 각 결과에 문서 내용이 포함돼요(노트당 ~1,500 토큰). 기본 페이지 크기는 50, 최대 200이에요. 메타데이터만 필요하면 list_notes를 사용하세요.

파라미터

ParameterTypeRequiredDescription
keywordstringYes검색 keyword(1자 이상). 제목과 단락 내용을 기준으로 전문 검색 매칭.
pagination.cursorstringOptional향후 사용 예약. 심층 검색 endpoint는 현재 null을 방출해요.
pagination.sizenumberOptional페이지당 결과 수(기본값 50, 최대 200).
filter.folderIdstringOptional폴더로 제한(재귀적 — 하위 폴더 포함).
filter.createdAtFromstringOptionalISO 8601 datetime, createdAt의 포함 하한.
filter.createdAtTostringOptionalISO 8601 datetime, createdAt의 배제 상한.

keyword (필수)

검색어예요. 서버 측에서 토큰화돼요. 한국어 텍스트는 형태소 분석돼요(예: 네이버[네, 버]). 비었거나 공백만 있는 keyword는 400을 반환해요. keyword 검색은 현재 사용자 범위 API key가 필요해요. 팀 전용 API key는 400을 반환해요.

filter.folderId (선택)

list_notes와 의미가 같아요. 재귀적 폴더 범위이며 서버 측에서 인가돼요.

pagination (선택)

{ cursor, size }. 기본값 size: 50, 최대 200. 이 상한은 결과당 더 높은 비용(각 노트가 문서를 담음)을 반영해요.

응답 형식

성공 응답

{
  "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
}
필드 설명:
FieldTypeDescription
notes[]array매칭된 노트, 전문 검색 관련도(동점 시 createdAt 내림차순)로 정렬.
notes[].matchedSnippetsstring[] | null하이라이트 스니펫용 예약. 현재 null로, “하이라이트 미구현”과 “검색했으나 매칭 하이라이트 없음”을 구분해요.
notes[].documents[]array노트의 주요 문서. 노트에 문서가 없으면 빈 배열.
notes[].documents[].documentGuidstring안정적인 문서 식별자.
notes[].documents[].templateIdnumber | null숫자 template id — 유일하게 안정적인 구분자.
notes[].documents[].templateTitlestring표시 라벨(예: "One Pager", "회의록"). locale에 따라 달라지고 custom 템플릿은 사용자가 편집 가능 — 이 문자열로 구분하지 마세요.
notes[].documents[].contentstringHTML 제거된 markdown 친화 텍스트. 5,000자로 제한. truncated를 참고하세요.
notes[].documents[].truncatedboolean내용이 잘렸으면 true. 나머지가 필요하면 get_note(include: ['documents'])로 전체 문서를 가져오세요.
nextCursorstring | null향후 사용 예약. 현재 항상 null.
degradedboolean검색 인덱스를 사용할 수 없거나 실패했으면 true.
degradedReasonstring | nulldegraded=true일 때: "search_index_unavailable" 또는 "search_index_degraded".
templateTitle로 구분하지 마세요. 이건 enum이 아니라 표시 라벨이에요. boolean 확인(“이게 one-pager인가?”)에는 알려진 관리형 템플릿 id에 대해 templateId를 사용하거나, 두 필드를 모두 노출하고 UI가 라벨로 고르게 하세요.

성능 저하 응답

검색 인덱스를 사용할 수 없으면 응답은 degraded=true로 설정되고 빈 notes 배열을 반환해요:
{
  "notes": [],
  "nextCursor": null,
  "degraded": true,
  "degradedReason": "search_index_unavailable"
}
degradedReason은 다음 중 하나예요:
  • search_index_unavailable — 이 환경에서 검색 인덱스가 비활성화됨.
  • search_index_degraded — 쿼리 도중 검색 인덱스가 오류를 던짐.
재시도를 미루거나 결과를 적절히 해석할 수 있도록 이를 LLM/사용자에게 노출하세요.

사용 예시

예시 1: 주제 검색

요청:
{
  "keyword": "OKR"
}
OKR을 언급하는 가장 관련도 높은 노트 10개를 각각의 주요 문서와 함께 inline으로 반환해요.

예시 2: 폴더 범위 한국어 keyword

요청:
{
  "keyword": "네이버",
  "filter": {
    "folderId": "455765"
  },
  "pagination": {
    "size": 5
  }
}
폴더 455765(및 하위)에서만 네이버를 검색해요. 한국어 형태소 분석이 서버 측에서 실행돼요.

예시 3: 날짜 범위 심층 검색

요청:
{
  "keyword": "release",
  "filter": {
    "createdAtFrom": "2026-04-01T00:00:00Z",
    "createdAtTo": "2026-05-01T00:00:00Z"
  }
}

권장 사례

먼저 list_notes로 어떤 노트가 매칭되는지 찾으세요. LLM이 답하기 위해 여전히 문서 내용이 필요하면 같은 keyword로 search_notes로 전환하세요. 가장 저렴한 점진적 공개 경로예요.
폴더 범위 검색은 관련도 공간이 더 작아서 더 빠르고 순위가 더 좋은 결과를 반환해요. 폴더 후보를 먼저 찾으려면 list_notes(filter.folderId)와 함께 쓰세요.
심층 검색 endpoint는 현재 nextCursor: null을 방출해요. 결과 30개로 부족하면 페이지네이션 대신 keyword를 더 구체적으로 다듬거나 folderId/dateRange로 범위를 좁히세요.
degraded=true 응답은 솔직한 신호예요. 검색 인덱스가 실행되지 못했어요. 빈 notes 배열을 “매칭 없음”으로 취급하지 말고, 재시도 타이밍을 적절히 잡을 수 있도록 성능 저하를 사용자/LLM에게 노출하세요.

자주 발생하는 오류

빈 keyword

팀 전용 API key

해결 방법: 사용자 범위 API key를 사용하세요. 팀 폴더 keyword 검색은 후속 릴리스에 들어와요.

토큰 사용량

노트당 (문서 포함): 평균 약 1,500 토큰. 잘린 문서는 원본 크기와 관계없이 약 1,500 토큰으로 제한돼요.
get_note_transcript와 비교하면(회의 시간당 ~3,000–5,000 토큰), search_notes는 보통 10배 더 압축적이면서 같은 핵심 결정을 다루는 정제된 문서를 반환해요. 정확한 발화가 필요할 때만 transcript를 사용하세요.