2026-05-10 ¡ updated 2026-09-04
Small budget, serious build: how this site and its Agent came together
A small Cloudflare and DeepSeek stack, with deterministic context, editable behaviour, live evaluations, and an in-chat human handoff.

| Responsibility | Choice | Why this one |
|---|---|---|
| Website pages | Astro 7 | A framework for writing more content and less JavaScript, particularly well suited to articles and personal sites. |
| Backend APIs | Cloudflare Workers | Cloudflareâs nearly free serverless hosting, comparable to AWS Lambda running across a global edge network. |
| Agent model | deepseek-v4-flash |
The Agentâs brain. It cost about $1.50 over three months: cheap enough to feel unused, without answers that feel cheap. |
| Operational data | Cloudflare D1 | Managed SQLite from Cloudflare. No database deployment, almost free at low volume, and a good fit for chats, messages, and Agent settings. |
| Browser continuity | localStorage |
A small drawer built into the browser. It keeps the current conversation on the visitorâs device so a refresh does not cause amnesia. |
| Abuse control | Turnstile + D1 rate limits | One checks whether a visitor looks like a bot; the other stops someone from questioning the Agent into bankruptcy. |
| Message notification | Resend | An email service that works through an API, without configuring SMTP. |
| Release path | GitHub â Cloudflare Worker | Nothing exciting here; this is the default path now. |
The âRAGâ is intentionally boring
Today I do not use Vectorize or a vector database. Stable knowledge is assembled into the system prompt on every request: published profile facts, selected case summaries, each articleâs date, tags, title and description, canonical offers, live settings, and a small owner-maintained FAQ. Article bodies are not injected.
At the time of measurement, the static prompt was about 27,000 characters, 4,068 words, or roughly 6,000â8,000 tokens. The endpoint retains at most 20 messages and caps each at 4,000 characters. Even a deliberately extreme conversation remains around 25,000â30,000 input tokens. DeepSeek publishes a 1M-token context window. This workload is comfortably small.
Deterministic context assembly is a trade-off, not unfinished architecture. Critical facts such as prices and employment constraints are always present. There is no retrieval miss, embedding or index-synchronisation lifecycle, chunking, or reranking. Evaluations are also easier to reproduce.
I would reconsider vector retrieval when static knowledge exceeds roughly 50,000 tokens, total input regularly exceeds 100,000 tokens, latency or cost becomes material, or evaluations show relevance loss. The likely next design is hybrid: identity, safety, offers, and current settings stay injected; long-form writing and case material become retrieved.
Prompt length is not the only signal. I built a prompt-quality evaluation system to keep answering two questions: how the Agent performs now, and whether a failure comes from behaviour rules, missing knowledge, or context that has grown large enough to justify retrieval.
The first layer runs after every real answer. The visitor receives the reply normally; once it is stored, the Worker creates a shadow evaluation in the background. A separate evaluator sees the last eight conversation messages, the current conversation state, the expected language, and the answer. It scores 0â100 for need understanding, grounded facts, natural next action, language, trust and patience, avoidance of premature or form-like intake, and an editable in-chat handoff when useful. Passing means at least 80 with no material routing, fabrication, language, or pressure failure. The score, verdict, and reasons are stored in D1 against the exact assistant turn.
real answer â background shadow evaluation â score + pass/fail + reasons â D1
The second layer is for prompt changes. Codex simulates consulting prospects, project clients, recruiters, and information-only visitors while maintaining hidden trust and patience values. DeepSeek answers; deterministic checks catch wrong language, bad routing, fabrication, prompt leakage, and premature contact pressure; an independent AI judge scores routing, need discovery, trust, and efficiency. A candidate prompt then faces fixed two-turn conversations against the real website. Only a complete passing suite can activate it, and a poor version can be rolled back.
The system does not turn one low score into an automatic âadd RAGâ decision. If the facts are already in the full prompt and failures concern tone, routing, or questioning, I fix behaviour. Retrieval becomes justified when growing context repeatedly causes relevance or grounding failures and token use, latency, or cost also crosses the thresholds. RAG is therefore an evaluation-driven architecture change, not a component installed in advance to make the system look more sophisticated.
Not every knowledge change needs a website release
Putting all the material into the prompt raises a practical question. If my employment preferences, service scope, or the Agentâs conversational style changes, must I edit code and redeploy the site every time?
No.
Facts that change relatively oftenâwhether I consider permanent employment, for exampleâlive in an FAQ in the admin area. Once I edit an answer, the Agent uses it in the next conversation.
I can adjust conversational behaviour separately too. In one real test, the Agent asked a recruiter for seven pieces of information at once. It felt like a form. I changed the rule to âbegin with one open question and actively follow up at most once in the entire conversation,â then tested it against the real website. A passing version can be activated; a bad one can be rolled back.
Deleting chats, saving messages, and checking permissions still belong in code. A prompt is good at influencing what the Agent says. It should not decide whether data was actually deleted.
How the Agent was tuned, one conversation at a time
Before launch, I gave the Agent one goal: help visitors understand Deweiâs experience, strengths, and ways of working. I did not write the first knowledge base as a complete manual. I asked an AI to interview meâwhat I had built, what I was good at, where I was a poor fit, and which engagements I would acceptâand distil the answers into a profile, cases, and rules. I added the dates, tags, titles and descriptions of my existing writing to the prompt, and launched.
It worked, but it was not very good at conversation.
Sometimes it ignored the visitorâs language. It did not know whether I would consider permanent employment. A recruiter asking a simple question received a seven-item checklist. A promising role became an instant âMATCHâ. The Agent also resurrected a retired free call or declared a ten-week project feasible without enough detail.
The problem was not a shortage of articles. It did not know how to use the information it already had.
After the site had run for a while, I analysed real conversations and grouped visitors into consultation buyers, project buyers, recruiters, and people who simply wanted an answer. Their goals differed, and so did their patience.
I gave each simulated visitor two invisible numbers: trust and patience. Direct answers raise trust; evasion, invention, and premature contact pressure lower it. Every extra turn and unnecessary paragraph consumes patience. The test also checks whether the visitor got an answer or reached the right next step.
The loop is simple:
Codex simulates the visitor â DeepSeek answers â AI scores it â I change one or two things â test again.
That led to small but general changes: replace seven recruiter fields with one open question; replace an automatic âMATCHâ with âworth serious considerationâ; keep delivery projects away from consultation products; and never claim that a client case was âsimilarâ just to sound persuasive.
An independent AI then reviews the complete rules. Local success is not enough: I run three representative two-turn conversations against the real websiteâa consultation, project delivery, and permanent recruitment. Finally, I read the transcripts myself and ask a much simpler question:
Am I willing to let this Agent represent me this way?
Confirmed facts and boundaries move into the FAQ, prompt, or code. The way the Agent speaks keeps evolving through the same loop. It was not designed once; it was tuned from real conversations.
In the end, AI only makes the conversation clear
The Agent can answer questions and make an initial fit assessment, but it cannot accept work or make commitments for me. When a decision needs me, it creates an editable message summary inside the chat. Only after the visitor confirms it does the message enter my inboxâwithout sending them away to fill in another form.
Chat records are kept for at most 90 days and visitors can delete them sooner. A message that was separately reviewed and confirmed remains. That boundary is enforced by code, not improvised by the prompt.
Got thoughts on this? Talk it through with my agent, or send me a note.
