mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 11:00:42 +00:00
feat(plugins): add before agent finalize hook (#71765)
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
f5236ba3f34837485d1e319262d4d73ecd46ea8890d3f4c26a069834f376b796 config-baseline.json
|
||||
484b36513ecb4a13cc945c3916fbe5ac712b5e0ab2c4ffa2dc811758da4ec7a6 config-baseline.core.json
|
||||
15a3740b57d0c95f0c0963c1d0eff6d85ecdb8cb03960b4763e847f8a24551c0 config-baseline.json
|
||||
3c39a3a2008ce938886b600e9429a71921c1f9b00c64a16801f47d6d8d2ad7a8 config-baseline.core.json
|
||||
7cd9c908f066c143eab2a201efbc9640f483ab28bba92ddeca1d18cc2b528bc3 config-baseline.channel.json
|
||||
17eb3f8887193579ff32e35f9bd520ba2bd6049e52ab18855c5d41fcbf195d83 config-baseline.plugin.json
|
||||
9e131d7734f8b9cc9e7f8af6cc6b6dc81c9971dc551fadbe66fb0d682173f32d config-baseline.plugin.json
|
||||
|
||||
@@ -126,6 +126,11 @@ Each event includes: `type`, `action`, `sessionKey`, `timestamp`, `messages` (pu
|
||||
|
||||
**Compaction events**: `session:compact:before` includes `messageCount`, `tokenCount`. `session:compact:after` adds `compactedCount`, `summaryLength`, `tokensBefore`, `tokensAfter`.
|
||||
|
||||
`command:stop` observes the user issuing `/stop`; it is cancellation/command
|
||||
lifecycle, not an agent-finalization gate. Plugins that need to inspect a
|
||||
natural final answer and ask the agent for one more pass should use the typed
|
||||
plugin hook `before_agent_finalize` instead. See [Plugin hooks](/plugins/hooks).
|
||||
|
||||
## Hook discovery
|
||||
|
||||
Hooks are discovered from these directories, in order of increasing override precedence:
|
||||
|
||||
@@ -219,7 +219,8 @@ For runtime hook debugging:
|
||||
from a module-loaded inspection pass.
|
||||
- `openclaw gateway status --deep --require-rpc` confirms the reachable Gateway,
|
||||
service/process hints, config path, and RPC health.
|
||||
- Non-bundled conversation hooks (`llm_input`, `llm_output`, `agent_end`) require
|
||||
- Non-bundled conversation hooks (`llm_input`, `llm_output`,
|
||||
`before_agent_finalize`, `agent_end`) require
|
||||
`plugins.entries.<id>.hooks.allowConversationAccess=true`.
|
||||
|
||||
Use `--link` to avoid copying a local directory (adds to `plugins.load.paths`):
|
||||
|
||||
@@ -160,7 +160,7 @@ See [MCP](/cli/mcp#openclaw-as-an-mcp-client-registry) and
|
||||
- `plugins.entries.<id>.apiKey`: plugin-level API key convenience field (when supported by the plugin).
|
||||
- `plugins.entries.<id>.env`: plugin-scoped env var map.
|
||||
- `plugins.entries.<id>.hooks.allowPromptInjection`: when `false`, core blocks `before_prompt_build` and ignores prompt-mutating fields from legacy `before_agent_start`, while preserving legacy `modelOverride` and `providerOverride`. Applies to native plugin hooks and supported bundle-provided hook directories.
|
||||
- `plugins.entries.<id>.hooks.allowConversationAccess`: when `true`, trusted non-bundled plugins may read raw conversation content from typed hooks such as `llm_input`, `llm_output`, and `agent_end`.
|
||||
- `plugins.entries.<id>.hooks.allowConversationAccess`: when `true`, trusted non-bundled plugins may read raw conversation content from typed hooks such as `llm_input`, `llm_output`, `before_agent_finalize`, and `agent_end`.
|
||||
- `plugins.entries.<id>.subagent.allowModelOverride`: explicitly trust this plugin to request per-run `provider` and `model` overrides for background subagent runs.
|
||||
- `plugins.entries.<id>.subagent.allowedModels`: optional allowlist of canonical `provider/model` targets for trusted subagent overrides. Use `"*"` only when you intentionally want to allow any model.
|
||||
- `plugins.entries.<id>.config`: plugin-defined config object (validated by native OpenClaw plugin schema when available).
|
||||
|
||||
@@ -34,6 +34,7 @@ These are in-process OpenClaw hooks, not Codex `hooks.json` command hooks:
|
||||
- `llm_input`, `llm_output`
|
||||
- `before_tool_call`, `after_tool_call`
|
||||
- `before_message_write` for mirrored transcript records
|
||||
- `before_agent_finalize` through Codex `Stop` relay
|
||||
- `agent_end`
|
||||
|
||||
Plugins can also register runtime-neutral tool-result middleware to rewrite
|
||||
@@ -583,10 +584,10 @@ The Codex harness has three hook layers:
|
||||
|
||||
OpenClaw does not use project or global Codex `hooks.json` files to route
|
||||
OpenClaw plugin behavior. For the supported native tool and permission bridge,
|
||||
OpenClaw injects per-thread Codex config for `PreToolUse`, `PostToolUse`, and
|
||||
`PermissionRequest`. Other Codex hooks such as `SessionStart`,
|
||||
`UserPromptSubmit`, and `Stop` remain Codex-level controls; they are not exposed
|
||||
as OpenClaw plugin hooks in the v1 contract.
|
||||
OpenClaw injects per-thread Codex config for `PreToolUse`, `PostToolUse`,
|
||||
`PermissionRequest`, and `Stop`. Other Codex hooks such as `SessionStart` and
|
||||
`UserPromptSubmit` remain Codex-level controls; they are not exposed as
|
||||
OpenClaw plugin hooks in the v1 contract.
|
||||
|
||||
For OpenClaw dynamic tools, OpenClaw executes the tool after Codex asks for the
|
||||
call, so OpenClaw fires the plugin and middleware behavior it owns in the
|
||||
@@ -622,6 +623,7 @@ Supported in Codex runtime v1:
|
||||
| Context engine lifecycle | Supported | Assemble, ingest or after-turn maintenance, and context-engine compaction coordination run for Codex turns. |
|
||||
| Dynamic tool hooks | Supported | `before_tool_call`, `after_tool_call`, and tool-result middleware run around OpenClaw-owned dynamic tools. |
|
||||
| Lifecycle hooks | Supported as adapter observations | `llm_input`, `llm_output`, `agent_end`, `before_compaction`, and `after_compaction` fire with honest Codex-mode payloads. |
|
||||
| Final-answer revision gate | Supported through the native hook relay | Codex `Stop` is relayed to `before_agent_finalize`; `revise` asks Codex for one more model pass before finalization. |
|
||||
| Native shell, patch, and MCP block or observe | Supported through the native hook relay | Codex `PreToolUse` and `PostToolUse` are relayed for committed native tool surfaces, including MCP payloads on Codex app-server `0.125.0` or newer. Blocking is supported; argument rewriting is not. |
|
||||
| Native permission policy | Supported through the native hook relay | Codex `PermissionRequest` can be routed through OpenClaw policy where the runtime exposes it. If OpenClaw returns no decision, Codex continues through its normal guardian or user approval path. |
|
||||
| App-server trajectory capture | Supported | OpenClaw records the request it sent to app-server and the app-server notifications it receives. |
|
||||
@@ -635,7 +637,6 @@ Not supported in Codex runtime v1:
|
||||
| `tool_result_persist` for Codex-native tool records | That hook transforms OpenClaw-owned transcript writes, not Codex-native tool records. | Could mirror transformed records, but canonical rewrite needs Codex support. |
|
||||
| Rich native compaction metadata | OpenClaw observes compaction start and completion, but does not receive a stable kept/dropped list, token delta, or summary payload. | Needs richer Codex compaction events. |
|
||||
| Compaction intervention | Current OpenClaw compaction hooks are notification-level in Codex mode. | Add Codex pre/post compaction hooks if plugins need to veto or rewrite native compaction. |
|
||||
| Stop or final-answer gating | Codex has native stop hooks, but OpenClaw does not expose final-answer gating as a v1 plugin contract. | Future opt-in primitive with loop and timeout safeguards. |
|
||||
| Byte-for-byte model API request capture | OpenClaw can capture app-server requests and notifications, but Codex core builds the final OpenAI API request internally. | Needs a Codex model-request tracing event or debug API. |
|
||||
|
||||
## Tools, media, and compaction
|
||||
|
||||
@@ -64,6 +64,7 @@ observation-only.
|
||||
- `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
|
||||
|
||||
**Conversation observation**
|
||||
@@ -185,7 +186,16 @@ bodies, or provider request IDs. These hooks include stable metadata such as
|
||||
`durationMs`/`outcome`, and `upstreamRequestIdHash` when OpenClaw can derive a
|
||||
bounded provider request-id hash.
|
||||
|
||||
Non-bundled plugins that need `llm_input`, `llm_output`, or `agent_end` must set:
|
||||
`before_agent_finalize` runs only when a harness is about to accept a natural
|
||||
final assistant answer. It is not the `/stop` cancellation path and does not
|
||||
run when the user aborts a turn. Return `{ action: "revise", reason }` to ask
|
||||
the harness for one more model pass before finalization, `{ action:
|
||||
"finalize", reason? }` to force finalization, or omit a result to continue.
|
||||
Codex native `Stop` hooks are relayed into this hook as OpenClaw
|
||||
`before_agent_finalize` decisions.
|
||||
|
||||
Non-bundled plugins that need `llm_input`, `llm_output`,
|
||||
`before_agent_finalize`, or `agent_end` must set:
|
||||
|
||||
```json
|
||||
{
|
||||
|
||||
@@ -65,11 +65,12 @@ dynamic tools still execute through OpenClaw, while Codex-native tools such as
|
||||
shell/apply-patch execute inside Codex. For Codex-native tool events, OpenClaw
|
||||
injects a per-turn native hook relay so plugin hooks can block
|
||||
`before_tool_call`, observe `after_tool_call`, and route Codex
|
||||
`PermissionRequest` events through OpenClaw approvals. The v1 relay is
|
||||
deliberately conservative: it does not mutate Codex-native tool arguments,
|
||||
rewrite Codex thread records, or gate final answers/Stop hooks. Use explicit
|
||||
ACP only when you want the ACP runtime/session model. The embedded Codex support
|
||||
boundary is documented in the
|
||||
`PermissionRequest` events through OpenClaw approvals. Codex `Stop` hooks are
|
||||
relayed to OpenClaw `before_agent_finalize`, where plugins can request one more
|
||||
model pass before Codex finalizes its answer. The relay remains deliberately
|
||||
conservative: it does not mutate Codex-native tool arguments or rewrite Codex
|
||||
thread records. Use explicit ACP only when you want the ACP runtime/session
|
||||
model. The embedded Codex support boundary is documented in the
|
||||
[Codex harness v1 support contract](/plugins/codex-harness#v1-support-contract).
|
||||
|
||||
Natural-language triggers that should route to the ACP runtime:
|
||||
|
||||
@@ -223,7 +223,7 @@ do not run in live chat traffic, check these first:
|
||||
`openclaw gateway run` process.
|
||||
- Use `openclaw plugins inspect <id> --json` to confirm hook registrations and
|
||||
diagnostics. Non-bundled conversation hooks such as `llm_input`,
|
||||
`llm_output`, and `agent_end` need
|
||||
`llm_output`, `before_agent_finalize`, and `agent_end` need
|
||||
`plugins.entries.<id>.hooks.allowConversationAccess=true`.
|
||||
- For model switching, prefer `before_model_resolve`. It runs before model
|
||||
resolution for agent turns; `llm_output` only runs after a model attempt
|
||||
|
||||
Reference in New Issue
Block a user