Skip to content

Add @getzep/zep-vercel-ai integration (Vercel AI SDK)#529

Merged
danielchalef merged 2 commits into
mainfrom
feat/zep-vercel-ai
Jun 18, 2026
Merged

Add @getzep/zep-vercel-ai integration (Vercel AI SDK)#529
danielchalef merged 2 commits into
mainfrom
feat/zep-vercel-ai

Conversation

@danielchalef

Copy link
Copy Markdown
Member

Adds the @getzep/zep-vercel-ai package (integrations/vercel-ai/typescript) — Zep memory for the Vercel AI SDK.

Hooks (verified against installed ai@6.0.207)

Three composable layers (the SDK is stateless, so it offers several injection points):

  • createZepMiddleware({ client, threadId }) — a wrapLanguageModel middleware (specificationVersion: 'v3'). transformParams prepends Zep's Context Block as a system message (works for generate and stream); wrapGenerate optionally persists the turn for non-streaming generateText.
  • getZepContext / persistZepTurn helpers — for streamText/manual use (system: + persist in onFinish, which fires for both paths — the documented path since wrapGenerate doesn't run under streaming).
  • createZepTools(client, { userId | graphId })zepSearch / zepRemember / zepContext via the AI SDK tool() (Zod inputSchema) for in-loop retrieval.

All persist paths truncate to Zep's 4096-char limit and log lengths only (no PII); Zep failures degrade gracefully (never crash the call).

Deps

ai@^6 + zod as peer dependencies (the AI SDK requires a single shared instance), @getzep/zep-cloud@^3.23.0. ESM+CJS, NodeNext + strict.

Ships

README, SETUP.md (Zep signup at getzep.com), generate-text (middleware + tool, 3-turn recall) and stream-text (onFinish persistence) examples, 49 mock tests + a live test, eslint, tsup build.

Validation

tsc --noEmit + eslint + vitest (49 passed, 1 skipped) + tsup build, independently re-verified; live end-to-end smoke test against Zep + OpenAI passed (cross-turn recall confirmed). CI paths-filter entry added under the TypeScript lane.

🤖 Generated with Claude Code

danielchalef added a commit that referenced this pull request Jun 18, 2026
The Claude Code Review workflow (added in #530) granted only
`pull-requests: read` / `issues: read`. The anthropics/claude-code-action
needs Pull requests + Issues write access to post its findings as inline PR
comments — with read-only, the run succeeds but posts nothing (observed:
`permission_denials_count: 20`, `No buffered inline comments`, zero comments
on PRs #522#527/#529). Per the official docs, the action's GitHub App requires
Contents/Issues/Pull requests Read & write, and every posting example uses
`pull-requests: write` + `issues: write`.

Bump pull-requests and issues to write (contents stays read — review-only, no
commits/PRs created).

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
danielchalef added a commit that referenced this pull request Jun 18, 2026
The code-review plugin only posts findings when invoked with `--comment`;
without it the action reviews the PR (spending tokens) but prints to the
hidden terminal and posts nothing. Confirmed across PRs #522#527/#529:
runs complete `success` with write perms (post-#531) but log "No buffered
inline comments" and leave zero comments. Per the plugin spec ("If --comment
was NOT provided, stop here. Do not post any GitHub comments.").

Append --comment to the prompt; #531's pull-requests/issues write perms are
required for it to post and stay in place.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@claude

claude Bot commented Jun 18, 2026

Copy link
Copy Markdown

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

danielchalef and others added 2 commits June 18, 2026 11:00
New package integrations/vercel-ai/typescript (@getzep/zep-vercel-ai),
targeting AI SDK v6. Ships three layers over Zep's temporal Context Graph:

- createZepMiddleware: a LanguageModelMiddleware (specificationVersion v3)
  that injects the user's Context Block as a system message in
  transformParams, and (with persist: true) records the turn via
  thread.addMessages in wrapGenerate for non-streaming generateText.
- getZepContext / persistZepTurn: plain helpers for the system: + onFinish
  pattern required by streamText (where wrapGenerate does not fire), plus
  ensureZepUserAndThread for provisioning.
- createZepTools: model-callable zepSearch / zepRemember / zepContext tools
  built with the AI SDK tool() + Zod inputSchema.

Errors never crash the host call (caught, logged, degrade gracefully).
Truncation warnings log lengths only — never message content or PII.

Includes mock-based vitest tests (49 passing) plus a ZEP_API_KEY-gated live
test, runnable generateText and streamText examples, README, SETUP, and
CHANGELOG. Adds the vercel-ai TypeScript paths-filter entry to
test-integrations.yml.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Apply confirmed code-review fixes to integrations/vercel-ai/typescript:

- Make createZepMiddleware context-injection only. Inject the Context Block
  as a system message ONLY on a genuine new user turn (last prompt message
  role is 'user'), skipping tool-loop continuation steps. This stops the
  per-step wrapGenerate persistence that fragmented a turn across multiple
  thread.addMessages calls (writing intermediate tool-call preamble as a real
  assistant message) and re-fetched the Context Block once per step. Remove
  wrapGenerate and the `persist` option entirely.
- Add createZepOnFinish({ client, threadId, userId?, user?, ... }): an AI SDK
  onFinish callback that persists the whole turn exactly once (user input +
  final assistant text from the event) via persistZepTurn. Fires once per turn
  for both generateText and streamText.
- zepRemember graph.add path: add GRAPH_MAX_CHARS (10,000-char Zep limit) and
  truncate-with-warning, mirroring the 4,096-char thread path. Never silently
  drops; logs lengths only.
- ensureZepUserAndThread: gate "already exists" tolerance on the typed SDK
  signal (Zep.ConflictError / statusCode === 409) instead of a loose message
  regex; surface other errors (401/network/5xx) as real warnings.
- toRoleType: optional debug log (role NAME only, no content) when coercing an
  unknown role to 'norole'.
- Update both examples (generate-text, stream-text) to inject-via-middleware +
  persist-via-onFinish. Update README/SETUP/CHANGELOG and index.ts JSDoc to
  describe the new pattern, fix the createZepTools `binding` wrapper in JSDoc,
  remove the false "persisted automatically once per turn" claims, and align
  the zod requirement to 3 or 4.
- Tests: add a multi-step tool-loop middleware test (context injected only on
  the new-user-turn step, fetched exactly once per turn) and createZepOnFinish
  tests (turn persisted once with the final text, no preamble); add graph.add
  truncation and toRoleType debug-log tests; convert ensureZepUserAndThread
  tests to the typed ConflictError signal.

Validation: tsc --noEmit clean, eslint clean, 59 tests pass (1 live skipped),
tsup build succeeds.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@danielchalef danielchalef merged commit dca59ae into main Jun 18, 2026
10 checks passed
@danielchalef danielchalef deleted the feat/zep-vercel-ai branch June 18, 2026 19:23
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