DEV Community

Cover image for OpenAPI로 AI 에이전트 툴 연동: 수동 래퍼 작성 없이
Rihpig
Rihpig

Posted on Originally published at apidog.com

OpenAPI로 AI 에이전트 툴 연동: 수동 래퍼 작성 없이

대부분의 에이전트 코드베이스에는 아무도 유지보수하고 싶어 하지 않는 파일이 있습니다. 40개의 도구 정의와, 이미 다른 곳에 존재하는 스키마를 수기로 옮긴 JSON 스키마가 들어 있는 파일입니다. API 팀이 필수 필드와 스펙을 업데이트해도, 누군가 400 오류를 발견하기 전까지 에이전트는 이전 페이로드를 계속 전송합니다.

지금 Apidog를 사용해 보세요

모든 엔드포인트에 대한 기계 판독 가능한 설명은 이미 있습니다. 바로 OpenAPI 문서입니다. 이 문서를 모델이 호출할 수 있는 도구 정의로 변환하고, 두 가지를 자동으로 동기화하면 수동 관리와 기억에 의존하는 문제를 줄일 수 있습니다.

이 가이드에서는 다음을 다룹니다.

  • OpenAPI 작업을 도구 스키마로 매핑하는 방법
  • 생성기에서 수정해야 할 스키마 요소
  • 수백 개의 엔드포인트를 모델이 추론할 수 있는 규모로 줄이는 방법
  • 생성된 도구를 테스트하는 방법

스택의 더 앞단에 있다면 여전히 API 도구가 필요한가에 대한 글에서 더 넓은 맥락을 확인할 수 있습니다.

Apidog가 중요한 이유는 간단합니다. 원본 스펙이 정확해야 그 스펙에서 생성되는 도구도 정확할 수 있습니다. 도구 정의는 나타납니다.

정의가 어긋납니다

스펙은 코드나 API 팀이 관리하고, 도구 파일은 에이전트 개발자가 관리합니다. 둘을 연결하는 자동화가 없으면 조용히 서로 달라집니다. 첫 증상은 에이전트가 "갑자기" 작동하지 않는 것입니다.

설명이 부실해집니다

40개의 스키마를 수동으로 작성하면 뒤쪽 도구의 설명은 한 줄로 줄어들기 쉽습니다. 모델은 설명을 바탕으로 도구를 선택하므로, 부실한 설명은 선택 정확도를 직접 떨어뜨립니다. 에이전트를 위한 도구 스키마 설계에서 문구가 중요한 이유를 자세히 다룹니다.

오류가 런타임까지 드러나지 않습니다

API가 정수를 요구하는데 수동 스키마에 문자열로 정의되어 있다면, 에이전트가 프로덕션에서 처음 호출할 때 422 오류가 발생합니다.

스펙에서 도구를 생성하면 세 문제가 한 번에 줄어듭니다.

  • 진실 공급원은 하나입니다.
  • 설명은 문서의 설명과 일치합니다.
  • 타입은 서버가 검증하는 스키마와 일치합니다.

OpenAPI 작업을 도구로 매핑하기

매핑은 생각보다 직접적입니다. 다음 OpenAPI 작업을 예로 들어보겠습니다.

paths:
  /orders/{orderId}/refund:
    post:
      operationId: refundOrder
      summary: 주문 환불
      description: >
        완료된 주문에 대해 전체 또는 부분 환불을 처리합니다.
        환불은 취소할 수 없습니다. 부분 환불은 남은 환불 가능 잔액보다
        크지 않은 금액이 필요합니다.
      parameters:
        - name: orderId
          in: path
          required: true
          schema: { type: string }
          description: 환불할 주문.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [reason]
              properties:
                amount:
                  type: integer
                  description: 센트 단위의 금액. 전체 환불의 경우 생략.
                reason:
                  type: string
                  enum: [duplicate, fraudulent, requested_by_customer]

Enter fullscreen mode Exit fullscreen mode

생성되는 도구 정의는 다음과 같습니다.

{
  "name": "refundOrder",
  "description": "완료된 주문에 대해 전체 또는 부분 환불을 처리합니다. 환불은 취소할 수 없습니다. 부분 환불은 남은 환불 가능 잔액보다 크지 않은 금액이 필요합니다.",
  "input_schema": {
    "type": "object",
    "required": ["orderId", "reason"],
    "properties": {
      "orderId": { "type": "string", "description": "환불할 주문." },
      "amount": { "type": "integer", "description": "센트 단위의 금액. 전체 환불의 경우 생략." },
      "reason": { "type": "string", "enum": ["duplicate", "fraudulent", "requested_by_customer"] }
    }
  }
}

