top of page

명령어 하나로 끝내는 Air API 연동: ClawHub 플러그인 이야기

  • 7일 전
  • 5분 분량


안녕하세요, 개발팀에서 DevOps/SRE를 담당하고 있는 이창윤입니다.

최근 Air API 출시와 함께 저희 팀은 인프라 모니터링 체계를 구축하고 있습니다. 이번 글에서는 그 과정에서 개발한 OpenClaw 플러그인을 소개하려고 합니다 🙂



시작하기 전에


OpenClaw를 한동안 써본 분이라면 한 번쯤 이런 상황을 겪어보셨을 겁니다. 외부 모델 프로바이더를 연결하려는 순간, 설정 메뉴를 뒤적이고 Base URL을 복사-붙여넣기 하고 사용할 모델마다 엔드포인트를 손으로 하나씩 등록하는 그 과정을요. 하다보면 동작은 하는데, 세팅이 유쾌하지는 않습니다.


이 글에서는 저희 팀이 개발한 플러그인을 통해 plugins install 명령어 하나가 이 모든 반복을 어떻게 없애는지를 소개해보도록 하겠습니다. 그리고 그 뒤에서는 실제로 무슨 코드가 돌아가는지까지도 함께 들여다보겠습니다.



기존 방식: Custom Provider, 모델마다 반복


아래 그림처럼, 기존에는 OpenClaw와 AirAPI를 연결하려면 Custom Provider를 직접 등록해야만 했습니다. 설정 화면으로 이동해서 API Base URL을 입력하고, API Key를 붙여넣고 저장하면 모델 1개가 연결됩니다.


OpenClaw 수동 설정 화면에서 API Base URL을 직접 입력하는 모습
OpenClaw 수동 설정 화면에서 API Base URL을 직접 입력하는 모습

















문제는 여기서 시작됩니다. AirAPI는 모델마다 엔드포인트가 다르기 때문에 만약 qwen3.5-9b와 qwen3.5-35b-a3b 두 모델을 함께 쓰고 싶다면 같은 과정을 두 번 반복해야 합니다. 그러다 세 번째 모델이 필요해지면 또 한 번 더 같은 과정을 진행해야 합니다. 이렇듯 설정의 번거로움은 쓰고 싶은 모델 수와 비례해서 늘어납니다. 이건 개발자든 일반 사용자든 OpenClaw를 쓰는 누구에게나 반갑지 않은 병목입니다.



새로운 방식: ClawHub 플러그인으로 한 번에


AirAPI 팀은 이런 반복 설정의 피로를 없애기 위해 새로운 방식을 택했습니다.


프로바이더 설정 전체를 ClawHub 플러그인으로 패키징하고, @aieev/openclaw-airapi-provider 이름으로 배포한 것입니다. 이제 사용자 입장에서 셋업은 터미널 명령어 딱 한 줄이면 됩니다.


openclaw plugins install clawhub:@aieev/openclaw-airapi-provider

설치가 완료되면 OpenClaw의 온보딩 화면이 플러그인을 자동으로 인식합니다. Model / Auth provider 선택 단계에서 기존 내장 옵션들 옆에 AirAPI가 자연스럽게 등장하죠. 직접 입력할 필드도, 엔드포인트를 찾아다닐 필요도 없습니다.

모델별 URL 라우팅은 플러그인 내부에서 처리됩니다. 사용자는 모델만 선택하면 되고, 어디로 요청이 가는지는 플러그인이 알아서 챙깁니다.


내부 들여다보기: 단일 파일로 완성되는 프로바이더


이 플러그인의 흥미로운 점은 모든 로직이 index.ts 한 파일에 들어간다는 것입니다. 프로바이더 등록, 모델 카탈로그, 인증 설정, 온보딩 프리셋까지 전부 다 이 파일에 담겨 있습니다.



정적 모델 카탈로그: 엔드포인트를 코드에 심는다


플러그인의 핵심은 KNOWN_RUNTIME_MODELS 맵입니다. 모델 ID를 키로, 각 모델의 메타데이터와 고유한 Base URL을 값으로 들고 있습니다.


const KNOWN_RUNTIME_MODELS = {
  "qwen/qwen3.5-9b": {
    baseUrl: "https://ap-1.aieev.cloud/ac/7/qwen3-5-9b-fp8-5090-2/v1",
    cost: { input: 0.05, output: 0.15},
    // ...
  },
  "qwen/qwen3.5-35b-a3b": {
    baseUrl: https://ap-1.aieev.cloud/ac/7/qwen3-5-35b-a3b/v1,
    cost: { input: 0.1623, output: 1.3},
    // ...
  }
}; as const;

