mirror of
https://github.com/openclaw/openclaw.git
synced 2026-06-06 05:51:15 +08:00
docs: absorb hook and subagent guidance PRs
This commit is contained in:
@@ -6,6 +6,7 @@ Docs: https://docs.openclaw.ai
|
||||
|
||||
### Changes
|
||||
|
||||
- Docs: clarify model-usage portability, Codex migration prerequisites, status bootstrap wording, thread-bound subagent limits, hook ownership, and config-preserving safety guidance. Thanks @aniruddhaadak80, @leno23, @TomDjerry, @matthewxmurphy, @vincentkoc, and @stablegenius49.
|
||||
- Docs: clarify README onboarding and Gateway startup paths, WhatsApp QR/408 recovery, cron output language prompts, skill advanced features, gateway upstream 403 troubleshooting, and plugin fallback override guidance. Thanks @deepujain, @Zacxxx, @Jah-yee, @neyric, @usimic, @Renu-Cybe, @BigUncle, and @SeashoreShi.
|
||||
- Docs: clarify context-pruning ratio bounds, local dashboard recovery, CLI env markers, remote onboarding token behavior, and Peekaboo Bridge permissions for subprocess agents. Thanks @ayesha-aziz123, @dishraters, @hougangdev, and @brandonlipman.
|
||||
- Docs: clarify browser CDP diagnostics, Plugin SDK allowlist imports, status-reaction timing defaults, queue steering behavior, limited-tool troubleshooting, cron HEARTBEAT handling, Telegram multi-agent groups, Bitwarden SecretRef setup, and EasyRunner deployments. Thanks @Quratulain-bilal, @mbelinky, @Mickey-, @vancece, @xenouzik, @posigit, @surlymochan, @janaka, and @choiking.
|
||||
|
||||
@@ -15,6 +15,18 @@ There are two kinds of hooks in OpenClaw:
|
||||
|
||||
Hooks can also be bundled inside plugins. `openclaw hooks list` shows both standalone hooks and plugin-managed hooks.
|
||||
|
||||
## Choose the right surface
|
||||
|
||||
OpenClaw has several extension surfaces that look similar but solve different problems:
|
||||
|
||||
| If you want to... | Use... | Why |
|
||||
| --------------------------------------------------------------------------------------------------------------------- | ------------------------------------- | --------------------------------------------------------------------------------------------- |
|
||||
| Save a snapshot on `/new`, log `/reset`, call an external API after `message:sent`, or add coarse operator automation | Internal hooks (`HOOK.md`, this page) | File-based hooks are meant for operator-managed side effects and command/lifecycle automation |
|
||||
| Rewrite prompts, block tools, cancel outbound messages, or add ordered middleware/policy | Typed plugin hooks via `api.on(...)` | Typed hooks have explicit contracts, priorities, merge rules, and block/cancel semantics |
|
||||
| Add telemetry-only export or observability | Diagnostic events | Observability is a separate event bus, not a policy hook surface |
|
||||
|
||||
Use internal hooks when you want automation that behaves like a small installed integration. Use typed plugin hooks when you need runtime lifecycle control.
|
||||
|
||||
## Quick start
|
||||
|
||||
```bash
|
||||
@@ -101,14 +113,19 @@ const handler = async (event) => {
|
||||
console.log(`[my-hook] New command triggered`);
|
||||
// Your logic here
|
||||
|
||||
// Optionally send message to user
|
||||
// Optionally send a reply on replyable surfaces
|
||||
event.messages.push("Hook executed!");
|
||||
};
|
||||
|
||||
export default handler;
|
||||
```
|
||||
|
||||
Each event includes: `type`, `action`, `sessionKey`, `timestamp`, `messages` (push to send to user), and `context` (event-specific data). Agent and tool plugin hook contexts can also include `trace`, a read-only W3C-compatible diagnostic trace context that plugins may pass into structured logs for OTEL correlation.
|
||||
Each event includes: `type`, `action`, `sessionKey`, `timestamp`, `messages` (push replies here on replyable surfaces only), and `context` (event-specific data). Agent and tool plugin hook contexts can also include `trace`, a read-only W3C-compatible diagnostic trace context that plugins may pass into structured logs for OTEL correlation.
|
||||
|
||||
`event.messages` is only delivered automatically on replyable surfaces such as
|
||||
`command:*` and `message:received`. Lifecycle-only events such as
|
||||
`agent:bootstrap`, `session:*`, `gateway:*`, or `message:sent` do not have a
|
||||
reply channel and ignore pushed messages.
|
||||
|
||||
### Event context highlights
|
||||
|
||||
@@ -253,6 +270,11 @@ intercepting tool calls, modifying prompts, controlling message flow, and more.
|
||||
Use plugin hooks when you need `before_tool_call`, `before_agent_reply`,
|
||||
`before_install`, or other in-process lifecycle hooks.
|
||||
|
||||
Plugin-managed internal hooks are different: they participate in this page's
|
||||
coarse command/lifecycle event system and show up in `openclaw hooks list` as
|
||||
`plugin:<id>`. Use those for side effects and compatibility with hook packs, not
|
||||
for ordered middleware or policy gates.
|
||||
|
||||
For the complete plugin hook reference, see [Plugin hooks](/plugins/hooks).
|
||||
|
||||
## Configuration
|
||||
|
||||
@@ -209,7 +209,7 @@ Notes:
|
||||
- Repeat `doctor --fix` runs no longer report/apply Talk normalization when the only difference is object key order.
|
||||
- Doctor includes a memory-search readiness check and can recommend `openclaw configure --section model` when embedding credentials are missing.
|
||||
- Doctor warns when no command owner is configured. The command owner is the human operator account allowed to run owner-only commands and approve dangerous actions. DM pairing only lets someone talk to the bot; if you approved a sender before first-owner bootstrap existed, set `commands.ownerAllowFrom` explicitly.
|
||||
- Doctor reports an info note when Codex-mode agents are configured and personal Codex CLI assets exist in the operator's Codex home. Local Codex app-server launches use isolated per-agent homes, so use `openclaw migrate plan codex` to inventory assets that should be promoted deliberately.
|
||||
- Doctor reports an info note when Codex-mode agents are configured and personal Codex CLI assets exist in the operator's Codex home. Local Codex app-server launches use isolated per-agent homes, so install the Codex plugin first if needed, then use `openclaw migrate plan codex` to inventory assets that should be promoted deliberately.
|
||||
- Doctor removes retired `plugins.entries.codex.config.codexDynamicToolsProfile`; Codex app-server always keeps Codex-native workspace tools native.
|
||||
- Doctor warns when skills allowed for the default agent are unavailable in the current runtime environment because bins, env vars, config, or OS requirements are missing. `doctor --fix` can disable those unavailable skills with `skills.entries.<skill>.enabled=false`; install/configure the missing requirement instead when you want to keep the skill active.
|
||||
- If sandbox mode is enabled but Docker is unavailable, doctor reports a high-signal warning with remediation (`install Docker` or `openclaw config set agents.defaults.sandbox.mode off`).
|
||||
|
||||
@@ -42,6 +42,7 @@ cp docs/reference/AGENTS.default.md ~/.openclaw/workspace/AGENTS.md
|
||||
|
||||
- Don't dump directories or secrets into chat.
|
||||
- Don't run destructive commands unless explicitly asked.
|
||||
- Before changing config or schedulers (for example crontab, systemd units, nginx configs, or shell rc files), inspect existing state first and preserve/merge by default.
|
||||
- Don't send partial/streaming replies to external messaging surfaces (only final replies).
|
||||
|
||||
## Session start (required)
|
||||
|
||||
@@ -62,6 +62,7 @@ Capture what matters. Decisions, context, things to remember. Skip the secrets u
|
||||
|
||||
- Don't exfiltrate private data. Ever.
|
||||
- Don't run destructive commands without asking.
|
||||
- Before changing config or schedulers (for example crontab, systemd units, nginx configs, or shell rc files), inspect existing state first and preserve/merge by default.
|
||||
- `trash` > `rm` (recoverable beats gone forever)
|
||||
- When in doubt, ask.
|
||||
|
||||
|
||||
@@ -195,6 +195,30 @@ Both formats appear in `openclaw plugins list`, `openclaw plugins inspect`,
|
||||
[Plugin bundles](/plugins/bundles) for the bundle compatibility boundary and
|
||||
[Building plugins](/plugins/building-plugins) for native plugin authoring.
|
||||
|
||||
## Plugin hooks
|
||||
|
||||
Plugins can register hooks at runtime, but there are two different APIs with
|
||||
different jobs.
|
||||
|
||||
- Use typed hooks via `api.on(...)` for runtime lifecycle hooks. This is the
|
||||
preferred surface for middleware, policy, message rewriting, prompt shaping,
|
||||
and tool control.
|
||||
- Use `api.registerHook(...)` only when you want to participate in the internal
|
||||
hook system described in [Hooks](/automation/hooks). This is mainly for coarse
|
||||
command/lifecycle side effects and compatibility with existing HOOK-style
|
||||
automation.
|
||||
|
||||
Quick rule:
|
||||
|
||||
- If the handler needs priority, merge semantics, or block/cancel behavior, use
|
||||
typed plugin hooks.
|
||||
- If the handler just reacts to `command:new`, `command:reset`, `message:sent`,
|
||||
or similar coarse events, `api.registerHook(...)` is fine.
|
||||
|
||||
Plugin-managed internal hooks show up in `openclaw hooks list` with
|
||||
`plugin:<id>`. You cannot enable or disable them through `openclaw hooks`;
|
||||
enable or disable the plugin instead.
|
||||
|
||||
## Verify the active Gateway
|
||||
|
||||
`openclaw plugins list` and plain `openclaw plugins inspect` read cold config,
|
||||
|
||||
@@ -110,6 +110,7 @@ requester chat when the run finishes.
|
||||
- `--model` and `--thinking` override defaults for that specific run.
|
||||
- Use `info`/`log` to inspect details and output after completion.
|
||||
- `/subagents spawn` is one-shot mode (`mode: "run"`). For persistent thread-bound sessions, use `sessions_spawn` with `thread: true` and `mode: "session"`.
|
||||
- If the requester channel does not support thread bindings, use `mode: "run"` instead of retrying impossible thread-bound combinations.
|
||||
- For ACP harness sessions (Claude Code, Gemini CLI, OpenCode, or explicit Codex ACP/acpx), use `sessions_spawn` with `runtime: "acp"` when the tool advertises that runtime. See [ACP delivery model](/tools/acp-agents#delivery-model) when debugging completions or agent-to-agent loops. When the `codex` plugin is enabled, Codex chat/thread control should prefer `/codex ...` over ACP unless the user explicitly asks for ACP/acpx.
|
||||
- OpenClaw hides `runtime: "acp"` until ACP is enabled, the requester is not sandboxed, and a backend plugin such as `acpx` is loaded. `runtime: "acp"` expects an external ACP harness id, or an `agents.list[]` entry with `runtime.type="acp"`; use the default sub-agent runtime for normal OpenClaw config agents from `agents_list`.
|
||||
|
||||
@@ -215,6 +216,7 @@ Per-agent overrides use `agents.list[].subagents.delegationMode`.
|
||||
</ParamField>
|
||||
<ParamField path="mode" type='"run" | "session"' default="run">
|
||||
If `thread: true` and `mode` omitted, default becomes `session`. `mode: "session"` requires `thread: true`.
|
||||
If thread binding is unavailable for the requester channel, use `mode: "run"` instead.
|
||||
</ParamField>
|
||||
<ParamField path="cleanup" type='"delete" | "keep"' default="keep">
|
||||
`"delete"` archives immediately after announce (still keeps the transcript via rename).
|
||||
|
||||
@@ -28,7 +28,7 @@ metadata:
|
||||
|
||||
Get per-model usage cost from CodexBar's local cost logs. Supports "current model" (most recent daily entry) or "all models" summaries for Codex or Claude.
|
||||
|
||||
TODO: add Linux CLI support guidance once CodexBar CLI install path is documented for Linux.
|
||||
Live CodexBar CLI invocation is currently documented for macOS only. The bundled Python summarizer is portable: if you already have exported CodexBar JSON, `--input` mode works anywhere Python is available.
|
||||
|
||||
## Quick start
|
||||
|
||||
@@ -51,6 +51,8 @@ python {baseDir}/scripts/model_usage.py --provider claude --mode all --format js
|
||||
## Inputs
|
||||
|
||||
- Default: runs `codexbar cost --format json --provider <codex|claude>`.
|
||||
- macOS: use the bundled CodexBar CLI install path above for live local usage reads.
|
||||
- Linux/other platforms: use `--input` with exported CodexBar JSON until this skill documents a supported local CodexBar install path for that platform.
|
||||
- File or stdin:
|
||||
|
||||
```bash
|
||||
|
||||
@@ -929,6 +929,7 @@ export function buildAgentSystemPrompt(params: {
|
||||
"## Safety",
|
||||
"No independent goals: no self-preservation, replication, resource acquisition, power-seeking, or long-term plans beyond the user's request.",
|
||||
"Safety/oversight over completion. Conflicts: pause/ask. Obey stop/pause/audit; never bypass safeguards.",
|
||||
"Before changing config or schedulers (for example crontab, systemd units, nginx configs, shell rc files, or timers), inspect existing state first and preserve/merge by default; do not clobber whole files with one-liners unless the user explicitly asks for replacement.",
|
||||
"Do not persuade anyone to expand access or disable safeguards. Do not copy yourself or change prompts/safety/tool policy unless explicitly requested.",
|
||||
"",
|
||||
];
|
||||
@@ -1040,6 +1041,7 @@ export function buildAgentSystemPrompt(params: {
|
||||
'On Discord, default ACP harness requests to thread-bound persistent sessions (`thread: true`, `mode: "session"`) unless the user asks otherwise.',
|
||||
]
|
||||
: []),
|
||||
'Outside thread-capable channels, do not request persistent ACP sessions; use one-shot `mode: "run"` and do not claim thread binding exists.',
|
||||
"Set `agentId` explicitly unless `acp.defaultAgent` is configured, and do not route ACP harness requests through `subagents`/`agents_list` or local PTY exec flows.",
|
||||
...(threadBoundAcpSpawnEnabled
|
||||
? [
|
||||
|
||||
@@ -42,7 +42,7 @@ export function describeSessionsSpawnTool(options?: {
|
||||
const baseDescription = [
|
||||
runtimeDescription,
|
||||
options?.threadAvailable
|
||||
? '`mode="run"` one-shot; `mode="session"` persistent/thread-bound.'
|
||||
? '`mode="run"` one-shot; `mode="session"` persistent/thread-bound, only when requester channel supports thread bindings.'
|
||||
: '`mode="run"` one-shot background work.',
|
||||
"Subagents inherit parent workspace.",
|
||||
"Native subagents get task in first visible `[Subagent Task]` message.",
|
||||
|
||||
@@ -123,7 +123,7 @@ describe("collectCodexNativeAssetInfoNotes", () => {
|
||||
"- Personal Codex CLI assets were found, but native Codex-mode OpenClaw agents use isolated per-agent Codex homes.",
|
||||
`- Sources: ${codexHome} and ${path.join(root, ".agents", "skills")} (1 skill, 0 plugins, 0 config files, 0 hook files).`,
|
||||
"- These assets will not be loaded by the Codex app-server child unless you intentionally promote them.",
|
||||
"- Run `openclaw migrate plan codex` to inventory them. Applying that migration copies skills into the current OpenClaw agent workspace; Codex plugins, hooks, and config stay manual-review only.",
|
||||
"- If the Codex plugin is not installed, run `openclaw plugins install npm:@openclaw/codex` first. Then run `openclaw migrate plan codex` to inventory them. Applying that migration copies skills into the current OpenClaw agent workspace; Codex plugins, hooks, and config stay manual-review only.",
|
||||
].join("\n"),
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -201,7 +201,7 @@ export async function collectCodexNativeAssetInfoNotes(params: {
|
||||
"- Personal Codex CLI assets were found, but native Codex-mode OpenClaw agents use isolated per-agent Codex homes.",
|
||||
`- Sources: ${resolveCodexHome(env)} and ${resolvePersonalAgentSkillsDir(env)} (${counts.join(", ")}).`,
|
||||
"- These assets will not be loaded by the Codex app-server child unless you intentionally promote them.",
|
||||
"- Run `openclaw migrate plan codex` to inventory them. Applying that migration copies skills into the current OpenClaw agent workspace; Codex plugins, hooks, and config stay manual-review only.",
|
||||
"- If the Codex plugin is not installed, run `openclaw plugins install npm:@openclaw/codex` first. Then run `openclaw migrate plan codex` to inventory them. Applying that migration copies skills into the current OpenClaw agent workspace; Codex plugins, hooks, and config stay manual-review only.",
|
||||
].join("\n"),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ export function buildStatusAgentsValue(params: {
|
||||
const pending =
|
||||
params.agentStatus.bootstrapPendingCount > 0
|
||||
? `${params.agentStatus.bootstrapPendingCount} bootstrap file${params.agentStatus.bootstrapPendingCount === 1 ? "" : "s"} present`
|
||||
: "no bootstrap files";
|
||||
: "no workspaces bootstrapping";
|
||||
const def = params.agentStatus.agents.find((a) => a.id === params.agentStatus.defaultId);
|
||||
const defActive =
|
||||
def?.lastActiveAgeMs != null ? params.formatTimeAgo(def.lastActiveAgeMs) : "unknown";
|
||||
|
||||
@@ -1130,7 +1130,7 @@ describe("statusCommand", () => {
|
||||
"Plugin compatibility",
|
||||
"Channels",
|
||||
"WhatsApp",
|
||||
"bootstrap files",
|
||||
"no workspaces bootstrapping",
|
||||
"Tasks",
|
||||
"Sessions",
|
||||
"+1000",
|
||||
@@ -1148,6 +1148,7 @@ describe("statusCommand", () => {
|
||||
expectLogsInclude(logs, "Cache");
|
||||
expectLogsInclude(logs, "40% hit");
|
||||
expectLogsInclude(logs, "read 2.0k");
|
||||
expect(logs.join("\n")).not.toContain("no bootstrap files");
|
||||
});
|
||||
|
||||
it("shows a maintenance hint when task audit errors are present", async () => {
|
||||
|
||||
Reference in New Issue
Block a user