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.

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

OpenClaw가 ClawHub에서 플러그인을 내려받아 로컬에 등록합니다.
Step 2 — Select AirAPI
After restarting OpenClaw, AirAPI appears in the Model / Auth provider list.

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
