Klippy answers from what you saved now: links and files ingested in a Workflow, chunks with context, hybrid search and a reranker, cited answers, and a lock on writing once saved content is read. One fix first, the eval from lesson 8. Then the tour, the deploy, and bits' check.
Verified agents 0.33.0@cloudflare/ai-chat 0.12.2ai 7.0.162wrangler 4.157.0
Start from e-08 on GitHub. Starting here, or behind? Get the code at that tag:
git clone https://github.com/ryanyogan/klippy cd klippy git checkout e-08
1. Give the eval its own index
Create a second index, only for measuring, with its owner metadata index:
pnpm exec wrangler vectorize create klippy-notes-eval --dimensions=768 --metric=cosine pnpm exec wrangler vectorize create-metadata-index klippy-notes-eval --propertyName=owner --type=string
Bind it next to the real one. No app code reads it:
Run pnpm run cf-typegen. vitest.eval.config.mts now refuses to start unless that binding's index name ends in -eval:
2. Ids of its own, and a full wait
upsertChunks takes an id prefix (default chunk-), and vectorSearch reads the chunk id from the end of the vector id:
Then the eval runs everything on a copy of env whose VECTORIZE is the eval index, and deletes only its own prefixed ids, only from there:
Three guards, so one mistake can't reach your real vectors: the config check, the check in the file, and the prefix check before deleting. And one more fix: the eval used to wait for the first vector to be searchable, and once measured "vectors only 0.17" on a half-built index. Now it waits for all of them.
Copy vectors.ts, the eval files (test/eval/ and vitest.eval.config.mts), test/vectors.spec.ts and test/env.d.ts. Lesson 8 never had you add the script, so add it to the scripts in apps/agent/package.json:
"eval:retrieval": "vitest run --config vitest.eval.config.mts"Now it's safe to measure:
The same numbers as lesson 8, now from klippy-notes-eval only. Then the real work starts: replace the corpus with your own.
3. Name the tag
In apps/agent/src/check.ts (and test/check.spec.ts):
Run pnpm test: ours was 21 agent test files, 96 tests passed.
4. The tour
Locally, with a Klippy that has pip.md, the UI brief and trip.md saved (the Workers AI fallback answered, not Claude):
A fresh name, with nothing saved, gets "That's not in your notes." for both: every search comes back empty. That's the owner wall, not a bug.
5. Ship it
Course E added four D1 migrations (0002 to 0005), and the live database doesn't have them yet. Apply them before the deploy, or the new code meets old tables:
pnpm exec wrangler d1 migrations apply klippy-db --remote pnpm exec wrangler deploy
The klippy-notes index has been remote all along, and the IngestWorkflow is created by the deploy. If you use the web app from course D, deploy it too (pnpm deploy:web from the repo root): it shows the [n] title sources.
What we recorded, and what we didn't. We haven't applied the remote migrations or deployed the reference Klippy, so there's no recorded live run. Our dry run (pnpm exec wrangler deploy --dry-run) printed a total upload of 4076.39 KiB (781.91 KiB gzipped), with the two new bindings among the rest: env.INGEST (IngestWorkflow), a Workflow, and env.VECTORIZE (klippy-notes), a Vectorize index. And the check, locally:
6. Let bits check it
Paste your agent Worker's address. bits calls /klippy/check on it and looks for this checkpoint's tag.
A pass proves a Worker at that address answers the way this lesson asks. It doesn't prove who wrote it.
That's Klippy answering from your notes. Your code matches tag e-09 (changes from e-08).