Skip to content

feat: skip Supermemory for subagents, headless runs and helper prompts by default - #70

Open
Dhravya wants to merge 2 commits into
mainfrom
capy/skip-subagent-headless-capture
Open

Dhravya wants to merge 2 commits into
mainfrom
capy/skip-subagent-headless-capture

Conversation

@Dhravya

@Dhravya Dhravya commented Nov 7, 2026 •

Copy link
Copy Markdown
Member

By default the plugin now makes zero Supermemory calls from its before_prompt_build (recall) and agent_end (capture) hooks for OpenClaw subagent sessions, host helper runs, host-generated inputs, and headless runs. Interactive TUI / Control UI / channel turns behave exactly as before. Two opt-in flags restore today's behaviour.

What is detected and how (OpenClaw's own signals)

Checked against openclaw/openclaw main @ 7ab0143 and the published openclaw@2026.11.1 CLI.

Class Host signal Source
Subagents ctx.sessionKey contains a subagent: segment (agent:<id>:subagent:<uuid>, incl. incognito- and nested) docs/tools/subagents.md ("Each one runs in its own session (agent:<agentId>:subagent:<uuid>)"), src/sessions/session-key-utils.ts isSubagentSessionKey / getSubagentDepth
Host helper runs session-key segments the host mints for its own runs: active-memory: (active-memory recall run, extensions/active-memory/recall-run.ts), helper: (session-memory slug generator, src/hooks/bundled/session-memory/handler.ts), update-repair: (src/infra/update-repair-agent.runtime.ts), internal-session-effects: (session forks, side-chat companion, memory flush, src/config/sessions/internal-session-key.ts), dreaming-narrative- (isDreamingNarrativeSessionStoreKey) as listed
Host-generated input (e.g. a subagent announcing its result into the parent session) inputProvenance.kind is inter_session or internal_system: ctx.inputProvenance on before_prompt_build, the last user message's provenance on agent_end src/sessions/input-provenance.ts isHostGeneratedInputProvenance; docs/plugins/hooks/prompt-and-session.md ("ctx.trigger === "user" is a run trigger, not an origin classification … Use typed provenance to distinguish those inputs")
Headless OpenClaw has no explicit "headless" flag in hook context. openclaw agent exec ("Run one isolated headless embedded agent turn", src/cli/program/register.agent-turn.ts; "exec matches no channel", src/commands/agent-exec-input.ts) and scripted openclaw agent --message turns run with no messageProvider/channel, while every interactive surface stamps one (TUI/Control UI webchat = INTERNAL_MESSAGE_CHANNEL, chat channels, node, system agent openclaw). A run is treated as headless when ctx.trigger is set and both fields are empty; hosts that predate ctx.trigger keep the legacy behaviour. src/utils/message-channel-constants.ts, src/agents/command/run-embedded-attempt.ts, observed ctx below

Existing cron / heartbeat / memory-flush skips are unchanged. Subagents inherit messageProvider: "webchat" and trigger: "user" from their parent (observed below), so the session key is the only usable subagent signal.

Opt-in flags (plugin config in openclaw.json, or env for the OpenClaw process; each re-enables both recall and capture for its class):

  • captureSubagents: true / SUPERMEMORY_CAPTURE_SUBAGENTS=true: subagents, helper runs, host-generated inputs
  • captureHeadless: true / SUPERMEMORY_CAPTURE_HEADLESS=true: headless runs (a subagent spawned from a headless run needs both)

Stored data, container tags, customIds, and metadata shapes are untouched; explicit memory tool calls are unaffected. README and CHANGELOG are updated.

Verification on the real host

openclaw@2026.11.1 from npm, gateway + openclaw tui driven in a tmux pty (interactive), openclaw agent exec and openclaw agent --message (headless). The model was a local OpenAI-compatible stub (models.providers.stub, api: "openai-completions") that returns a sessions_spawn tool call when the prompt says SPAWNCHILD, so the host spawned a real agent:main:subagent:<uuid> session. The plugin was pointed at a recording Supermemory stub (baseUrl: http://127.0.0.1:18081, dummy sm_ key) that logs every method+path. The same 4-step script ran per scenario (stub servers and scripts are not committed):

Step main (before) this PR default captureSubagents config SUPERMEMORY_CAPTURE_SUBAGENTS=true captureHeadless config SUPERMEMORY_CAPTURE_HEADLESS=true
1 interactive TUI turn 2 2 2 2 2 2
2 TUI turn that spawns a subagent 6 2 (parent turn only) 6 6 2 2
3 openclaw agent exec 2 0 0 0 2 2
4 openclaw agent --message (gateway, no channel) 2 0 0 0 2 2
total 12 4 8 8 8 8

Default run, Supermemory stub log (all calls):

STEP 1 interactive TUI turn
  POST /v4/profile q="I prefer dark roast coffee every morning"
  POST /v3/documents content="[role: user]\nI prefer dark roast coffee every morning ..."
STEP 2 TUI turn that spawns a subagent (sessions_spawn)
  POST /v4/profile q="Please SPAWNCHILD a worker to check the build"
  POST /v3/documents content="[role: user]\nPlease SPAWNCHILD a worker to check the build ..."
STEP 3 headless: openclaw agent exec
STEP 4 headless: scripted openclaw agent --message via gateway
total supermemory calls: 4

Hook contexts the host passed in that run (from a second, logging-only plugin), showing the subagent and the announce turn really ran:

before_prompt_build agent:main:main trigger=user provider=webchat
subagent_spawned child=agent:main:subagent:d19f29a6-…
agent_end agent:main:main trigger=user provider=webchat lastUser.provenance={"kind":"external_user"}
before_prompt_build agent:main:subagent:d19f29a6-… trigger=user provider=webchat
agent_end agent:main:subagent:d19f29a6-… trigger=user provider=webchat
before_prompt_build agent:main:main trigger=user provider=webchat ctx.inputProvenance={"kind":"inter_session",…,"sourceTool":"subagent_announce"}
agent_end agent:main:main trigger=user provider=webchat lastUser.provenance={"kind":"inter_session",…,"sourceTool":"subagent_announce"}
before_prompt_build agent:main:explicit:c3873ca1-… trigger=user provider=undefined   (agent exec)
before_prompt_build agent:main:main trigger=user provider=undefined                    (agent --message)

On main, the 4 extra calls in step 2 were the subagent's own profile + capture and the parent's capture of [Inter-session message] sourceSession=agent:main:subagent:….

The helper-run session keys (active-memory, helper, update-repair, internal-session-effects, dreaming) were verified by replaying the host's key shapes and triggers through the hook handlers, not by driving those host features live: 0 calls by default, 2 with captureSubagents. Interactive webchat, a Telegram-shaped context, the system agent (manual / openclaw), and a legacy context without trigger keep their 2 calls in every configuration.

bun run check-types and biome ci . (CI's 2.3.8) pass. The repo has no test suite.

Not detectable / out of scope

  • OpenClaw exposes no explicit headless flag to plugins. A scripted gateway turn that names a channel (openclaw agent --channel … --deliver) carries that channel and is treated as interactive.
  • ACP sessions (agent:<id>:acp:…, external Codex/Claude harnesses via sessions_spawn runtime: "acp") run outside OpenClaw's embedded hooks, so this plugin never saw them and nothing changes.
  • Session titles and conversation labels (src/gateway/dashboard-session-title.ts, src/auto-reply/reply/conversation-label-generator.ts) go through runUtilityCompletion (src/agents/utility-completion.ts), a plain completion that never fires before_prompt_build/agent_end, so the plugin never saw them. I did not find a separate branch-name generator.

Open in Capy

…s by default

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
… turns (#71)

* fix: match helper session keys like OpenClaw, keep recall for host-generated turns, let env override config

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

* chore(release): 2.2.0

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>

---------

Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants