Langsung ke konten utama

Documentation Index

Fetch the complete documentation index at: https://docs.openclaw.ai/llms.txt

Use this file to discover all available pages before exploring further.

Kernel giliran kanal adalah mesin status masuk bersama yang mengubah peristiwa platform yang dinormalisasi menjadi giliran agen. Plugin kanal menyediakan fakta platform dan callback pengiriman. Inti memiliki orkestrasi: serap, klasifikasikan, preflight, selesaikan, otorisasi, susun, rekam, dispatch, dan finalisasi. Gunakan ini saat Plugin Anda berada pada jalur panas pesan masuk. Untuk peristiwa non-pesan (perintah slash, modal, interaksi tombol, peristiwa siklus hidup, reaksi, status suara), pertahankan tetap lokal di Plugin. Kernel hanya memiliki peristiwa yang mungkin menjadi giliran teks agen.
Kernel dijangkau melalui runtime Plugin yang diinjeksi sebagai runtime.channel.turn.*. Tipe runtime Plugin diekspor dari openclaw/plugin-sdk/core, sehingga Plugin native pihak ketiga dapat menggunakan titik masuk ini dengan cara yang sama seperti Plugin kanal bawaan.

Mengapa kernel bersama

Plugin kanal mengulang alur masuk yang sama: normalisasi, rutekan, batasi, bangun konteks, rekam metadata sesi, dispatch giliran agen, finalisasi status pengiriman. Tanpa kernel bersama, perubahan pada gating mention, balasan terlihat yang hanya berisi alat, metadata sesi, riwayat tertunda, atau finalisasi dispatch harus diterapkan per kanal. Kernel sengaja menjaga empat konsep tetap terpisah:
  • ConversationFacts: dari mana pesan berasal
  • RouteFacts: agen dan sesi mana yang harus memprosesnya
  • ReplyPlanFacts: ke mana balasan terlihat harus dikirim
  • MessageFacts: body dan konteks tambahan apa yang harus dilihat agen
DM Slack, topik Telegram, thread Matrix, dan sesi topik Feishu semuanya membedakan ini dalam praktik. Memperlakukannya sebagai satu pengenal menyebabkan drift seiring waktu.

Siklus hidup tahap

Kernel menjalankan pipeline tetap yang sama apa pun kanalnya:
  1. ingest — adapter mengubah peristiwa platform mentah menjadi NormalizedTurnInput
  2. classify — adapter menyatakan apakah peristiwa ini dapat memulai giliran agen
  3. preflight — adapter melakukan dedupe, self-echo, hidrasi, debounce, dekripsi, pengisian awal fakta parsial
  4. resolve — adapter mengembalikan giliran yang sudah tersusun penuh (rute, rencana balasan, pesan, pengiriman)
  5. authorize — kebijakan DM, grup, mention, dan perintah diterapkan pada fakta yang tersusun
  6. assembleFinalizedMsgContext dibangun dari fakta melalui buildContext
  7. record — metadata sesi masuk dan rute terakhir dipersistenkan
  8. dispatch — giliran agen dieksekusi melalui dispatcher blok berbuffer
  9. finalizeonFinalize adapter berjalan bahkan saat terjadi error dispatch
Setiap tahap memancarkan peristiwa log terstruktur saat callback log disediakan. Lihat Observabilitas.

Jenis admisi

Kernel tidak melempar error saat suatu giliran dibatasi. Ia mengembalikan ChannelTurnAdmission:
JenisKapan
dispatchGiliran diterima. Giliran agen berjalan dan jalur balasan terlihat dijalankan.
observeOnlyGiliran berjalan end-to-end tetapi adapter pengiriman tidak mengirim apa pun yang terlihat. Digunakan untuk agen pengamat siaran dan alur multi-agen pasif lainnya.
handledPeristiwa platform dikonsumsi secara lokal (siklus hidup, reaksi, tombol, modal). Kernel melewati dispatch.
dropJalur lewati. Secara opsional recordHistory: true mempertahankan pesan dalam riwayat grup tertunda sehingga mention mendatang memiliki konteks.
Admisi dapat berasal dari classify (kelas peristiwa menyatakan tidak dapat memulai giliran), dari preflight (dedupe, self-echo, mention hilang dengan rekaman riwayat), atau dari resolveTurn sendiri.

Titik masuk