눈여겨볼 포인트는 두 모델의 baseUrl이 서로 다르다는 점입니다. qwen3.5-9b는 전용 GPU 엔드포인트(qwen3-5-9b-fp8-5090-2)를 직접 가리키고, qwen3.5-35b-a3b는 디폴트 런타임 URL을 씁니다. 사용자가 이걸 수동으로 설정했다면 URL을 각각 찾아서 복사-붙여넣기를 했을테지만, 여기서는 코드 한 곳에서 깔끔하게 관리합니다.



플러그인 진입점: definePluginEntry


OpenClaw 플러그인 SDK가 제공하는 definePluginEntry로 진입점을 정의합니다. register 콜백 안에서 api.registerProvider를 호출하면 프로바이더가 OpenClaw에 등록됩니다.



export default definePluginEntry({
  id: "openclaw-airapi-provider",
  name: "AirAPI Provider for OpenClaw",
  description: "AirAPI provider plugin with a single airapi provider and per-model runtime endpoints",
  register(api) {
    api.registerProvider({
      id: PROVIDER_ID,
      label: "AirAPI",
      docsPath: "/providers/airapi",
      envVars: ["AIRAPI_API_KEY"],
      auth: [ /* ... */ ],
      catalog: { /* ... */ },
      resolveDynamicModel: async (ctx) => { /* ... */ },
      normalizeResolvedModel: (ctx) => { /* ... */ }
    });
  }
});

registerProvider 하나의 호출에 인증, 카탈로그, 모델 해석 로직이 모두 담깁니다. 별도 설정 파일이나 외부 의존성 없이 이 한 번의 등록이 곧 프로바이더 전체입니다.



인증: API Key 한 번이면 충분하다


인증 설정은 SDK의 createProviderApiKeyAuthMethod를 사용합니다. 온보딩 위저드에서 "AirAPI" 그룹으로 노출되고 사용자가 키를 입력하면 applyConfig가 OpenClaw 설정에 두 모델을 한꺼번에 등록해줍니다. applyConfig 안에서 SUPPORTED_AIRAPI_ONBOARD_MODELS를 순회하며 모델을 allowlist에 넣는 부분이 핵심입니다. 사용자 입장에서는 API Key 하나만 입력했지만 내부적으로는 지원 모델 전체가 사용 가능 상태로 전환됩니다.



모델 라우팅의 비밀: normalizeResolvedModel


플러그인에서 가장 영리한 부분은 normalizeResolvedModel입니다. OpenClaw가 카탈로그의 디폴트 Base URL을 기준으로 모델을 resolve하고 나면, 이 함수가 실제 요청이 나가기 직전에 가로채서 모델별로 정확한 엔드포인트 URL로 바꿔치기합니다.


normalizeResolvedModel: (ctx) => {
  const known = KNOWN_RUNTIME_MODELS[ctx.modelId as keyof typeof KNOWN_RUNTIME_MODELS];
  if (!known) return null;
  return { ...ctx.model, baseUrl: known.baseUrl };
}

이것이 "모델마다 엔드포인트가 다른" 문제를 푸는 핵심 메커니즘입니다. 카탈로그에서는 모델 목록만 반환하고, 실제 HTTP 요청 시점에 KNOWN_RUNTIME_MODELS에서 정확한 baseUrl을 꺼내 끼워 넣습니다. 사용자는 /model qwen/qwen3.5-9b만 입력하면 되고, 그 뒤에서 요청이 어느 엔드포인트로 가는지는 신경 쓰지 않아도 됩니다.



플러그인 매니페스트: openclaw.plugin.json


코드 외에 하나 더 중요한 파일이 있습니다. openclaw.plugin.json은 OpenClaw 플러그인 로더가 읽는 선언적 매니페스트로, 지원 모델 목록과 인증 방식을 정적으로 기술합니다. 이 매니페스트가 있기 때문에 OpenClaw는 플러그인 코드를 실행하기 전에도 어떤 프로바이더와 모델을 지원하는지 미리 알 수 있습니다. 단, index.ts의 런타임 로직과 이 매니페스트는 항상 동기화 상태를 유지해야 합니다. 모델을 추가하거나 제거할 때 양쪽 파일을 함께 수정해야 하는 것도 그 때문입니다.



실제 설정 흐름: 4단계로 끝내기


지금까지 플러그인의 구조를 코드 레벨에서 살펴봤다면, 이번에는 실제로 사용자 입장에서 어떻게 설치하고 연결하는지를 순서대로 따라가 보겠습니다.


1단계 — 플러그인 설치


터미널에서 아래 명령어를 실행합니다.


openclaw plugins install clawhub:@aieev/openclaw-airapi-provider
ClawHub에서 Air API 플러그인 내려받는 터미널 출력 화면
ClawHub에서 Air API 플러그인 내려받는 터미널 출력 화면

OpenClaw가 ClawHub에서 플러그인을 내려받아 로컬에 등록합니다.



2단계 — AirAPI 선택


OpenClaw를 재시작하면 Model / Auth provider 항목에 AirAPI가 새로 생겨 있습니다.


플러그인 설치 후 온보딩 화면(Model/auth provider)에 Air API가 새로 추가된 모습
플러그인 설치 후 온보딩 화면(Model/auth provider)에 Air API가 새로 추가된 모습

이 시점에 일어나는 일을 코드로 보면, 플러그인의 register 함수가 실행되면서 api.registerProvider를 통해 airapi 프로바이더가 OpenClaw의 프로바이더 목록에 추가됩니다. 온보딩 위저드의 wizard.groupLabel: "AirAPI" 설정이 UI에 그대로 반영되는 것입니다.


3단계 — API Key 입력


AirAPI를 선택하고 API Key만 입력하면 그 다음은 플러그인이 알아서 처리합니다. 내부적으로는 applyConfig가 실행되면서 qwen/qwen3.5-9bqwen/qwen3.5-35b-a3b 두 모델이 동시에 allowlist에 등록되고 디폴트 모델은 airapi/qwen/qwen3.5-35b-a3b로 설정됩니다.


4단계 — 모델 전환


이제부터는 /model 또는 /models 명령어로 대화 중 언제든 사용 가능한 AirAPI 모델 목록을 확인하고 원하는 모델로 즉시 전환할 수 있습니다.


/models

모델을 전환하면 resolveDynamicModelKNOWN_RUNTIME_MODELS에서 해당 모델을 찾아내고, normalizeResolvedModel이 그에 맞는 엔드포인트 URL을 끼워 넣습니다. 사용자 입장에서는 모델 이름만 바뀐 것처럼 보이지만, 뒤에서는 완전히 다른 서버로 요청이 날아가고 있을 수 있습니다.



이 글에서는 핵심 로직만 살펴봤지만, 전체 구현 코드가 궁금하신 분은 GitHub 저장소에서 직접 확인하실 수 있습니다.


비교: Before vs After: 한눈에 보기


4단계를 직접 따라가 보셨다면 체감이 되셨겠지만 이렇게 표로 비교해보면 그 차이가 더 명확합니다.


Before (수동 등록)

After (플러그인)

모델 2개 사용 시

프로바이더 2번 등록

명령어 1회 실행

엔드포인트 관리

직접 입력

플러그인이 처리

모델 추가 시

다시 등록

플러그인 업데이트 1회

모델 전환

설정 재진입

/model 명령어

URL 라우팅

사용자가 직접

normalizeResolvedModel이 자동 처리



마치며


사실 이 글에서 말하고 싶었던 건 Air API 하나가 아닙니다. ClawHub의 플러그인 구조가 열어주는 가능성에 관한 이야기입니다.


사내 LLM 게이트웨이든, 파인튜닝된 모델 엔드포인트든, 사설 API 래퍼든, 프로바이더 설정을 패키지로 만들어 두면 팀 누구든 명령어 한 줄로 바로 쓸 수 있습니다. 위에서 살펴본 것 처럼 실제로 필요한 파일은 index.tsopenclaw.plugin.json 두 개가 전부입니다. definePluginEntry  → registerProvider  → 정적 모델 맵, 이 흐름만 따라가면 어떤 OpenAI-compatible 엔드포인트든 ClawHub 플러그인으로 감쌀 수 있습니다.


"Base URL 여기다 붙여넣고 Custom Provider로 등록하세요" 라는 방식이 정말 최선일까요? OpenClaw 위에서 무언가를 만들고 있고, 팀과 공유할 만한 프로바이더 통합이 있다면 ClawHub 등록을 한 번 고민해 보세요. 명령어 한 줄짜리 설치가 다섯 단계짜리 수동 설정보다 낫다는 건 실행해보시면 바로 알 수 있습니다.


여기까지 긴 글 읽어주셔서 감사합니다.






| Dev Team

| Author: CY Lee

| Site: Linkedin




*참고 문서


Blog
bottom of page