feat(skills): suggest saving detected reusable workflows by default#100692
Conversation
…95477) Adds the middle tier between capture-off and autonomous capture: when autonomy is disabled, detected durable-instruction signals record a one-shot pendingSkillSuggestion on the session entry (signal-hash fingerprint prevents transcript-history replay), and the next non-heartbeat turn atomically consumes it and injects one bounded user-role line offering to save the skill. The agent offers, the user decides; skill_workshop approval flow unchanged; no new config.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 842163cfe5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const consumed = await consumeSessionSkillSuggestion({ | ||
| agentId, | ||
| sessionKey, | ||
| storePath, | ||
| }); |
There was a problem hiding this comment.
Defer consuming suggestions until a run is admitted
When a session has pendingSkillSuggestion, this clears it before active-run admission has succeeded. If a new non-heartbeat message arrives while the previous run is still active, resolvePreparedReplyQueueState can return the “Previous run is still shutting down” reply after waiting (src/auto-reply/reply/get-reply-run-queue.ts:43-52), so runReplyAgent is never called and the projected context is never shown; the persisted suggestion has already been removed, so the next real turn will not offer to save the workflow. Consume only after admission is guaranteed to continue, or restore the flag on early reply paths.
Useful? React with 👍 / 👎.
* origin/main: (1287 commits) fix(android): block loopback canvas navigation (openclaw#99874) fix(hooks): suppress unhandled stdout/stderr stream errors in gmail watcher (openclaw#100519) fix(memory-core): guard qmd mcporter JSON.parse against non-JSON stdout (openclaw#98381) fix(build): fall back to tsx for build TypeScript scripts (openclaw#91262) feat(skills): suggest saving detected reusable workflows by default (openclaw#95477) (openclaw#100692) docs(changelog): remove generated release-note entries feat(telegram): offer BotFather web app flow in setup help and docs (openclaw#100540) fix(ios): unify Talk and Settings row typography on one branded detail row (openclaw#100515) feat(gateway): add persisted crash-loop breaker and fatal-config exit contract refactor(macos): lock and unify PortGuardian tunnel record persistence so concurrent app instances cannot lose orphan records (openclaw#100601) fix: stop reconnecting on protocol mismatch (openclaw#98414) fix(maint): reuse recent hosted gates after rebase (openclaw#100663) fix(ui): reopen web terminals without stale content (openclaw#100665) fix(browser): diagnose empty WSL2 Chrome replies (openclaw#100590) fix(ios): chat snaps back to bottom when scrolling to top via status-bar tap (openclaw#100502) Treat already-compacted CLI compaction as no-op (openclaw#99136) docs(changelog): remove direct main fix entry fix(feishu): strip internal tool-trace banners from outbound text (openclaw#98705) fix(message): thread --limit through to CLI formatter and surface provider pagination hints (openclaw#99089) fix(voyage): close response body stream when batch output JSONL parsing throws (openclaw#98840) ... # Conflicts: # extensions/memory-wiki/package.json
…penclaw#95477) (openclaw#100692) Adds the middle tier between capture-off and autonomous capture: when autonomy is disabled, detected durable-instruction signals record a one-shot pendingSkillSuggestion on the session entry (signal-hash fingerprint prevents transcript-history replay), and the next non-heartbeat turn atomically consumes it and injects one bounded user-role line offering to save the skill. The agent offers, the user decides; skill_workshop approval flow unchanged; no new config.
…penclaw#95477) (openclaw#100692) Adds the middle tier between capture-off and autonomous capture: when autonomy is disabled, detected durable-instruction signals record a one-shot pendingSkillSuggestion on the session entry (signal-hash fingerprint prevents transcript-history replay), and the next non-heartbeat turn atomically consumes it and injects one bounded user-role line offering to save the skill. The agent offers, the user decides; skill_workshop approval flow unchanged; no new config.
What Problem This Solves
Skill capture had two modes with nothing in between: off (the default — durable-instruction signals detected at agent-end were silently dropped) and
skills.workshop.autonomous.enabled(proposals filed directly). Users repeatedly ask for the agent to get better at repeated tasks, but full autonomous capture stays opt-in for good reasons. The detection machinery already existed and did nothing for the default configuration.Closes #95477 (scoped: suggestion tier; full post-task self-reflection remains future work).
Why This Change Was Made
Default-on suggest tier between off and autonomous, reusing existing seams end to end:
runSkillResearchAutoCapture(src/skills/research/autocapture.ts): when autonomy is off, the same signal extraction now records a one-shotpendingSkillSuggestionon the session entry instead of returning early. Same eligibility gates (success only; no cron/heartbeat/subagent/active-memory sessions), same pending-proposal dedupe, plus a live-skill guard (existing skills don't get "save this as a skill" suggestions).lastSkillSuggestionSignalHashfingerprint (sha256 of the signal evidence) is stored alongside, so the same correction re-extracted from transcript history on later turns never re-suggests — the invariant the coordinated capture design (improve: skill auto-capture catches reactive corrections and routes them to existing skills #100576 review) requires, landed here first.src/config/sessions/skill-suggestions.ts): atomic record/consume viapatchSessionEntry— an unconsumed suggestion is never replaced, the next non-heartbeat interactive turn atomically clears the flag and injects exactly one user-role context line (inbound-meta.ts, same seam and conventions as the active-goal line from feat(goals): keep active session goals in per-turn context + continuance QA scenarios #100468, quote-sanitized and length-bounded):A reusable workflow ("<skillName>") was detected last turn — offer to save it as a skill via skill_workshop if the user agrees.Competing/queued turns see cleared state; heartbeats neither inject nor consume.
skill_workshoppending/approval flow.autonomous.enabledbehavior is unchanged (direct proposals, no suggestion line).pendingSkillSuggestion+ fingerprint registered as reserved session-entry slot keys). System prompt and prior transcript bytes untouched.User Impact
Out of the box, OpenClaw now notices "from now on…"-style durable instructions and offers — once, on the next turn — to save them as a reviewable skill. Saying yes produces a normal pending Skill Workshop proposal; ignoring it costs nothing further. Operators who enabled autonomous capture see no change. Docs: "Suggested skills" section in skill-workshop.
Evidence
src/skills/research/autocapture.test.ts(suggest recorded on default config; not recorded when autonomous/signal absent/pending proposal/live skill/blocked trigger; fingerprint replay guard),src/auto-reply/reply/inbound-meta.test.ts(line format, sanitization, absence),src/auto-reply/reply/get-reply-run.media-only.test.ts(one-shot consume, heartbeat exclusion, queued-turn behavior).git diff --check, formatting, docs formatting clean.feat— the Skill Workshop now suggests saving detected reusable workflows by default; the agent offers, the user decides, approval flow unchanged.