definePluginEntry
Import: openclaw/plugin-sdk/plugin-entry
For provider plugins, advanced tool plugins, hook plugins, and anything that
is not a messaging channel.
-
idmust match youropenclaw.plugin.jsonmanifest. -
External session catalogs use
openclaw/plugin-sdk/session-catalogand register aSessionCatalogProviderwithapi.registerSessionCatalog(...). Required provider fields areid,label,list, andread; optional hooks arecreateListOperation,resolveCreateSession,continueSession,copyToGatewaySession,checkUpstreamActivity,archive,openTerminal, andstartTerminalSession. Core owns thesessions.catalog.*Gateway methods; providers return host, session, transcript, and terminal-plan projections without registering RPCs. A list provider should call the optionalonHost(host)callback as each host settles; the returned host array remains required as the final compatibility snapshot. The optionalallowPartialResultsflag is true only when a connected caller explicitly opts in while receiving host progress on a list without host selection or cursors. When true, a provider may return retained host snapshots or mark a still-loading hostpending: true, then publish its completed snapshot throughonHostandwaitUntil. Pending hosts preserve existing client rows and cursors; omitted hosts are removed. Clearpendingon a completed host. EachonHostpublication must be authoritative for that host: the Gateway includes the latest publication for each retained host in the aggregate response even when another provider or visibility projection delays delivery. The final host set is authoritative: an omitted host is withdrawn, not restored from an earlier publication. Preserve the last known rows while refreshing; do not publish an empty host to represent pending work. When the flag is absent or false, return the complete compatibility snapshot. Targeted host lookups and pagination retain that complete-response contract. If a host can finish afterlistreturns a fail-soft snapshot, register its bounded completion with the optionalwaitUntil(completion: Promise<void>)hook beforelistsettles. Include host mapping and theonHostcall in that promise. UsepublishSessionCatalogHost({ onHost, waitUntil }, pendingHost)from the same SDK entry point to publish the host and register the complete callback chain. Registration afterlistsettles is rejected. Providers that do not register completion work finish publishing when theirlistsettles. The optionalsignal: AbortSignalbelongs to the catalog operation or provider lifetime. Pass it to cancellable work, including the top-levelsignalfield ofapi.runtime.nodes.invoke(...). A requesting client disconnect only removes that client’s subscription; it does not cancel shared discovery. The Gateway removes queued listings when their catalog owner retires. Providers that have started keep their admission slot until their returned promise settles. Retaining completion does not extend native invocation or fail-soft response deadlines, grant new authority, or permit starting work after the owner retires. Providers remain responsible for bounded work that settles after cancellation. KeepallowPartialResults,onHost,waitUntil, andsignalseparate from validated catalog query objects and node command payloads. The request-ownedsessionEntriessnapshot andlistNodeshook must be released whenlistsettles, or when the optional list operation below closes. Prepare the facts needed by late host mapping before that boundary. Providers with a multi-step fill can implement the optionalSessionCatalogProvider.createListOperation(params)hook. Its synchronous factory returns{ next, close }without starting source work. The Gateway calls the factory once inside the first admission and callsnext()serially:{ done: false }means the step has settled and only inert continuation state remains. The same request rejoins the existing provider FIFO behind waiting callers; no partial result is sent to the client.{ done: true, hosts }supplies the complete filled result thatlistwould return. Providers without this hook continue usinglistonce.
sessions.catalog.listchecks its original Gateway and catalog registration owner before each step and after it settles. A stale owner ends the stepped list and closes its operation without starting further source work. Eachnext()returns a promise and must join all foreground work it starts before settling. A handoff cannot leave a source page, classification, or required projection running. Preserve the source’s existing limits, shared producer ownership, ordering, and failure behavior. One logical request keeps the samesessionEntries,listNodes,onHost,waitUntil, andsignallifetime across every step. Register publication work before the logical list settles, usingpublishSessionCatalogHostas above; an asynchronous publication callback remains separately accounted work, not a foreground step. The Gateway calls synchronousclose()once after completion, failure, or cancellation while queued. Active cancellation still waits for the actualnext()promise before closing. Mark the operation closed first, reject any unfinished logical host results, and release only operation-owned references. Close starts no source work or asynchronous cleanup and must not cancel shared producers. Laternext()calls must fail before I/O; repeated close is inert. Native-discovery consent is checked before factory construction and before and after each step. Initial disablement returns an empty result without constructing the source; later revocation rejects the logical list. Transcript items may include asenderwith a qualifiedSessionParticipantidentity and optional display label or avatar. Supply only source-known attribution; the viewer and the session adopter are not transcript authors. Core resolves profile identities against current profile data, including merges. User items without attribution display as User. A Gateway-hosted catalog may setaudience: "gateway-operators"when every authenticated operator withoperator.readmay view its rows. Such a provider may implementcopyToGatewaySession(...)to return a bounded display name and optional preferred model for an independent Gateway-owned continuation. Core owns operator and agent authorization, session creation, model readiness and policy checks, rollback, and untrusted-content wrapping. The provider supplies transcript text throughread(...); it must not write the destination session. A read-only catalog of sessions published by another Gateway may setaudience: "session-viewers". Viewers needoperator.read; configured roles must also allow viewing others’ sessions (sessions.others: "view","suggest", or"write"). Source publication and receiver roles are checked independently. Core rechecks the receiver’s access after asynchronous reads; the provider must recheck that the source session remains published before returning its transcript. Provider attribution remains display metadata and does not adopt the source session into the receiving Gateway. Native source titles are presentation, not unique session labels. When adopting a new source, pass its title asdisplayNameto the owner-authorized session creator; the host bounds and stores that snapshot with the new row. Keep source identity independent of naming, preserve existing labels and snapshots on reuse or recovery, and do not resync native renames. A provider may declare one readable transcript route withshareRoute. This is a closed contract, not a free-form routing hint:The provider must return lowercase hexadecimalthreadIdvalues of exactly 32 characters on the declared host. Whenlist(...)receives asearchvalue that is a valid 12-32 character prefix, that host must return only rows whosethreadIdstarts with the prefix. Return every match up to the requested limit and setnextCursorwhen more may exist. The Control UI resolves only one result with no next page; multiple rows ornextCursorare explicitly ambiguous and never select the first row. Named share links use/<routeSegment>/<title-slug>-<id-prefix>with the same bounded slug as regular session links. Return the title in the catalog row’sname; the Control UI uses it to refresh the decorative slug. Only the id suffix selects the transcript. Bare-id and stale-title links remain valid, and titles never resolve an ambiguous id.routeSegmentmust not use the first segment of a built-in Control UI route or alias, and it must be unique across active session catalogs. Invalid, unsupported, reserved, or multiply owned descriptors fail closed; catalog sessions remain available through the generic/chat/<agent>?catalog=...&host=...&thread=...URL. The shared session URL contract owns the built-in reservation decision: its share-path builder returnsnullfor reserved segments, and the Gateway omits reserved descriptors before publishing catalogs. Keep one plugin-owned descriptor constant and reuse it for registration, prefix lookup, and URL generation so those obligations cannot drift. CLI-backed catalogs that expose the same local-plus-paired-node shape can usecreateSessionCatalogFamily(...). The family composer owns canonical cursor validation, node payload validation, host projection, adopted-session projection, per-host publication, read routing, single-flight continuation per resolved agent and source, and terminal plan routing. Different agents do not share in-flight adoption results; adopted-source lookup keys remain host/thread pairs. The provider must supply its local store reads, identifiers and commands, error text, capability projection, continuation availability and persistence operations, upstream-activity check, and terminal executable/arguments. There are no default continuation, capability-mutation, or terminal authorities. UsecreateSessionCatalogNodeHostBindings(...)to build the matching list/read/terminal node commands and terminal-only invoke policy from those explicit provider inputs. The same entrypoint exportssessionCatalogPaging, which groups the bounded list/read parameter parsers, canonical base64url cursor codec, and bounded UTF-8 transcript pager. Providers pass their own identifier pattern and validation messages intoparseReadParams(...)andparseListParams(...).resolveCreateSession({ agentId })must return a config-derived model/runtime target before OpenClaw advertises model-chat creation. Native terminal readiness is independent of this target. Useapi.runtime.agent.resolveSessionCatalogCreateTarget(...)to apply the host’s runtime and model-allowlist policy instead of duplicating it.startTerminalSessionadvertisescapabilities.startTerminal: trueindependently of model-chat creation. ReturncanStartTerminal: trueon each eligible host from the ordinary cataloglistcallback, including empty hosts. Publish the same flag in progressiveonHostframes and final results; explicitly returnfalsewhen readiness changes. A failed transcript listing does not revoke an otherwise available CLI. Node hosts require their exact connected, invocable fresh-start command; start-only nodes must not invoke a missing list command. Preserve local source IDs and process-home isolation. The shippedcreateSession.startTerminalfield remains model-chat metadata; new terminal callers use the independent capability and raw catalog hosts.startTerminalSession({ agentId, cwd, initialMessage?, nodeId?, hostId? })creates a fresh CLI terminal plan. Return either a local plan (kind: "local",argv, and the exactcwd, plus optionalenv,pathEnv, andtitle) or a paired-node plan (kind: "node",nodeId,command,paramsJSON, and the exactcwd). Thesessions.catalog.startTerminalRPC requiresoperator.adminplusgateway.cliAgents.enabledandgateway.terminal.enabled. The caller provisionscwd; the Gateway requires an existing absolute local directory, rejects a changed plan cwd or host, and applies the normal agent-sandbox, node-pairing, deadline, and connection-ownership checks before opening the PTY.hostIdcarries the selected local source;nodeIdidentifies a node. Initial prompts are bounded to 16,384 characters and cwd to 4,096 characters (4,096 UTF-8 bytes on nodes). Fresh node commands usedecodeNodePtyStartParamsfromnode-hostandrunNodePtyCommand({ ..., requiredCwd: true }, io)to require an existing absolute node directory, including a recheck immediately before spawning. Resume retains its existing cwd fallback contract. Node payloads must not accept executable, argv, environment, credentials, or a Gateway agent as native account selection. Paired-node plans that run an interactive CLI directly can declareuploadPathStyle: "native"when it accepts double-quoted POSIX paths and simple double-quoted Windows drive or UNC paths as file references. Native Windows formatting preserves apostrophes and backslashes, and rejects double quotes and control characters. Declare the same contract throughterminal.uploadPathStyleincreateSessionCatalogFamily(...). Leave the field absent for shells or other input syntaxes. The Gateway includes it interminal.uploadresults only for clients advertisingterminal-upload-path-style. Without an upload style, clients use the terminal’s shell quoting rules. The terminal manager retains the native title and actual connection/agent owner across attach and reconnect. Clients advertiseterminal-session-metadatato receive attach title/owner and list titles; older closed response shapes stay unchanged. -
kindis deprecated: declare an exclusive slot ("memory"or"context-engine") in theopenclaw.plugin.jsonmanifestkindfield instead. Runtime-entrykindremains only as a compatibility fallback for older plugins. -
configSchemacan be a function for lazy evaluation. OpenClaw resolves and memoizes the schema on first access, so expensive schema builders only run once. -
A
nodeHostCommandsdescriptor can defineisAvailable({ config, env }). Returningfalseomits that command and its capability from the headless node’s Gateway declaration. OpenClaw evaluates it against the node-local startup config; command handlers should still validate availability when invoked.