Skip to content

fix: prevent memory pollution and API waste on automated runs (Resolves #20)#52

Open
franksde wants to merge 2 commits into
supermemoryai:mainfrom
franksde:fix/automated-runs-guard
Open

fix: prevent memory pollution and API waste on automated runs (Resolves #20)#52
franksde wants to merge 2 commits into
supermemoryai:mainfrom
franksde:fix/automated-runs-guard

Conversation

@franksde
Copy link
Copy Markdown

Summary

Currently, Supermemory executes recall and capture hooks on all agent turns, including automated background tasks like heartbeat and cron. This leads to significant token waste and pollutes the memory database with irrelevant background logs.

While there is an existing SKIPPED_PROVIDERS array in capture.ts, it is insufficient because automated triggers often lack a distinct messageProvider.

Now that the OpenClaw SDK exposes the trigger field in the hook context (merged in openclaw/openclaw#24585), we can accurately identify and skip non-interactive automated runs.

Key Changes

  • hooks/recall.ts: Safely extracts ctx.trigger. If the trigger exists and is NOT "user" or "manual", it skips the memory recall process entirely.
  • hooks/capture.ts: Applies the same trigger-based whitelist before deciding to capture memories, working alongside the existing SKIPPED_PROVIDERS check.

Compatibility

This change is 100% backward compatible. If a user is on an older version of OpenClaw where ctx.trigger is undefined, the logic safely bypasses the guard and falls back to the legacy behavior.

Resolves #20

@franksde
Copy link
Copy Markdown
Author

@Dhravya mind taking a look when you have a moment? Happy to adjust if the approach doesn't fit.

Copy link
Copy Markdown
Contributor

@vorflux vorflux Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The approach is sound and backward-compatible. A few things worth fixing:

Comment thread hooks/capture.ts Outdated
const provider = ctx.messageProvider as string
if (SKIPPED_PROVIDERS.includes(provider)) {
const trigger = ctx.trigger as string | undefined
const isAutomatedRun = trigger && trigger !== "user" && trigger !== "manual"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The log.info fires before this guard (line 33), so automated runs still produce log noise. Move the trigger check above the log.info call.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved the trigger guard above the capture log now, so automated runs return before agent_end fired gets emitted.

Comment thread hooks/recall.ts Outdated
ctx?: Record<string, unknown>,
) => {
const trigger = ctx?.trigger as string | undefined
if (trigger && trigger !== "user" && trigger !== "manual") {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The trigger check is duplicated verbatim in both files. Extract it to a shared helper, e.g. isInteractiveTrigger(trigger: string | undefined): boolean in a utils file, to avoid drift if the allowed values ever change.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pulled this into hooks/trigger.ts and reused it from both hooks. That keeps the allowlist in one place if OpenClaw adds or renames trigger values later.

Comment thread hooks/capture.ts Outdated
const provider = ctx.messageProvider as string
if (SKIPPED_PROVIDERS.includes(provider)) {
const trigger = ctx.trigger as string | undefined
const isAutomatedRun = trigger && trigger !== "user" && trigger !== "manual"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The allowlist ("user" | "manual") is implicit — if openclaw ever ships a new interactive trigger type (e.g. "api" or "webhook"), it will be silently blocked without any obvious failure. A comment noting where these values come from (openclaw trigger enum) would help future maintainers.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a short note next to the shared helper explaining that user and manual are the interactive OpenClaw triggers, while undefined stays allowed for older OpenClaw versions.

@ved015
Copy link
Copy Markdown
Member

ved015 commented May 20, 2026

@franksde can you pls have a look at the suggestions

@franksde
Copy link
Copy Markdown
Author

Pushed an update for the review suggestions. The trigger check now happens before capture logging, and the interactive trigger allowlist lives in a shared helper with a short note about the OpenClaw trigger values and legacy undefined behavior.

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.

Feature Request: Add skipOnHeartbeat Configuration Option

2 participants