Skip to content

AGE-2737: call Zep through its official SDK - #1305

Open
hary73 wants to merge 3 commits into
mainfrom
hary/zep-sdk
Open

hary73 wants to merge 3 commits into
mainfrom
hary/zep-sdk

Conversation

@hary73

@hary73 hary73 commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Moves every Zep call in the memory provider from hand-written HTTP requests to the official Zep SDK (@getzep/zep-cloud 4.1.0), so we no longer define or maintain Zep's request and response types ourselves.

Fixes AGE-2737

Changes

  • ZepMemoryProvider now uses the SDK's typed methods for user lookup/create/node, thread create, add/list messages, edge search and episode add.
  • Removed the 4 zod response schemas, the hand-written request helper (URL building, timeouts, retry/backoff, Retry-After parsing) and the manual idempotency key; the SDK sends one key per call and reuses it across retries.
  • One small #call wrapper keeps per-operation logs, maps SDK errors to ZepRequestError (operation + status), and treats a 404 as "not found" where that's expected.
  • Kept as before: IDs-only users and speaker names, user metadata mapping back to TrueForge, the user uuid cache, the lookup-then-create race handling, and the duplicate check before resending an exchange.
  • Retries: adding messages and the session-start summary still make a single attempt; other calls use the SDK's retries (408/429/5xx, up to 3 retries).
  • Tests reworked; tests that only exercised the old retry code or SDK internals were removed.

Behaviour differences: network errors are no longer retried within a call (the SDK retries only on status codes; ingestion retries next run), the SDK may wait up to 60s on Retry-After (was 30s), and failures are logged once per operation instead of once per attempt.

How was this tested?

  • Server unit suite (912 passing) and the provider tests (19)
  • Requests captured against a stub fetch: same paths, snake_case bodies and Api-Key header as before
  • Live round trip against the Zep test project: user/thread creation and message ingestion, duplicate detection, memory_add, summary and search, and unknown users returning nothing instead of failing
  • ESLint, Prettier, and tsc for the server and unit tests (the tests/db typecheck has 4 pre-existing errors on main)

Checklist

  • I have read the contributing guidelines
  • Tests added/updated where it makes sense
  • No hand-edits to generated code
  • Docs / .env.example updated if configuration or behavior changed (no configuration change)

Note

Medium Risk
Memory ingestion and retrieval now depend on the Zep SDK’s retry and error behaviour; idempotency for saved notes no longer uses our UUID header, and non-idempotent paths may fail faster without in-call network retries.

Overview
Replaces the hand-rolled Zep HTTP layer with @getzep/zep-cloud, wiring ZepMemoryProvider through ZepClient for users, threads, messages, graph search and episodes.

Removes custom fetch wrappers, Zod response schemas, manual backoff/Retry-After handling and the explicit idempotency header on saved notes; adds a thin #call helper for logging and mapping SDK/ZepError into ZepRequestError, with 404 treated as “missing” where appropriate.

Behaviour shifts: message ingestion still uses a single SDK attempt (maxRetries: 0) so duplicates aren’t risked; other calls rely on the SDK’s retries (408/429/5xx, up to three). Session-start summary and similar paths pin one attempt via options. Tests are reworked (fake timers for SDK backoff, stricter “no retry” expectations for add_messages, dropped cases that only covered the old HTTP retry stack).

Adds a changeset (patch) and lockfile entry for the new dependency.

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

Co-authored-by: Cursor <cursoragent@cursor.com>
@changeset-bot

changeset-bot Bot commented Nov 6, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 748deb2

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@truefoundry/trueforge Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@qodex-ai

qodex-ai Bot commented Nov 6, 2026 •

Copy link
Copy Markdown

Qodex review

(no summary)

Effort: ●●●○○ (3/5) · No findings worth raising. The diff reads clean.

Since last review: 0 addressed, 0 new.

Scope: the changes since the last review (delta: only what changed since the previously reviewed commit 25c2026 is reviewed; findings are anchored on the whole change).

Walkthrough
What Qodex checked

Lenses (openqodex review with checked answers, all dimensions)

  • Bugs and correctness
  • Security (auth, injection, SSRF, secrets, headers)
  • Performance regressions
  • Maintainability
  • Style and consistency

Scanners

  • Scanners (none fit the changed files)
  • 0 scanner candidates raised or dropped by the reviewer

Quality filters

  • PR description: adequate (present: length, checklist; missing: issue link)
  • Repo card last refreshed 8 days ago — may not reflect very recent code structure changes
  • Per-category confidence floor (bug/security/performance 0.7, maintainability 0.71, style 0.75)
  • Severity threshold from .qodex.yaml: minor
  • Path excludes (none configured in .qodex.yaml)
  • Disabled rules (none configured in .qodex.yaml)

Verification (M1b probes against PR preview)

  • Preview deployment discovered (no successful deploy for this commit)
  • Probes (skipped, no preview to probe)

Cross-review dedup

  • Delta review: delta: only what changed since the previously reviewed commit 25c2026 is reviewed; findings are anchored on the whole change
  • Carry-overs (no findings from earlier reviews still present)

Output

  • Walkthrough comment posted
  • Inline comments (no in-diff findings to attach)

Reviewer: 0 tool calls served, 0 model calls, 0 correction rounds, 0.0s. The library does not report tool calls asked apart from those it served, or a step cap.
Reviewed by Qodex · 13.3s

Every dimension is reviewed. Bugs, security, and performance post inline; low-severity style and convention notes are collected in the group above rather than dropped. Mark a finding resolved or flag a false positive in the Qodex Pull Requests view.

this.#client = new ZepClient({
apiKey: options.apiKey,
baseUrl: options.baseUrl.replace(/\/+$/, ''),
timeoutInSeconds: DEFAULT_TIMEOUT_SECONDS,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Medium: Preserve the response-body deadline

In SDK 4.1.0, makeRequest() clears its timeout after headers arrive, before getResponseBody() reads the body, so timeoutInSeconds does not preserve the removed AbortSignal.timeout protection against trickling responses. (raw.githubusercontent.com) Pass a separate deadline through the SDK's abortSignal option that remains active until body consumption completes, combined with caller cancellation where supplied; otherwise one unfinished ingestion request blocks the sequential ingestion pass for subsequent tenants.

@veria-ai

veria-ai Bot commented Nov 6, 2026

Copy link
Copy Markdown

PR overview

The PR switches the Zep memory provider to use Zep’s official SDK for API calls, including ingestion requests.

One issue remains open: the SDK timeout ends when response headers arrive, leaving response-body consumption without the previous deadline protection. A slow or trickling response could therefore keep an ingestion request pending indefinitely; a separate deadline covering body consumption is still needed. No issues have been addressed yet.

Open issues (1)

Fixed/addressed: 0 · PR risk: 4/10

@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 using default effort 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 99f38f9. Configure here.

if (listed.status === 404) {
return false;
}
return ZepMessagesResponseSchema.parse(listed.body).items.some(

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Search crashes on null facts

Low Severity

Edge search no longer treats a null fact as empty. The old response schema allowed nullish facts and skipped them; calling trim() on null now throws and fails the whole search instead of returning the remaining facts.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 99f38f9. Configure here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The SDK deserializes a null fact to undefined (checked: {"fact": null} parses to {}), which the edge.fact === undefined guard already skips.

This branch has not been deployed

No deployments
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