Zum Inhalt springen

Plugin SDK + Runtime: Die neue Architektur für Messaging Connector

Kennst du das? Du willst eine kleine Änderung am Core vornehmen, aber plötzlich funktionieren mehrere Integrationen nicht mehr. Direkte Imports aus internen Verzeichnissen machen Updates riskant und verhindern, dass externe Entwickler saubere Plugins bauen können. Dieser Wildwuchs an Patterns führt dazu, dass jede Erweiterung anders funktioniert und Upgrades zur Qual werden.

Wir lösen dieses Problem, indem wir Messaging Connector strikt vom Core entkoppeln. Jeder Connector wird zu einem Plugin, das ausschließlich über eine stabile API kommuniziert.

  • OpenClaw Core
  • TypeScript (für Typisierung)
  • openclaw/plugin-sdk
  • OpenClawConfig

In der neuen Architektur nutzt du zwei Layer, um Plugins zu bauen oder zu migrieren. Der wichtigste Punkt: Importiere niemals direkt aus src/**.

  1. Plugin SDK nutzen: Verwende openclaw/plugin-sdk für Typen wie ChannelPlugin oder Hilfsfunktionen für die Konfiguration.
  2. Runtime API verwenden: Greife auf Core-Funktionen nur über OpenClawPluginApi.runtime zu.
  3. Konfiguration validieren: Nutze buildChannelConfigSchema für deine Plugin-Einstellungen.
  4. Version festlegen: Deklariere eine benötigte Runtime-Version (z. B. openclawRuntime: ">=2026.2.0").

Hier ist die Definition der neuen Plugin-Runtime, die du für alle Interaktionen nutzt:

export type PluginRuntime = {
channel: {
text: {
chunkMarkdownText(text: string, limit: number): string[];
resolveTextChunkLimit(cfg: OpenClawConfig, channel: string, accountId?: string): number;
hasControlCommand(text: string, cfg: OpenClawConfig): boolean;
};
reply: {
dispatchReplyWithBufferedBlockDispatcher(params: {
ctx: unknown;
cfg: unknown;
dispatcherOptions: {
deliver: (payload: {
text?: string;
mediaUrls?: string[];
mediaUrl?: string;
}) => void | Promise<void>;
onError?: (err: unknown, info: { kind: string }) => void;
};
}): Promise<void>;
createReplyDispatcherWithTyping?: unknown; // adapter for Teams-style flows
};
routing: {
resolveAgentRoute(params: {
cfg: unknown;
channel: string;
accountId: string;
peer: { kind: RoutePeerKind; id: string };
}): { sessionKey: string; accountId: string };
};
pairing: {
buildPairingReply(params: { channel: string; idLine: string; code: string }): string;
readAllowFromStore(channel: string): Promise<string[]>;
upsertPairingRequest(params: {
channel: string;
id: string;
meta?: { name?: string };
}): Promise<{ code: string; created: boolean }>;
};
media: {
fetchRemoteMedia(params: { url: string }): Promise<{ buffer: Buffer; contentType?: string }>;
saveMediaBuffer(
buffer: Uint8Array,
contentType: string | undefined,
direction: "inbound" | "outbound",
maxBytes: number,
): Promise<{ path: string; contentType?: string }>;
};
mentions: {
buildMentionRegexes(cfg: OpenClawConfig, agentId?: string): RegExp[];
matchesMentionPatterns(text: string, regexes: RegExp[]): boolean;
};
groups: {
resolveGroupPolicy(
cfg: OpenClawConfig,
channel: string,
accountId: string,
groupId: string,
): {
allowlistEnabled: boolean;
allowed: boolean;
groupConfig?: unknown;
defaultConfig?: unknown;
};
resolveRequireMention(
cfg: OpenClawConfig,
channel: string,
accountId: string,
groupId: string,
override?: boolean,
): boolean;
};
debounce: {
createInboundDebouncer<T>(opts: {
debounceMs: number;
buildKey: (v: T) => string | null;
shouldDebounce: (v: T) => boolean;
onFlush: (entries: T[]) => Promise<void>;
onError?: (err: unknown) => void;
}): { push: (v: T) => void; flush: () => Promise<void> };
resolveInboundDebounceMs(cfg: OpenClawConfig, channel: string): number;
};
commands: {
resolveCommandAuthorizedFromAuthorizers(params: {
useAccessGroups: boolean;
authorizers: Array<{ configured: boolean; allowed: boolean }>;
}): boolean;
};
};
logging: {
shouldLogVerbose(): boolean;
getChildLogger(name: string): PluginLogger;
};
state: {
resolveStateDir(cfg: OpenClawConfig): string;
};
};
  • Instabile Upgrades: Wenn dein Plugin bei Core-Updates bricht, liegt das oft an direkten Imports aus src/**. Migriere auf das SDK und die Runtime API, um Stabilität zu garantieren.
  • Veraltete Bridges: Falls du noch core-bridge.ts in deinen Extensions nutzt, ersetze diese Logik durch api.runtime Aufrufe.

Hast du Fragen zur Implementierung? Nutze unseren AI Setup Assistant.

OpenClaw

OpenClaw Expert

Noch festgefahren?

Wenn diese Seite nicht hilft, frage OpenClaw Expert nach Schritt-fuer-Schritt-Loesungen.