공개 데이터 Skills에 통합 응답 envelope가 필요한 이유

공개 데이터 Skills에 통합 응답 envelope가 필요한 이유
Unif Engineering team
Unif Engineering team

업데이트

플랫폼마다 응답 형태가 다릅니다. UnifAPI는 이를 하나의 엔벨로프로 통합해 Skills가 안정적으로 호출·비교·복구할 수 있게 합니다.

요약: 이것은 응답 계약에 관한 글입니다. 공개 플랫폼은 서로 다르지만, 에이전트는 페이지네이션, 과금, 오류, record를 위해 하나의 envelope가 필요합니다.

모든 공개 데이터 출처는 서로 다른 응답 형태를 반환합니다. TikTok은 결과를 한 방식으로 감싸고, Reddit은 또 다른 방식으로, YouTube는 또 다른 방식으로, LinkedIn은 또 다른 방식으로 감쌉니다. 당신의 에이전트가 그 모두와 직접 대화하면, 그 모든 변형을 물려받습니다 — 페이지네이션 로직이 갈라지고, 재시도 정책이 갈라지고, 오류 파싱이 갈라집니다. 우리는 모든 작업을 하나의 envelope를 통과시켜 이를 해결합니다. 다음은 그 스키마와 그것이 왜 중요한지입니다.

문제

출처 변형은 다중 플랫폼 에이전트에 부과되는 보이지 않는 세금입니다. 에이전트의 도구 사용 루프는 많은 형태를 처리해야 하고, 그 복잡성은 유지보수에 비용이 드는 세 곳에서 드러납니다. 프롬프트(모델에 각 형태를 가르쳐야 함), 재시도 정책(서로 다른 출처가 실패 후 다르게 페이지네이션함), 그리고 오류 envelope(한 플랫폼의 unauthorized 응답이 다른 플랫폼의 것과 전혀 닮지 않음)입니다.

우리는 우리 자신의 데모 에이전트가 추론 대신 형태 곡예에 대부분의 토큰을 쓰는 모습을 지켜봤고, 올바른 해결책은 에이전트가 아니라 게이트웨이에 있다고 결정했습니다.

UnifAPI envelope

우리가 노출하는 모든 HTTP 엔드포인트는, 모든 플랫폼에 걸쳐, 같은 외부 형태를 반환합니다: { request_id, data, pagination?, billing }. data 안의 필드는 플랫폼별입니다 — TikTok 동영상에는 해시태그가, Reddit 게시물에는 서브레딧이 있습니다 — 하지만 그 주위의 모든 것은 일관됩니다.

오류는 닫힌 어휘로 수렴합니다. 각각은 사람이 읽을 수 있는 메시지와 기계가 읽을 수 있는 type을 담습니다. 모델은 플랫폼별 텍스트를 인식할 필요 없이 type에 따라 분기할 수 있습니다.

우리가 사용하는 리셰이프 패턴

공개 플랫폼을 하나의 envelope 뒤에 표준화한다는 것은 우리의 리셰이프 레이어가 플랫폼당 수백 줄이라는 뜻입니다. 세 가지 패턴이 지배적입니다.

커서 통합 — 모든 플랫폼의 페이지네이션 토큰(max_cursor, after, nextPageToken, end_cursor, page)이 pagination.cursor가 됩니다. 우리는 출처가 제공하는 어떤 신호로부터든 has_more를 계산합니다(length === limit, 명시적 has_more 플래그, null인 next-cursor).

필드 평탄화 — 출처가 데이터를 세 단계 깊이로 중첩할 때(data.data.children.data, 너 말이야 Reddit), 우리는 이를 최상위 data[]로 끌어올립니다. 모델은 중간 envelope를 결코 보지 않습니다. record를 봅니다.

방어적 파싱 — 공개 플랫폼은 예고 없이 필드 타입을 바꿉니다(count가 문자열이 되고, 배열이 단일 항목이 되고, 타임스탬프가 null이 됨). 리셰이프 레이어는 각 필드를 선언된 타입으로 강제 변환하고, 필수 필드가 빠진 경우에만 record를 버립니다. 그 규율은 원시 패스스루에서 우리가 봤던 대부분의 조용한 실패를 잡아냅니다.

이를 건너뛰면 무엇이 깨지는가

envelope 없이는, 규모가 커지면 두 가지가 잘못됩니다. 첫째, 당신의 에이전트 프롬프트가 플랫폼 수에 따라 선형으로 늘어납니다 — 모든 새 플랫폼이 그 응답 형태를 설명하는 단락을 추가합니다. 플랫폼 10개에 이르면, 프롬프트가 호출에서 가장 느린 부분이 됩니다.

둘째, 당신의 재시도와 페이지네이션 코드가 곱셈적으로 늘어납니다. 각 출처별 특이점이 서로의 특이점과 상호작용하고, "조건 Y에서 플랫폼 X에 대해 retry-after-cursor가 작동하는가"의 행렬이 폭발합니다. 일찍 정규화하지 않는 팀은 결국 버그가 생긴 뒤 늦게 정규화 레이어를 작성하게 됩니다.

다음은 무엇인가

현재 envelope는 리스트형 엔드포인트를 깔끔하게 커버합니다. 우리가 작업 중인 다음 반복은 스트리밍과 웹훅 형태의 출처를 커버합니다 — 응답이 일회성 { data: [...] }가 아니라 시간에 걸친 일련의 이벤트인 곳입니다. 우리는 프롬프트 변경이 최소가 되도록, 에이전트 쪽에서 비동기 이터레이터처럼 느껴지게 형태를 잡고 있습니다.

오늘 다중 플랫폼 에이전트를 구축하고 있고 실제로 envelope가 어떻게 펼쳐지는지 보고 싶다면, unifapi.com/skills의 Skill에서 시작하거나 unifapi.com/openapi.json에서 OpenAPI 스펙을 검사하세요 — 모든 엔드포인트, 모든 필드, 하나의 형태입니다.

다음에 읽을 글

MCP 카탈로그 도구 설계 - 에이전트가 이 envelope를 반환하는 작업을 어떻게 발견하는지 보여줍니다.

UnifAPI vs RapidAPI - 정규화를 비교 지점으로 사용합니다.

OpenAPI 스펙 - 산문 뒤의 실시간 스키마를 노출합니다.