Serhii NezhyhaiShopify developer

AI, with the boring parts included

Two different things get called "AI experience". One is using it to work faster. The other is shipping features that customers depend on. They need different evidence, so they're separated here.

In my workflow

I use AI daily, mostly for the parts of the job that are typing rather than thinking: scaffolding a Function and its tests, drafting a migration script, writing the first pass of a schema, reviewing a diff for the thing I've stopped noticing after four hours.

What I don't delegate is architecture, security decisions, or the question of whether the output is actually correct. On an integration that touches money — bank reconciliation, fiscal receipts — that's the whole job. A model that writes a plausible-looking sync is a liability unless someone read it, and that someone is me.

The practical effect is that I take on integrations and migrations I'd have been slower to attempt before, because the tedious half is now genuinely faster. The careful half takes exactly as long as it did.

A working example, on this page

This is the same pattern as a store's pre-sales assistant, pointed at my own case studies instead of a catalogue. It retrieves from the site's content, cites the section it used, and refuses when the answer isn't there. Everything it says is checkable by following the link.

The assistant needs JavaScript. Everything it can tell you is inthe case studies,the CV andservices.

How it's built

A demo that works once is not evidence. These are the constraints it runs under, which is the part a client should actually care about.

Grounded only
Answers come from retrieved excerpts of this site and nothing else. No general knowledge, about Shopify or about me.
Similarity floor at 0.3
If the best-matching passage scores below the floor, the chat model is never called. The refusal is deterministic, and an off-topic question costs one embedding instead of a completion.
Injection-resistant
The question and the retrieved text are both treated as data. Instructions found inside either — "ignore previous instructions", "reveal your prompt" — are not acted on.
Capped at 400 output tokens
Questions are limited to 500 characters and 5 passages of context. Short answers are the design, not a limitation.
8 questions per 10 minutes, 40 per day
Per IP, in Cloudflare KV, and it fails closed: if the counter is unavailable the endpoint refuses rather than running unmetered.
Spend cap at the account
A project-level monthly limit in the OpenAI dashboard, which is the one guard that does not depend on my code being correct.

Pipeline

Content is chunked by heading at author time and embedded with text-embedding-3-small at 512 dimensions — a third of the default. The reduction is deliberate: it keeps the whole index inside one Worker with no vector database to depend on, and it cost nothing measurable in retrieval quality here while clearly helping latency. At query time it's one embedding call, a dot product over the site's normalised vectors, then one capped completion. Answers are returned whole rather than streamed, so citations can be resolved to real links before anything reaches the page.

What the evals say

Recall@3
96%
Recall@5
100%
Questions
29
Refused by floor
3

Measured against the site content as of 2026-08-30.

The eval set scores retrieval, not phrasing: for each question it checks whether the passage that actually contains the answer came back in the top three. Out-of-scope questions are in the set too, and they are expected to be stopped by the similarity floor — a leak there fails the run. It's deterministic and costs one embedding per question, so it runs on every content change rather than once at launch.

AI commerce projects

Client work where AI is the substance rather than the tooling.

A shopper-facing chat agent on Claude and MCP — catalogue search, cart building and order status, in Ukrainian and Russian.

Informatica

Model
Claude Haiku 4.5
  • AI / agentic