top of page

One Command, Done: Integrating Air API with a ClawHub Plugin

  • 6 days ago
  • 5 min read


Hi,I’m CY Lee from the DevOps/SRE team.


With the launch of Air API, we’ve been building out our internal infrastructure monitoring system. Along the way, we developed an OpenClaw plugin—and in this post, I’d like to walk you through what we built and why it matters. 🙂



Before We Start


If you’ve used OpenClaw for a while, you’ve probably experienced something like this at least once. The moment you try to connect an external model provider, you find yourself going through the settings menu, copying and pasting the Base URL, and manually registering endpoints for each model. It works—but the setup process isn’t exactly pleasant.


In this post, I’ll walk through how the plugin we built removes all of that repetition with a single plugins install command. And then we’ll also take a look at what’s actually happening in the code behind it.


The Old Way: Custom Provider, Repeated Per Model


As shown below, previously you had to manually register a Custom Provider to connect OpenClaw with Air API. You would go into the settings, enter the API Base URL, paste the API key, and save—then one model is connected.


Manually entering the API Base URL in the OpenClaw settings screen
Manually entering the API Base URL in the OpenClaw settings screen

















This is where the problem begins. Since Air API uses different endpoints per model, if you want to use both qwen3.5-9b and qwen3.5-35b-a3b, you have to repeat the same process twice. If you need a third model, you repeat it again.

In other words, the setup effort increases in proportion to the number of models you want to use. This becomes an unpleasant bottleneck for anyone using OpenClaw.



The New Way: One Plugin, One Command


To remove this repetitive setup, the Air API team chose a different approach.


We packaged the entire provider configuration into a ClawHub plugin and distributed it under the name: @aieev/openclaw-airapi-provider

Now, from the user’s perspective, setup is just a single terminal command:


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

Once installed, OpenClaw automatically recognizes the plugin during onboarding. In the Model / Auth provider selection step, AirAPI appears alongside the built-in options.

There are no fields to fill out, and no need to search for endpoints.

Model-specific URL routing is handled inside the plugin. The user only selects a model, and the plugin takes care of where the request goes.


Inside the Plugin: A Provider Built in a Single File


One interesting aspect of this plugin is that all logic is contained in a single file: index.ts .

Provider registration, model catalog, authentication setup, and onboarding presets are all defined within this one file.


Static Model Catalog: Embedding Endpoints in Code


The core of the plugin is the KNOWN_RUNTIME_MODELS map. It uses model IDs as keys, and each model’s metadata and unique Base URL as values.


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;

One important detail is that the Base URLs differ between models.


For example:

  • qwen3.5-9b points to a dedicated GPU endpoint

  • qwen3.5-35b-a3b uses a default runtime URL


If this were done manually, users would have to look up and copy each URL individually. Here, everything is centrally managed in code.



Plugin Entry: definePluginEntry


The plugin entry point is defined using definePluginEntry from the OpenClaw plugin SDK.

Inside the register callback, calling api.registerProvider registers the provider with 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) => { /* ... */ }
    });
  }
});

With a single registerProvider call, authentication, catalog, and model resolution logic are all defined. No separate configuration files or external dependencies are required.


Authentication: One API Key Is Enough


Authentication is implemented using createProviderApiKeyAuthMethod. During onboarding, it appears under the "AirAPI" group. When the user enters the API key, applyConfig registers both models at once in the OpenClaw configuration. Inside applyConfig, the plugin iterates through SUPPORTED_AIRAPI_ONBOARD_MODELS and adds them to the allowlist.

From the user’s perspective, they only entered one API key—but internally, all supported models become available.



The Key Mechanism: normalizeResolvedModel


The most clever part of the plugin is normalizeResolvedModel. After OpenClaw resolves a model based on the default Base URL in the catalog, this function intercepts the request right before it is sent and replaces the Base URL with the correct endpoint for that model.


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 };
}

This is the core mechanism that solves the problem of "different endpoints per model."

The catalog only returns the list of models, and at request time, the plugin injects the correct Base URL from KNOWN_RUNTIME_MODELS.


From the user’s perspective, they simply enter: /model qwen/qwen3.5-9b

But behind the scenes, the request may be sent to a completely different endpoint.



Plugin Manifest: openclaw.plugin.json


In addition to the code, there is one more important file: openclaw.plugin.json.

This is a declarative manifest that the OpenClaw plugin loader reads. It defines supported models and authentication methods statically. Because of this, OpenClaw can understand what providers and models are supported even before executing the plugin code. However, the runtime logic in index.ts and this manifest must always stay in sync. When adding or removing models, both files need to be updated together.



Actual Setup Flow: Done in 4 Steps


Now that we’ve looked at the internal structure, let’s walk through the actual setup process from a user perspective.


Step 1 — Install the Plugin


Run the following command:


openclaw plugins install clawhub:@aieev/openclaw-airapi-provider
Terminal output showing the Air API plugin being downloaded from ClawHub
Terminal output showing the Air API plugin being downloaded from ClawHub

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



Step 2 — Select AirAPI


After restarting OpenClaw, AirAPI appears in the Model / Auth provider list.


Onboarding screen after plugin installation, where Air API appears as a new option under Model/Auth provider
Onboarding screen after plugin installation, where Air API appears as a new option under Model/Auth provider

At this point, the plugin’s register function runs and adds the provider via api.registerProvider.

The onboarding wizard reflects the plugin’s wizard.groupLabel: "AirAPI" setting in the UI.



Step 3 — Enter API Key


Once you select AirAPI and enter the API key, everything else is handled automatically.


Internally, applyConfig runs:

  • Both models are added to the allowlist

  • Default model is set to airapi/qwen/qwen3.5-35b-a3b



Step 4 — Switch Models


Now you can use:


/models

to check available models and switch between them anytime.



When switching models:

  • resolveDynamicModel finds the model in KNOWN_RUNTIME_MODELS

  • normalizeResolvedModel injects the correct endpoint


To the user, it looks like only the model name changes—but the request may be routed to a completely different server.


This post covered only the core logic, but if you’re interested in the full implementation, you can check it out directly in the GitHub repository.


Comparison: Before vs After



Before (Manual Setup)

After (Plugin)

Using 2 models

Register provider twice

Run command once

Endpoint management

Manual input

Handled by plugin

Adding models

Register again

Update plugin once

Switching models

Re-enter settings

/model command

URL routing

User-managed

Automatically handled by normalizeResolvedModel



Closing


What this post really tries to highlight is not just Air API itself, but the possibilities enabled by the ClawHub plugin architecture.


Whether it’s:

  • an internal LLM gateway

  • a fine-tuned model endpoint

  • a private API wrapper


If you package provider configuration into a plugin, anyone on your team can use it with a single command. As we saw above, the actual implementation only requires two files: index.ts and openclaw.plugin.json. If you’re building something on OpenClaw and have a provider integration worth sharing, it’s worth considering publishing it on ClawHub. You’ll quickly realize that a one-line install command is far better than a five-step manual setup.


Thanks for reading.





| Dev Team

| Author: CY Lee

| Site: Linkedin




*References


Blog
bottom of page