How Model Adapters Are Integrated into Maka via AiSdkBackend: A Complete Technical Guide
Maka integrates model adapters through a three-layer backend architecture: AiSdkBackend orchestrates model creation, delegates to a model-factory.ts for provider selection, and uses model-adapter.ts to normalize specifications into concrete AI-SDK language models.
Maka's runtime abstracts every LLM interaction behind a unified Backend interface. When your workflow configuration sets the backend type to "ai-sdk", the system automatically wires requests through the AI‑SDK backend implemented in AiSdkBackend. This design enables seamless provider switching—OpenAI, Anthropic, Google, and others—without changing flow definitions.
Backend Registration and Entry Point
The AI‑SDK integration starts with backend registration. Maka registers the implementation under the key ai-sdk in src/ai-sdk-backend.ts.
When a flow step requires a language model, the runtime locates the registered backend and invokes its model creation method. This entry point shields the rest of the system from provider-specific details.
// Simplified conceptual flow
const backend = runtime.getBackend('ai-sdk'); // Resolves to AiSdkBackend instance
const model = backend.createModel(spec); // Delegates to factory + adapter chain
The Model Factory: Provider Selection
The backend delegates actual model instantiation to the model factory (packages/runtime/src/model-factory.ts). This factory reads the ModelSpec configuration—provider name, model ID, temperature, max tokens—and selects the appropriate creator from the corresponding @ai-sdk/* package.
The factory maintains a registry mapping provider identifiers to SDK-specific creation functions. When you specify provider: '@ai-sdk/openai' or provider: '@ai-sdk/anthropic', the factory resolves this to the correct import and initialization logic.
import { createModelFactory } from '@maka/runtime/model-factory';
import type { ModelSpec } from '@maka/runtime/model-protocol';
const factory = createModelFactory();
const spec: ModelSpec = {
backend: 'ai-sdk',
provider: '@ai-sdk/anthropic',
modelId: 'claude-3-5-sonnet-20240620',
temperature: 0.7,
};
const model = factory.build(spec); // Returns LanguageModelV4 instance
The Adapter Layer: Normalization and Capability Injection
packages/runtime/src/model-adapter.ts contains buildModelFromSpec, the critical bridge between generic configuration and concrete SDK types. This adapter performs three essential functions:
- Type erasure – Hides provider-specific SDK interfaces behind Maka's
LanguageModelabstraction - Option normalization – Converts temperature, maxTokens, and other parameters to SDK-expected formats
- Capability attachment – Adds Maka-specific features including telemetry hooks, usage tracking, and tool-call handling
The adapter ensures that regardless of which @ai-sdk provider you use, the resulting model behaves consistently within Maka's runtime.
Step Execution and Response Wrapping
When AiSdkBackend runs a workflow step, it:
- Invokes the adapter-produced model to generate responses
- Receives raw SDK output (text, tool calls, usage metadata)
- Wraps this output back into Maka's internal
Messageformat for downstream processing
This bidirectional translation—spec to SDK model, SDK response to internal message—happens transparently at the backend boundary.
Compaction and Usage Tracking
The backend forwards usage data to AI‑SDK compaction utilities in packages/runtime/src/ai-sdk-compaction.ts. This enables:
- Token-budget enforcement – Uniform budget tracking across all providers
- Response caching – Provider-agnostic caching strategies
- Cost attribution – Aggregated usage reporting for observability
Configuration Examples
JSON Workflow Configuration
{
"model": {
"backend": "ai-sdk",
"provider": "openai",
"modelId": "gpt-4o-mini",
"temperature": 0.7,
"maxTokens": 1024
}
}
Programmatic Backend Usage
import { AiSdkBackend } from '@maka/runtime/ai-sdk-backend';
import type { ModelSpec } from '@maka/runtime/model-protocol';
// Runtime-provided context (logging, telemetry, etc.)
const backend = new AiSdkBackend(context);
const spec: ModelSpec = {
backend: 'ai-sdk',
provider: '@ai-sdk/openai',
modelId: 'gpt-4o-mini',
temperature: 0.7,
};
// Internal: createModel uses factory + adapter
const lm = backend.createModel(spec);
const result = await lm.complete('Explain how model adapters work.');
console.log(result.text);
Key Source Files
| File | Purpose |
|---|---|
packages/runtime/src/ai-sdk-backend.ts |
AiSdkBackend class implementation; coordinates model creation, message conversion, usage tracking |
packages/runtime/src/model-factory.ts |
Creates language-model instances from ModelSpec; selects correct @ai-sdk provider |
packages/runtime/src/model-adapter.ts |
buildModelFromSpec function; normalizes spec, builds SDK model, adds Maka capabilities |
packages/runtime/src/model-protocol.ts |
TypeScript interfaces for ModelSpec and related types |
packages/runtime/src/ai-sdk-compaction.ts |
Token-budget compaction and usage reporting utilities |
Summary
- Backend abstraction –
AiSdkBackendregistered under keyai-sdkprovides the entry point - Factory pattern –
model-factory.tsresolves provider names to concrete@ai-sdk/*creators - Adapter normalization –
model-adapter.tstype-erases SDK differences and injects Maka capabilities - Unified interface – All providers expose identical
LanguageModelbehavior to workflow steps - Cross-cutting concerns – Compaction and usage tracking work uniformly via
ai-sdk-compaction.ts
Frequently Asked Questions
What is the relationship between AiSdkBackend and the model factory?
AiSdkBackend depends on the model factory as an internal implementation detail. When you call backend.createModel(spec), the backend delegates to createModelFactory().build(spec). This separation keeps the backend focused on orchestration while the factory handles provider-specific instantiation logic.
Can I use AiSdkBackend directly without the full Maka runtime?
Yes. Instantiate AiSdkBackend with a compatible context object containing logging and telemetry interfaces. However, most production use goes through the runtime's backend registry, which manages lifecycle and configuration loading automatically.
How does Maka handle provider-specific options like Anthropic's extended thinking?
The ModelSpec interface includes an extensible options field. The adapter in model-adapter.ts passes unrecognized options through to the underlying SDK after normalization. Provider-specific features work as long as the target @ai-sdk/* package supports them.
Why does model-adapter.ts type-erase the concrete SDK type?
Type erasure enables polymorphism. Workflow steps receive a LanguageModel interface without caring whether the underlying implementation is OpenAI, Anthropic, or another provider. This allows runtime provider switching and simplifies testing with mock implementations.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →