How to Implement a Custom Bot Adapter for Maka
Implement the ExternalSessionAdapter interface, expose a constructor accepting an options object, and register the adapter in the ExternalSessionAdapterRegistry to enable Maka to read, write, and list sessions from any custom bot.
Maka treats any bot capable of reading, writing, or listing chat-like sessions as an External Session Adapter. According to the apache/maka source code, the core architecture resides in the @maka/core package (imported as @maka/core/external-session) and wires into the runtime through a centralized registry. By implementing a custom bot adapter, you can integrate proprietary LLM services, internal chatbots, or third-party APIs into Maka's session handling pipeline without modifying core framework logic.
Understanding the External Session Adapter Architecture
The adapter architecture follows a three-tier pattern that decouples session storage from the importer logic.
First, your custom implementation adheres to the ExternalSessionAdapter interface defined in @maka/core/external-session. Second, the ExternalSessionAdapterRegistry (created via createExternalSessionAdapterRegistry) maintains an array of available adapters. Finally, the ExternalSessionImporter consumes this registry at runtime to route session operations to the appropriate adapter.
┌─────────────────────┐
│ Custom Bot Adapter │ (implements ExternalSessionAdapter)
└───────┬─────────────┘
│
▼
┌─────────────────────┐
│ ExternalSessionAdapterRegistry │ (holds an array of adapters)
└───────┬─────────────┘
│
▼
┌─────────────────────┐
│ ExternalSessionImporter │ (loads sessions via the registry)
└─────────────────────┘
Reference implementations such as OpenCodeSessionAdapter, CodexSessionAdapter, and ClaudeCodeSessionAdapter demonstrate the required shape. The OpenCodeSessionAdapter source in packages/storage/src/opencode-session-adapter.ts provides the most concrete baseline for new implementations.
Implementing the ExternalSessionAdapter Interface
A valid custom bot adapter must implement five core methods: listSessions(), readSession(), writeSession(), deleteSession(), and optional metadata getters. All methods return Promises and operate on SessionMetadata and SessionMessage types.
Create a new file (e.g., my-bot-adapter.ts) and implement the interface as follows:
import type {
ExternalSessionAdapter,
SessionMetadata,
SessionMessage,
ExternalSessionError,
} from '@maka/core/external-session';
export interface MyBotAdapterOptions {
/** Base URL of the bot service */
apiUrl?: string;
/** Optional auth token (do NOT hard‑code it) */
authToken?: string;
/** Maximum number of messages to keep per session */
maxMessages?: number;
}
/** Simple in‑memory example – replace with real API calls */
export class MyBotAdapter implements ExternalSessionAdapter {
private readonly options: Required<MyBotAdapterOptions>;
constructor(options: MyBotAdapterOptions = {}) {
this.options = {
apiUrl: options.apiUrl ?? 'https://api.mybot.example',
authToken: options.authToken ?? '',
maxMessages: options.maxMessages ?? 100,
};
}
/** List all stored session ids */
async listSessions(): Promise<SessionMetadata[]> {
// TODO: replace with real HTTP request
return []; // placeholder
}
/** Read a session by its id */
async readSession(id: string): Promise<SessionMessage[]> {
// TODO: fetch from bot service, transform to SessionMessage[]
return [];
}
/** Write a full session (overwrite) */
async writeSession(
id: string,
messages: SessionMessage[],
): Promise<void> {
// TODO: POST messages to the bot service (respect maxMessages)
}
/** Delete a session */
async deleteSession(id: string): Promise<void> {
// TODO: DELETE request to the bot service
}
/** Optional – provide human‑readable metadata */
async getMetadata(id: string): Promise<SessionMetadata> {
return {
id,
name: `MyBot Session ${id}`,
cwd: '',
};
}
}
Key implementation requirements:
- Async returns: All interface methods must return Promises to allow the runner to interact uniformly with any bot.
- Options object: Accept a typed configuration object (e.g.,
MyBotAdapterOptions) containing API endpoints, authentication tokens, or filesystem paths rather than hard-coding values. - Error handling: Throw
ExternalSessionError(or a subclass) for recoverable failures; propagate unexpected errors to allow Maka to surface useful diagnostics.
Registering Your Custom Bot Adapter
After implementing the interface, register the adapter in the global registry to make it discoverable by the importer. Modify packages/storage/src/external-session-adapters.ts to include your adapter in the array passed to new ExternalSessionAdapterRegistry().
import { MyBotAdapter, type MyBotAdapterOptions } from './my-bot-adapter.js';
import { ExternalSessionAdapterRegistry } from '@maka/core/external-session';
// Existing adapters …
import { OpenCodeSessionAdapter, type OpenCodeSessionAdapterOptions } from './opencode-session-adapter.js';
export function createExternalSessionAdapterRegistry(
options: {
opencode?: OpenCodeSessionAdapterOptions;
myBot?: MyBotAdapterOptions; // ← new options
} = {},
): ExternalSessionAdapterRegistry {
return new ExternalSessionAdapterRegistry([
// keep existing adapters
new OpenCodeSessionAdapter(options.opencode),
// add the custom bot adapter
new MyBotAdapter(options.myBot),
]);
}
The registry factory pattern ensures that Maka's ExternalSessionImporter can locate and instantiate your adapter at runtime based on the configuration provided.
Using the Adapter in Production
Once registered, consume the adapter through the ExternalSessionImporter class. The importer automatically routes session operations to the correct adapter based on the session ID and registry configuration.
import { createExternalSessionAdapterRegistry } from '@maka/storage';
import { ExternalSessionImporter } from '@maka/storage';
// Create a registry that includes the custom bot
const registry = createExternalSessionAdapterRegistry({
myBot: { apiUrl: 'https://api.mybot.example', authToken: process.env.MY_BOT_TOKEN },
});
// Import a session (e.g., by id) – the importer will route to the correct adapter
const importer = new ExternalSessionImporter(registry, { cwd: '/some/project' });
const session = await importer.importSession('my-bot-session-123');
console.log(session.messages);
Error Handling and Best Practices
Follow these patterns to ensure compatibility with Maka's test suites and future updates:
- Throw specific errors: Use
ExternalSessionErrorfor expected failure modes (network timeouts, authentication failures) to enable Maka's error recovery logic. - Validate options: Enforce required configuration inside the constructor and provide sensible defaults for optional parameters.
- Test coverage: Model your test suite after
packages/storage/src/__tests__/opencode-session-adapter.test.ts, which exercises all adapter methods against mock data to verify compatibility. - Session metadata: Always return consistent
SessionMetadataobjects containingid,name, andcwdfields to ensure the UI can display session information correctly.
Summary
- Implement
ExternalSessionAdapter: Provide async methods forlistSessions,readSession,writeSession, anddeleteSessionin a new class file. - Accept configuration: Design the constructor to receive a typed options object for API URLs, tokens, and limits.
- Register in factory: Add your adapter instance to the array in
createExternalSessionAdapterRegistryinsideexternal-session-adapters.ts. - Handle errors properly: Throw
ExternalSessionErrorfor operational failures to integrate with Maka's diagnostic system. - Test thoroughly: Use the existing
opencode-session-adapter.test.tspattern to validate your implementation against mock data.
Frequently Asked Questions
What methods are required to implement a custom bot adapter for Maka?
You must implement four core methods from the ExternalSessionAdapter interface: listSessions() to retrieve available sessions, readSession(id) to fetch message arrays, writeSession(id, messages) to persist data, and deleteSession(id) to remove sessions. An optional getMetadata(id) method provides human-readable session information for the UI.
Where do I register a new custom bot adapter in the Maka codebase?
Register the adapter in packages/storage/src/external-session-adapters.ts inside the createExternalSessionAdapterRegistry function. Import your adapter class, add its options to the function's parameter type, and instantiate it in the array passed to new ExternalSessionAdapterRegistry().
How does Maka route session operations to the correct custom adapter?
The ExternalSessionImporter class consumes the ExternalSessionAdapterRegistry, which holds all registered adapters. When you call importSession(), the importer queries the registry to locate the appropriate adapter instance and delegates the read or write operation to it.
Can I use environment variables to configure my custom bot adapter?
Yes. Pass environment variables through the options object in createExternalSessionAdapterRegistry. For example, provide authToken: process.env.MY_BOT_TOKEN in the options object when instantiating your adapter, keeping sensitive credentials out of source code while maintaining runtime configurability.
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 →