Enter fullscreen mode Exit fullscreen mode

대부분의 매핑은 다음 네 가지 규칙으로 처리할 수 있습니다.

  • operationId를 도구 이름으로 사용합니다. 값이 없으면 메서드와 경로에서 안정적인 이름을 생성하고, 스펙 자체에 operationId를 추가하십시오.
  • 경로, 쿼리, 본문 매개변수를 하나의 속성 객체로 평면화합니다. 모델은 값이 어디로 전송되는지 신경 쓰지 않지만 실행기는 알아야 하므로, 매개변수 위치를 기록한 보조 테이블을 유지합니다.
  • summarydescription을 결합해 도구 설명을 만듭니다. summary만으로는 도구 선택에 필요한 맥락이 부족한 경우가 많습니다.
  • 경로와 본문의 필수 배열을 병합합니다. 필수 경로 매개변수와 필수 본문 필드는 하나의 required 목록에 들어갑니다.

실행기는 다음처럼 작게 유지할 수 있습니다.

def execute(tool_name, args, spec_index, http):
    op = spec_index[tool_name]          # 메서드, 경로 템플릿, 매개변수 위치
    path = op.path
    query, body = {}, {}

    for name, value in args.items():
        location = op.locations[name]   # "path" | "query" | "header" | "body"
        if location == "path":
            path = path.replace("{" + name + "}", str(value))
        elif location == "query":
            query[name] = value
        elif location == "body":
            body[name] = value

    return http.request(op.method, path, params=query, json=body or None)

Enter fullscreen mode Exit fullscreen mode

이 코드가 OpenAPI와 도구 호출을 연결하는 전체 브리지입니다. 나머지는 생성 과정에서 스키마를 정리하는 작업입니다.

생성기에서 수정해야 할 사항

스펙을 도구 스키마로 그대로 덤프하면 모델이 사용하기 어려운 도구가 만들어집니다. 다음 다섯 가지를 처리하십시오.

$ref 포인터 해결

대부분의 도구 호출 API는 JSON Schema의 일부만 지원하며, components의 참조를 직접 따라가지 않습니다. 참조를 인라인화하십시오.

단, 재귀 스키마는 무한히 확장될 수 있습니다. 고정된 깊이에서 재귀를 중단하고, 더 깊은 구조는 산문으로 설명하십시오.

지원되지 않는 키워드 제거

oneOf, allOf, discriminator, nullable은 스펙에서는 흔하지만 도구 스키마에서는 제대로 지원되지 않을 수 있습니다.

  • allOf: 속성을 병합해 단순화합니다.
  • oneOf: 지배적인 변형 하나를 선택하거나, 각 형태를 별도의 도구로 분리합니다.

후자의 방식이 도구 선택을 더 명확하게 만드는 경우가 많습니다.

깊은 중첩 평면화

세 단계 이상 중첩된 본문은 모델이 올바르게 채우기 어렵습니다. 예를 들어 customer.address.postal_code처럼 중첩된 주문 생성 페이로드는 더 평평한 도구 입력으로 노출하고, 실행기에서 원래 중첩 구조로 재조립하는 방식을 고려하십시오.

응답 스키마 제거

도구 정의는 입력을 설명합니다. 전체 응답 스키마까지 포함하면 컨텍스트만 낭비합니다. 응답 구조는 호출 결과를 처리할 때 중요하며, 이는 에이전트의 컨텍스트 창 내에서 API 응답 유지하기에서 다루는 별도의 문제입니다.

안전 플래그 전달

쓰기 작업은 실행기가 승인 게이트로 보낼 수 있도록 표시해야 합니다. 스펙에서 x-agent-requires-approval 같은 확장을 사용한다면 생성기가 이를 읽고 보존해야 합니다. AI 에이전트 가드레일 패턴과 함께 적용할 수 있습니다.

모델에 200개의 엔드포인트를 모두 제공하지 마십시오

실제 문제는 변환 자체보다 도구의 양입니다. 성숙한 API에는 수백 개의 작업이 있을 수 있습니다. 이를 모두 도구 목록에 넣으면 다음 문제가 발생합니다.

  1. 작업을 시작하기도 전에 컨텍스트가 스키마로 채워집니다.
  2. 모델이 비슷한 작업 사이에서 선택해야 하므로 정확도가 떨어집니다.

다음 세 가지 방법을 효과가 큰 순서대로 적용하십시오.

태그로 필터링

OpenAPI 작업의 태그는 일반적으로 제품 영역과 연결됩니다. 환불 에이전트라면 admin이나 analytics보다 orderspayments가 필요합니다. 한 줄짜리 필터만으로도 도구 표면을 크게 줄일 수 있습니다.

허용 목록 큐레이션

에이전트가 호출할 수 있는 작업을 operationId 목록으로 정의하고 해당 작업만 생성하십시오. 이는 보안 제어이기도 합니다. 도구가 없는 엔드포인트는 에이전트가 실수로 호출할 수 없습니다. AI 에이전트가 API를 파괴하는 것을 막기에서도 이처럼 좁은 표면을 권장합니다.

필요할 때 도구 검색 사용

API가 매우 크다면 작업을 인덱싱하고 현재 요청에 필요한 도구만 턴마다 선택할 수 있습니다. 다만 검색 단계에는 별도의 실패 모드가 있으므로, 필터링과 허용 목록만으로 부족할 때 사용하십시오.

프로토콜 수준의 대안도 있습니다. Model Context Protocol은 서버가 클라이언트에 도구를 노출하는 방식을 표준화합니다. OpenAPI 문서를 지원하는 MCP 서버를 사용하면 프레임워크별 통합 대신 하나의 통합 지점을 제공할 수 있습니다.

MCP가 무엇인지에서 개념을, Apidog로 MCP 서버 구축하기에서 구현 방법을 확인할 수 있습니다.

스펙을 먼저 정확하게 만드십시오

생성은 품질 문제를 상류로 이동할 뿐입니다. OpenAPI 설명이 모호하면 도구 설명도 모호해지고, 모델은 잘못된 엔드포인트를 선택합니다. 서버가 실제로 요구하는 필드를 선택 사항으로 표시하면 첫 호출부터 검증 오류가 발생합니다.

생성 전에 다음 기준으로 스펙을 감사하십시오.

  • 모든 작업에 operationId가 있고 동사 + 명사 형태로 읽힙니다.
  • 모든 작업에 무엇을 하고, 무엇을 변경하며, 언제 사용하지 않아야 하는지 설명이 있습니다. "사용자 삭제"보다 "사용자와 모든 세션을 영구적으로 삭제합니다. 되돌릴 수 없습니다. 일시적으로 접근을 비활성화하려면 deactivateUser를 사용하십시오."가 적절합니다.
  • 모든 매개변수 설명에 단위와 형식이 포함됩니다. amount보다 "센트 단위 금액, 최소 50"이 명확합니다.
  • 열거형은 설명이 아니라 enum으로 선언되어 모델이 닫힌 값 집합을 사용합니다.
  • 필수 항목이 정확하게 표시되어 런타임 검증에 의존하지 않습니다.

이는 일반적인 스펙 위생이지만 효과는 두 배입니다. 같은 텍스트가 공개 문서도 구동하기 때문입니다. Apidog에서는 스펙, 문서, 모의 서버, 테스트를 하나의 프로젝트에서 관리할 수 있습니다. 설명을 명확하게 만들면 모든 산출물이 함께 개선됩니다.

생성된 도구를 시간이 지나도 정직하게 유지하려면 Apidog에서 API 버전 관리도 함께 적용하십시오.

도구 세트를 공유하고 복사하지 마십시오

생성된 도구 세트도 구성입니다. 한 개발자의 체크아웃에만 구성이 있으면 수동 스키마와 같은 방식으로 어긋납니다.

다음 항목을 공유 아티팩트로 관리하고 원본 스펙 옆에서 버전 지정하십시오.

  • 태그 필터
  • 허용 목록
  • 고정된 스펙 버전

일부 플랫폼은 이를 기본 단위로 제공합니다. Sharkly에서는 에이전트가 일회성 프롬프트가 아니라 저장된 작업 구성입니다. 지침, 런타임, 스킬, 저장소, 실행 설정을 함께 이동하고 Space 전체에서 공유할 수 있으므로, 작동하는 도구 설정을 팀이 재사용할 수 있습니다.

런타임은 여전히 Claude Code, Codex 또는 이미 사용 중인 다른 도구일 수 있습니다. 달라지는 점은 주변 구성이 로컬에만 머물지 않는다는 것입니다.

생성된 도구 테스트

생성된 도구는 수동 도구와 다른 방식으로 실패합니다. 따라서 호출뿐 아니라 생성 과정도 테스트해야 합니다.

1. 스키마 왕복 검사

각 도구의 스키마에서 유효한 예제를 생성해 서버로 전송하십시오. 400 또는 422가 반환되면 도구 스키마와 서버 검증이 일치하지 않는 것입니다. 이때는 스펙을 수정해야 합니다.

2. 도구 선택 테스트

알려진 정답 도구가 있는 작은 작업 프롬프트 세트를 만들고 실행하십시오. 모델이 선택한 도구 이름을 기록하면, 도구 이름 변경이나 설명 축소로 인한 회귀를 빠르게 감지할 수 있습니다.

출력은 비결정적이므로 정확한 인수보다 도구 이름을 검증하십시오. 자세한 방법은 비결정적 AI 에이전트 테스트를 참고하십시오.

3. 모의 환경에서 실행

실제 시스템에 연결하기 전에 모의 환경에서 에이전트를 실행하십시오. 동일한 스펙으로 생성된 모의 서버는 부작용 없이 실제와 유사한 응답을 제공합니다. 재시도 로직이 처리해야 하는 500 오류와 타임아웃도 주입할 수 있습니다.

마무리

스펙은 계약이며, 도구 목록은 수동으로 관리하는 병렬 복사본이 아니라 그 계약의 투영이어야 합니다.

다음 순서로 적용하십시오.

  1. OpenAPI에서 도구를 생성합니다.
  2. 태그와 허용 목록으로 도구를 엄격하게 필터링합니다.
  3. 설명과 필수 필드를 정확하게 유지합니다.
  4. 스키마 왕복, 도구 선택, 모의 환경 실행을 테스트합니다.
  5. 스펙과 도구 설정을 버전 관리합니다.

먼저 OpenAPI 문서를 내보내고 설명이 없는 작업의 수를 세어 보십시오. 그 숫자가 신뢰할 수 있는 에이전트 도구를 만들기 위해 해결해야 할 작업량입니다.

스펙, 모의 서버, 테스트를 한 곳에서 관리하려면 Apidog를 다운로드하십시오.

자주 묻는 질문

Swagger 2.0 문서에서 도구를 생성할 수 있습니까?

가능하지만 먼저 OpenAPI 3.x로 변환하십시오. 2.0의 본문 모델은 생성기가 일관되게 처리하기 어려울 만큼 다르며, 현재 도구는 3.x를 대상으로 합니다. 차이점은 OpenAPI Specification 저장소에 문서화되어 있습니다.

모델이 한 번에 처리할 수 있는 도구 수는 얼마입니까?

기술적 한계에 도달하기 훨씬 전에 정확도가 떨어집니다. 실제 상한은 보통 수십 개입니다. 그보다 많은 도구가 필요하다면 태그 필터링이나 허용 목록 큐레이션이 필요하다는 신호로 보십시오.

도구 이름이 operationId와 정확히 일치해야 합니까?

operationId가 읽기 좋은 이름이라면 일치시키는 것이 좋습니다. 도구 호출에서 스펙 작업으로 직접 조회할 수 있어 추적과 디버깅이 쉬워집니다. 이름이 좋지 않다면 생성기에서 임의로 바꾸지 말고 스펙에서 수정하십시오.

GraphQL API에는 어떻게 적용합니까?

같은 아이디어를 적용할 수 있습니다. 스키마를 인트로스펙션하고 쿼리나 뮤테이션마다 하나의 도구를 생성하십시오. GraphQL은 더 넓은 표면을 노출하므로 도구 수 문제가 더 심각하며, 필터링이 특히 중요합니다.

여전히 도구를 수동으로 작성해야 합니까?

일부는 그렇습니다. 여러 호출을 하나의 작업으로 연결하는 복합 도구나 HTTP 이외의 시스템을 감싸는 도구는 수동 구현이 필요할 수 있습니다. 핵심은 일상적인 단일 엔드포인트 래퍼를 수작업으로 작성하지 않는 것입니다.

테스트 중 에이전트가 쓰기 엔드포인트를 호출하지 못하게 하려면 어떻게 합니까?

HTTP 메서드로 필터링해 읽기 전용 도구 세트를 만들고, 쓰기 작업은 모의 환경으로 연결하십시오. 자세한 설정은 에이전트가 프로덕션이 아닌 모의 환경을 사용해야 하는 이유를 참고하십시오.

Top comments (0)