Runtime mengekspos tiga titik masuk pilihan sehingga adapter dapat ikut serta pada level yang sesuai dengan kanal.
runtime.channel.turn.run(...)             // adapter-driven full pipeline
runtime.channel.turn.runPrepared(...)     // channel owns dispatch; kernel runs record + finalize
runtime.channel.turn.buildContext(...)    // pure facts to FinalizedMsgContext mapping
Dua helper runtime lama tetap tersedia untuk kompatibilitas Plugin SDK:
runtime.channel.turn.runResolved(...)      // deprecated compatibility alias; prefer run
runtime.channel.turn.dispatchAssembled(...) // deprecated compatibility alias; prefer run or runPrepared

run

Gunakan saat kanal Anda dapat mengekspresikan alur masuknya sebagai ChannelTurnAdapter<TRaw>. Adapter memiliki callback untuk ingest, classify opsional, preflight opsional, resolveTurn wajib, dan onFinalize opsional.
await runtime.channel.turn.run({
  channel: "tlon",
  accountId,
  raw: platformEvent,
  adapter: {
    ingest(raw) {
      return {
        id: raw.messageId,
        timestamp: raw.timestamp,
        rawText: raw.body,
        textForAgent: raw.body,
      };
    },
    classify(input) {
      return { kind: "message", canStartAgentTurn: input.rawText.length > 0 };
    },
    async preflight(input, eventClass) {
      if (await isDuplicate(input.id)) {
        return { admission: { kind: "drop", reason: "dedupe" } };
      }
      return {};
    },
    resolveTurn(input) {
      return buildAssembledTurn(input);
    },
    onFinalize(result) {
      clearPendingGroupHistory(result);
    },
  },
});
run adalah bentuk yang tepat saat kanal memiliki logika adapter kecil dan mendapat manfaat dari memiliki siklus hidup melalui hook.

runPrepared

Gunakan saat kanal memiliki dispatcher lokal kompleks dengan pratinjau, percobaan ulang, edit, atau bootstrap thread yang harus tetap dimiliki kanal. Kernel tetap merekam sesi masuk sebelum dispatch dan memunculkan DispatchedChannelTurnResult yang seragam.
const { dispatchResult } = await runtime.channel.turn.runPrepared({
  channel: "matrix",
  accountId,
  routeSessionKey,
  storePath,
  ctxPayload,
  recordInboundSession,
  record: {
    onRecordError,
    updateLastRoute,
  },
  onPreDispatchFailure: async (err) => {
    await stopStatusReactions();
  },
  runDispatch: async () => {
    return await runMatrixOwnedDispatcher();
  },
});
Kanal kaya (Matrix, Mattermost, Microsoft Teams, Feishu, QQ Bot) menggunakan runPrepared karena dispatcher mereka mengorkestrasi perilaku spesifik platform yang tidak boleh dipelajari kernel.

buildContext

Fungsi murni yang memetakan bundel fakta menjadi FinalizedMsgContext. Gunakan saat kanal Anda merangkai sebagian pipeline secara manual tetapi menginginkan bentuk konteks yang konsisten.
const ctxPayload = runtime.channel.turn.buildContext({
  channel: "googlechat",
  accountId,
  messageId,
  timestamp,
  from,
  sender,
  conversation,
  route,
  reply,
  message,
  access,
  media,
  supplemental,
});
buildContext juga berguna di dalam callback resolveTurn saat menyusun giliran untuk run.
Helper SDK usang seperti dispatchInboundReplyWithBase masih menjembatani melalui helper giliran tersusun. Kode Plugin baru sebaiknya menggunakan run atau runPrepared.

Tipe fakta

Fakta yang dikonsumsi kernel dari adapter Anda bersifat agnostik platform. Terjemahkan objek platform ke bentuk ini sebelum menyerahkannya ke kernel.

NormalizedTurnInput

BidangTujuan
idId pesan stabil yang digunakan untuk dedupe dan log
timestampEpoch ms opsional
rawTextBody sebagaimana diterima dari platform
textForAgentBody bersih opsional untuk agen (penghapusan mention, pemangkasan pengetikan)
textForCommandsBody opsional yang digunakan untuk parsing /command
rawReferensi pass-through opsional untuk callback adapter yang membutuhkan aslinya

ChannelEventClass

BidangTujuan
kindmessage, command, interaction, reaction, lifecycle, unknown
canStartAgentTurnJika false, kernel mengembalikan { kind: "handled" }
requiresImmediateAckPetunjuk untuk adapter yang perlu melakukan ACK sebelum dispatch

SenderFacts

BidangTujuan
idId pengirim platform stabil
nameNama tampilan
usernameHandle jika berbeda dari name
tagDiskriminator bergaya Discord atau tag platform
rolesId peran, digunakan untuk pencocokan allowlist peran anggota
isBotTrue saat pengirim adalah bot yang dikenal (digunakan kernel untuk menjatuhkan)
isSelfTrue saat pengirim adalah agen yang dikonfigurasi itu sendiri
displayLabelLabel pra-render untuk teks amplop

ConversationFacts

BidangTujuan
kinddirect, group, atau channel
idId percakapan yang digunakan untuk routing
labelLabel manusia untuk amplop
spaceIdPengenal ruang luar opsional (workspace Slack, homeserver Matrix)
parentIdId percakapan luar saat ini adalah thread
threadIdId thread saat pesan ini berada di dalam thread
nativeChannelIdId kanal native platform saat berbeda dari id routing
routePeerPeer yang digunakan untuk lookup resolveAgentRoute

RouteFacts

BidangTujuan
agentIdAgen yang harus menangani giliran ini
accountIdOverride opsional (kanal multi-akun)
routeSessionKeyKunci sesi yang digunakan untuk routing
dispatchSessionKeyKunci sesi yang digunakan saat dispatch ketika berbeda dari kunci rute
persistedSessionKeyKunci sesi yang ditulis ke metadata sesi yang dipersistenkan
parentSessionKeyInduk untuk sesi bercabang/ber-thread
modelParentSessionKeyInduk sisi model untuk sesi bercabang
mainSessionKeyPin pemilik DM utama untuk percakapan langsung
createIfMissingIzinkan langkah rekam membuat baris sesi yang hilang

ReplyPlanFacts

BidangTujuan
toTarget balasan logis yang ditulis ke konteks To
originatingToTarget konteks asal (OriginatingTo)
nativeChannelIdId saluran native platform untuk pengiriman
replyTargetTujuan balasan terlihat akhir jika berbeda dari to
deliveryTargetOverride pengiriman tingkat lebih rendah
replyToIdId pesan yang dikutip/ditambatkan
replyToIdFullId kutipan bentuk lengkap ketika platform memiliki keduanya
messageThreadIdId utas pada waktu pengiriman
threadParentIdId pesan induk dari utas
sourceReplyDeliveryModethread, reply, channel, direct, atau none

AccessFacts

AccessFacts membawa boolean yang dibutuhkan tahap otorisasi. Pencocokan identitas tetap berada di saluran: kernel hanya memakai hasilnya.
BidangTujuan
dmKeputusan izin/pairing/tolak DM dan daftar allowFrom
groupKebijakan grup, izin rute, izin pengirim, allowlist, persyaratan mention
commandsOtorisasi perintah di seluruh otorisator yang dikonfigurasi
mentionsApakah deteksi mention memungkinkan dan apakah agen disebut

MessageFacts

BidangTujuan
bodyIsi envelope akhir (terformat)
rawBodyIsi inbound mentah
bodyForAgentIsi yang dilihat agen
commandBodyIsi yang digunakan untuk parsing perintah
envelopeFromLabel pengirim yang sudah dirender untuk envelope
senderLabelOverride opsional untuk pengirim yang dirender
previewPratinjau singkat yang disunting untuk log
inboundHistoryEntri riwayat inbound terbaru saat saluran menyimpan buffer

SupplementalContextFacts

Konteks tambahan mencakup konteks kutipan, teruskan, dan bootstrap utas. Kernel menerapkan kebijakan contextVisibility yang dikonfigurasi. Adapter saluran hanya menyediakan fakta dan flag senderAllowed agar kebijakan lintas saluran tetap konsisten.

InboundMediaFacts

Media berbentuk fakta. Download platform, auth, kebijakan SSRF, aturan CDN, dan dekripsi tetap lokal saluran. Kernel memetakan fakta ke MediaPath, MediaUrl, MediaType, MediaPaths, MediaUrls, MediaTypes, dan MediaTranscribedIndexes.

Kontrak adapter

Untuk run lengkap, bentuk adapternya adalah:
type ChannelTurnAdapter<TRaw> = {
  ingest(raw: TRaw): Promise<NormalizedTurnInput | null> | NormalizedTurnInput | null;
  classify?(input: NormalizedTurnInput): Promise<ChannelEventClass> | ChannelEventClass;
  preflight?(
    input: NormalizedTurnInput,
    eventClass: ChannelEventClass,
  ): Promise<PreflightFacts | ChannelTurnAdmission | null | undefined>;
  resolveTurn(
    input: NormalizedTurnInput,
    eventClass: ChannelEventClass,
    preflight: PreflightFacts,
  ): Promise<ChannelTurnResolved> | ChannelTurnResolved;
  onFinalize?(result: ChannelTurnResult): Promise<void> | void;
};
resolveTurn mengembalikan ChannelTurnResolved, yaitu AssembledChannelTurn dengan jenis admission opsional. Mengembalikan { admission: { kind: "observeOnly" } } menjalankan turn tanpa menghasilkan output terlihat. Adapter tetap memiliki callback pengiriman; callback itu hanya menjadi no-op untuk turn tersebut. onFinalize berjalan pada setiap hasil, termasuk error dispatch. Gunakan ini untuk membersihkan riwayat grup yang tertunda, menghapus reaksi ack, menghentikan indikator status, dan flush status lokal.

Adapter pengiriman

Kernel tidak memanggil platform secara langsung. Saluran memberikan ChannelTurnDeliveryAdapter kepada kernel:
type ChannelTurnDeliveryAdapter = {
  deliver(payload: ReplyPayload, info: ChannelDeliveryInfo): Promise<ChannelDeliveryResult | void>;
  onError?(err: unknown, info: { kind: string }): void;
};

type ChannelDeliveryResult = {
  messageIds?: string[];
  threadId?: string;
  replyToId?: string;
  visibleReplySent?: boolean;
};
deliver dipanggil sekali per chunk balasan yang dibuffer. Kembalikan id pesan platform saat saluran memilikinya agar dispatcher dapat mempertahankan tambatan utas dan mengedit chunk berikutnya nanti. Untuk turn observe-only, kembalikan { visibleReplySent: false } atau gunakan createNoopChannelTurnDeliveryAdapter().

Opsi pencatatan

Tahap pencatatan membungkus recordInboundSession. Sebagian besar saluran dapat menggunakan default. Override melalui record:
record: {
  groupResolution,
  createIfMissing: true,
  updateLastRoute,
  onRecordError: (err) => log.warn("record failed", err),
  trackSessionMetaTask: (task) => pendingTasks.push(task),
}
Dispatcher menunggu tahap pencatatan. Jika pencatatan melempar error, kernel menjalankan onPreDispatchFailure (saat disediakan ke runPrepared) dan melempar ulang.

Observabilitas

Setiap tahap memancarkan event terstruktur saat callback log disediakan:
await runtime.channel.turn.run({
  channel: "twitch",
  accountId,
  raw,
  adapter,
  log: (event) => {
    runtime.log?.debug?.(`turn.${event.stage}:${event.event}`, {
      channel: event.channel,
      accountId: event.accountId,
      messageId: event.messageId,
      sessionKey: event.sessionKey,
      admission: event.admission,
      reason: event.reason,
    });
  },
});
Tahap yang dicatat: ingest, classify, preflight, resolve, authorize, assemble, record, dispatch, finalize. Hindari mencatat isi mentah; gunakan MessageFacts.preview untuk pratinjau singkat yang disunting.

Yang tetap lokal saluran

Kernel memiliki orkestrasi. Saluran tetap memiliki:
  • Transport platform (gateway, REST, websocket, polling, webhook)
  • Resolusi identitas dan pencocokan nama tampilan
  • Perintah native, slash command, autocomplete, modal, tombol, status suara
  • Rendering kartu, modal, dan adaptive-card
  • Auth media, aturan CDN, media terenkripsi, transkripsi
  • API edit, reaksi, redaksi, dan presence
  • Backfill dan pengambilan riwayat sisi platform
  • Alur pairing yang memerlukan verifikasi khusus platform
Jika dua saluran mulai membutuhkan helper yang sama untuk salah satu hal ini, ekstrak helper SDK bersama alih-alih mendorongnya ke kernel.

Stabilitas

runtime.channel.turn.* adalah bagian dari surface runtime Plugin publik. Tipe fakta (SenderFacts, ConversationFacts, RouteFacts, ReplyPlanFacts, AccessFacts, MessageFacts, SupplementalContextFacts, InboundMediaFacts) dan bentuk admission (ChannelTurnAdmission, ChannelEventClass) dapat dijangkau melalui PluginRuntime dari openclaw/plugin-sdk/core. Aturan kompatibilitas mundur berlaku: bidang fakta baru bersifat aditif, jenis admission tidak diganti namanya, dan nama entry point tetap stabil. Kebutuhan saluran baru yang memerlukan perubahan non-aditif harus melalui proses migrasi SDK Plugin.

Terkait