mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 16:50:43 +00:00
[plugin sdk] Add generic plugin host-hook contracts (#72287)
Merged via squash.
Prepared head SHA: 68e5f2ce19
Co-authored-by: 100yenadmin <239388517+100yenadmin@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Reviewed-by: @jalehman
This commit is contained in:
@@ -66,11 +66,13 @@ observation-only.
|
||||
**Agent turn**
|
||||
|
||||
- `before_model_resolve` — override provider or model before session messages load
|
||||
- `agent_turn_prepare` — consume queued plugin turn injections and add same-turn context before prompt hooks
|
||||
- `before_prompt_build` — add dynamic context or system-prompt text before the model call
|
||||
- `before_agent_start` — compatibility-only combined phase; prefer the two hooks above
|
||||
- **`before_agent_reply`** — short-circuit the model turn with a synthetic reply or silence
|
||||
- **`before_agent_finalize`** — inspect the natural final answer and request one more model pass
|
||||
- `agent_end` — observe final messages, success state, and run duration
|
||||
- `heartbeat_prompt_contribution` — add heartbeat-only context for background monitor and lifecycle plugins
|
||||
|
||||
**Conversation observation**
|
||||
|
||||
@@ -153,6 +155,13 @@ Rules:
|
||||
- `onResolution` receives the resolved approval decision — `allow-once`,
|
||||
`allow-always`, `deny`, `timeout`, or `cancelled`.
|
||||
|
||||
Bundled plugins that need host-level policy can register trusted tool policies
|
||||
with `api.registerTrustedToolPolicy(...)`. These run before ordinary
|
||||
`before_tool_call` hooks and before external plugin decisions. Use them only
|
||||
for host-trusted gates such as workspace policy, budget enforcement, or
|
||||
reserved workflow safety. External plugins should use normal `before_tool_call`
|
||||
hooks.
|
||||
|
||||
### Tool result persistence
|
||||
|
||||
Tool results can include structured `details` for UI rendering, diagnostics,
|
||||
@@ -174,9 +183,15 @@ Use the phase-specific hooks for new plugins:
|
||||
|
||||
- `before_model_resolve`: receives only the current prompt and attachment
|
||||
metadata. Return `providerOverride` or `modelOverride`.
|
||||
- `agent_turn_prepare`: receives the current prompt, prepared session messages,
|
||||
and any exactly-once queued injections drained for this session. Return
|
||||
`prependContext` or `appendContext`.
|
||||
- `before_prompt_build`: receives the current prompt and session messages.
|
||||
Return `prependContext`, `systemPrompt`, `prependSystemContext`, or
|
||||
`appendSystemContext`.
|
||||
Return `prependContext`, `appendContext`, `systemPrompt`,
|
||||
`prependSystemContext`, or `appendSystemContext`.
|
||||
- `heartbeat_prompt_contribution`: runs only for heartbeat turns and returns
|
||||
`prependContext` or `appendContext`. It is intended for background monitors
|
||||
that need to summarize current state without changing user-initiated turns.
|
||||
|
||||
`before_agent_start` remains for compatibility. Prefer the explicit hooks above
|
||||
so your plugin does not depend on a legacy combined phase.
|
||||
@@ -219,8 +234,31 @@ Non-bundled plugins that need `llm_input`, `llm_output`,
|
||||
}
|
||||
```
|
||||
|
||||
Prompt-mutating hooks can be disabled per plugin with
|
||||
`plugins.entries.<id>.hooks.allowPromptInjection=false`.
|
||||
Prompt-mutating hooks and durable next-turn injections can be disabled per plugin
|
||||
with `plugins.entries.<id>.hooks.allowPromptInjection=false`.
|
||||
|
||||
### Session extensions and next-turn injections
|
||||
|
||||
Workflow plugins can persist small JSON-compatible session state with
|
||||
`api.registerSessionExtension(...)` and update it through the Gateway
|
||||
`sessions.pluginPatch` method. Session rows project registered extension state
|
||||
through `pluginExtensions`, letting Control UI and other clients render
|
||||
plugin-owned status without learning plugin internals.
|
||||
|
||||
Use `api.enqueueNextTurnInjection(...)` when a plugin needs durable context to
|
||||
reach the next model turn exactly once. OpenClaw drains queued injections before
|
||||
prompt hooks, drops expired injections, and deduplicates by `idempotencyKey`
|
||||
per plugin. This is the right seam for approval resumes, policy summaries,
|
||||
background monitor deltas, and command continuations that should be visible to
|
||||
the model on the next turn but should not become permanent system prompt text.
|
||||
|
||||
Cleanup semantics are part of the contract. Session extension cleanup and
|
||||
runtime lifecycle cleanup callbacks receive `reset`, `delete`, `disable`, or
|
||||
`restart`. The host removes the owning plugin's persistent session extension
|
||||
state and pending next-turn injections for reset/delete/disable; restart keeps
|
||||
durable session state while cleanup callbacks let plugins release scheduler
|
||||
jobs, run context, and other out-of-band resources for the old runtime
|
||||
generation.
|
||||
|
||||
## Message hooks
|
||||
|
||||
|
||||
@@ -113,6 +113,49 @@ provider- or plugin-specific policy to core prompt builders.
|
||||
| `api.registerMemoryPromptSupplement(builder)` | Additive memory-adjacent prompt section |
|
||||
| `api.registerMemoryCorpusSupplement(adapter)` | Additive memory search/read corpus |
|
||||
|
||||
### Host hooks for workflow plugins
|
||||
|
||||
Host hooks are the SDK seams for plugins that need to participate in the host
|
||||
lifecycle rather than only adding a provider, channel, or tool. They are
|
||||
generic contracts; Plan Mode can use them, but so can approval workflows,
|
||||
workspace policy gates, background monitors, setup wizards, and UI companion
|
||||
plugins.
|
||||
|
||||
| Method | Contract it owns |
|
||||
| ------------------------------------------------------------------------ | --------------------------------------------------------------------------------- |
|
||||
| `api.registerSessionExtension(...)` | Plugin-owned, JSON-compatible session state projected through Gateway sessions |
|
||||
| `api.enqueueNextTurnInjection(...)` | Durable exactly-once context injected into the next agent turn for one session |
|
||||
| `api.registerTrustedToolPolicy(...)` | Bundled/trusted pre-plugin tool policy that can block or rewrite tool params |
|
||||
| `api.registerToolMetadata(...)` | Tool catalog display metadata without changing the tool implementation |
|
||||
| `api.registerCommand(...)` | Scoped plugin commands; command results can set `continueAgent: true` |
|
||||
| `api.registerControlUiDescriptor(...)` | Control UI contribution descriptors for session, tool, run, or settings surfaces |
|
||||
| `api.registerRuntimeLifecycle(...)` | Cleanup callbacks for plugin-owned runtime resources on reset/delete/reload paths |
|
||||
| `api.registerAgentEventSubscription(...)` | Sanitized event subscriptions for workflow state and monitors |
|
||||
| `api.setRunContext(...)` / `getRunContext(...)` / `clearRunContext(...)` | Per-run plugin scratch state cleared on terminal run lifecycle |
|
||||
| `api.registerSessionSchedulerJob(...)` | Plugin-owned session scheduler job records with deterministic cleanup |
|
||||
|
||||
The contracts intentionally split authority:
|
||||
|
||||
- External plugins can own session extensions, UI descriptors, commands, tool
|
||||
metadata, next-turn injections, and normal hooks.
|
||||
- Trusted tool policies run before ordinary `before_tool_call` hooks and are
|
||||
bundled-only because they participate in host safety policy.
|
||||
- Reserved command ownership is bundled-only. External plugins should use their
|
||||
own command names or aliases.
|
||||
- `allowPromptInjection=false` disables prompt-mutating hooks including
|
||||
`agent_turn_prepare`, `before_prompt_build`, `heartbeat_prompt_contribution`,
|
||||
prompt fields from legacy `before_agent_start`, and
|
||||
`enqueueNextTurnInjection`.
|
||||
|
||||
Examples of non-Plan consumers:
|
||||
|
||||
| Plugin archetype | Hooks used |
|
||||
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| Approval workflow | Session extension, command continuation, next-turn injection, UI descriptor |
|
||||
| Budget/workspace policy gate | Trusted tool policy, tool metadata, session projection |
|
||||
| Background lifecycle monitor | Runtime lifecycle cleanup, agent event subscription, session scheduler ownership/cleanup, heartbeat prompt contribution, UI descriptor |
|
||||
| Setup or onboarding wizard | Session extension, scoped commands, Control UI descriptor |
|
||||
|
||||
<Note>
|
||||
Reserved core admin namespaces (`config.*`, `exec.approvals.*`, `wizard.*`,
|
||||
`update.*`) always stay `operator.admin`, even if a plugin tries to assign a
|
||||
|
||||
Reference in New Issue
Block a user