Skip to content

feat(retrieval,agent-memory): add PostHog product telemetry (TS + PY)#281

Open
KIvanow wants to merge 1 commit into
masterfrom
feat/retrieval-agent-memory-posthog-analytics
Open

feat(retrieval,agent-memory): add PostHog product telemetry (TS + PY)#281
KIvanow wants to merge 1 commit into
masterfrom
feat/retrieval-agent-memory-posthog-analytics

Conversation

@KIvanow

@KIvanow KIvanow commented Jun 25, 2026

Copy link
Copy Markdown
Member

Mirror the agent-cache/semantic-cache analytics pattern across the retrieval and agent-memory packages in both TypeScript and Python: optional posthog dependency with a noop fallback, build-time baked-key placeholders, BETTERDB_TELEMETRY opt-out, and a Valkey-persisted instance-id UUID. Captures *_init and index_created events.

Wires POSTHOG_API_KEY/POSTHOG_HOST build env into the four release workflows so the keys bake into published artifacts.

Summary

Changes

Checklist

  • Unit / integration tests added
  • Docs added / updated
  • Roborev review passed — run roborev review --branch or /roborev-review-branch in Claude Code (internal)
  • Competitive analysis done / discussed (internal)
  • Blog post about it discussed (internal)

Note

Medium Risk
Published wheels/npm tarballs may embed a PostHog API key when release secrets are set, and telemetry is on by default unless users set BETTERDB_TELEMETRY or disable analytics—privacy-sensitive but mitigated by opt-out and fail-safe no-op paths.

Overview
Adds optional PostHog product analytics to @betterdb/agent-memory, @betterdb/retrieval, and their Python wheels, following the existing agent-cache pattern.

Each package gets an analytics module with a no-op fallback, BETTERDB_TELEMETRY opt-out, and a stable instance UUID stored in Valkey at {name}:__instance_id. Stores emit prefixed init events (memory_init / retriever_init) on first async lifecycle use and index_created when a new vector index is created. Analytics is wired into MemoryStore / Retriever with constructor flags to disable, shutdown on close(), and errors never propagate to callers.

Release builds can bake defaults via POSTHOG_API_KEY and POSTHOG_HOST: Python uses a Hatch hatch_build.py hook; TypeScript runs inject-telemetry-defaults.mjs after tsc. All four npm/PyPI release workflows pass those secrets at build time. posthog / posthog-node are added as dependencies, with unit tests for opt-out, noop paths, and PostHog behavior.

Reviewed by Cursor Bugbot for commit 34a568f. Bugbot is set up for automated code reviews on this repo. Configure here.

Mirror the agent-cache/semantic-cache analytics pattern across the
retrieval and agent-memory packages in both TypeScript and Python:
optional posthog dependency with a noop fallback, build-time baked-key
placeholders, BETTERDB_TELEMETRY opt-out, and a Valkey-persisted
instance-id UUID. Captures *_init and index_created events.

Wires POSTHOG_API_KEY/POSTHOG_HOST build env into the four release
workflows so the keys bake into published artifacts.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 34a568f. Configure here.

throw err;
}
}
this.analytics.capture('index_created', { dims });

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Spurious index_created event

Low Severity

When createIndex swallows an already exists error from concurrent FT.CREATE, it still emits index_created even though this worker did not create the index. The Python retriever returns before capturing in that case, so telemetry can over-count index creation on multi-worker boot.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 34a568f. Configure here.

}
const dims = await this.resolveDims();
await this.client.call('FT.CREATE', ...buildMemoryIndexArgs(this.name, dims));
this.analytics.capture('index_created', { dims });

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

index_created before analytics ready

Low Severity

index_created is captured on the default no-op analytics instance if ensureIndex or createIndex finishes before the constructor’s async createAnalytics chain assigns the real client. Python memory and retrieval await analytics startup before index work, so those builds can miss the event.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 34a568f. Configure here.

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.

1 participant