What You'll Build
A semantic workflow engine — a single-page tool that takes a plain-English query, uses cosine similarity scoring to semantically match it against a set of knowledge chunks, and then routes that matched context through the correct reusable prompt template (MCP-style workflow). Think of it as a miniature version of how production AI systems decide what to retrieve and which workflow to run.
- A knowledge base panel where you paste in text chunks that represent your "documents"
- A lightweight embedding simulator using keyword-overlap cosine similarity scoring to rank chunks
- A prompt template library with 3 reusable MCP-style workflow prompts (summarise, explain, compare)
- An automatic workflow router that picks the right template based on query intent keywords
- A results panel that shows the top matched chunk, the selected workflow, and the fully assembled prompt ready to copy
What You'll Need
AI Tool
Claude (claude.ai) or ChatGPT (chat.openai.com) — either works great for this project. Claude tends to produce especially clean structured HTML and JavaScript.
Text Editor
Any text editor works — VS Code is ideal. You'll save one HTML file and open it directly in your browser. No server or install required.
Step 1: Build the Knowledge Base Panel
Every RAG system starts with a knowledge base — a set of text chunks the system can search through. In this step you'll prompt your AI to build the UI panel where you'll paste those chunks in. This is the "retrieval corpus" part of the RAG pipeline, and understanding how it's structured is the foundation of everything else.
Build the first section of a single HTML file called semantic-workflow-engine.html. Use a dark theme with a charcoal/slate background. Add a panel at the top called "Knowledge Base". Inside it, place 3 textarea fields side by side (or stacked on mobile), each labelled "Chunk 1", "Chunk 2", "Chunk 3". Pre-fill each textarea with a short 2-3 sentence paragraph about a different topic — for example: embeddings, fine-tuning, and RAG. Each textarea should have a monospace font, a dark input background, and a subtle border. Add a section heading that says "Semantic Workflow Engine" in large bold text at the very top of the page. Do not add any JavaScript yet — just the HTML and CSS for this panel.
What to look for: You should get a clean dark-themed HTML page with three text areas pre-filled with different topic content. Check that the layout looks tidy on a wide screen and that the font in the textareas is monospace. If the AI uses inline styles instead of a style block, that's fine — just make sure the page renders without errors in your browser.
Step 2: Add the Embedding Similarity Scorer
Real embedding models turn text into high-dimensional vectors, then use cosine similarity to find the closest match. We'll approximate that concept using word-overlap scoring — the same underlying idea, just without calling an API. This step teaches you what embeddings actually do in a RAG pipeline, even if we're simulating the maths in plain JavaScript.
Add a JavaScript section to semantic-workflow-engine.html that implements a simple text similarity scorer. The function should: (1) tokenise a string into lowercase words, filtering out common stop words like "the", "a", "is", "of", "and", "to", "in", "it"; (2) build a word-frequency vector from each chunk; (3) compute cosine similarity between the query vector and each chunk vector using the dot product divided by the product of their magnitudes. Add a search input field below the Knowledge Base panel, labelled "Your Query", with placeholder text "e.g. How does semantic search work?". Add a button labelled "Find Best Match" that runs the similarity scorer against all 3 chunks when clicked. Display the result below the button showing which chunk won, its similarity score as a percentage, and the full text of that chunk highlighted in a green-bordered card. Label this result section "Top Retrieved Chunk". Comment the JavaScript clearly so I can learn from it.
What to look for: Type a query like "how do vector embeddings work" and click Find Best Match. You should see Chunk 1 (embeddings) score highest. The similarity score will be a percentage — even 15–30% is realistic for this kind of overlap scoring. If all chunks score 0%, the stop-word filter is probably too aggressive — ask the AI to loosen it.
Step 3: Build the Reusable Prompt Template Library
MCP Prompts are reusable workflow templates that accept arguments and produce consistent, structured outputs every time. In this step you'll define three prompt templates — Summarise, Explain, and Compare — each with a slot for the retrieved chunk to be injected into. This is the "reusable workflow" layer that sits on top of the retrieval system.
Add a "Prompt Template Library" section to semantic-workflow-engine.html below the query input. Define 3 reusable prompt templates as JavaScript objects stored in a const array called WORKFLOW_TEMPLATES. Each object should have: a "name" field ("Summarise", "Explain", "Compare"), a "description" field (one sentence about what this workflow does), a "triggerKeywords" array (3-5 words that suggest this workflow, e.g. ["summarise", "overview", "summary", "brief", "tldr"] for Summarise), and a "template" field — a multi-line string prompt that includes the placeholder {{RETRIEVED_CHUNK}} and {{USER_QUERY}} where the content will be injected. The Summarise template should ask for a bullet-point summary. The Explain template should ask for a beginner-friendly explanation with an analogy. The Compare template should ask the AI to compare the concept in the chunk to a related concept the user mentions. Render all 3 templates visually as cards in the UI, showing the name, description, and trigger keywords as small badges. Use a violet accent for these cards.What to look for: You should see three violet-accented cards below the query box, each showing a workflow name, its description, and small keyword badges. Check that the WORKFLOW_TEMPLATES array is in the JavaScript and that each template string really contains {{RETRIEVED_CHUNK}} and {{USER_QUERY}} as placeholders. These are the slots the router will fill in the next step.
Step 4: Wire Up the Automatic Workflow Router
This is where the three tutorials collide. The router scans the user's query for intent signals (the trigger keywords), picks the matching MCP-style workflow template, and then injects the RAG-retrieved chunk into it — producing a fully assembled, ready-to-paste prompt. This is exactly how production RAG systems decide which downstream workflow to activate based on what the user wants.
Update the "Find Best Match" button logic in semantic-workflow-engine.html so that after finding the top retrieved chunk, it also automatically selects the best workflow template. Add a routeWorkflow(query) function that: (1) lowercases the query and checks it for trigger keywords from each workflow template; (2) scores each template by how many of its trigger keywords appear in the query; (3) returns the template with the highest keyword match score, defaulting to "Explain" if there is a tie or no match. After routing, inject the retrieved chunk text and the original query into the chosen template's {{RETRIEVED_CHUNK}} and {{USER_QUERY}} placeholders. Display the result in a new panel below called "Assembled Workflow Prompt" — show which workflow was selected in a cyan badge, then display the full assembled prompt in a styled code block with a monospace font and a "Copy Assembled Prompt" button. Also show a small explanation line: "This prompt is ready to paste into Claude or ChatGPT."What to look for: Try a query like "can you summarise what RAG is" — you should see the Summarise workflow selected (cyan badge), and the assembled prompt should contain your actual chunk text where {{RETRIEVED_CHUNK}} was. Then try "explain embeddings to me like I'm new" and watch the router switch to the Explain template. If routing doesn't switch, ask the AI to debug the keyword scoring logic.
Step 5: Add a Debug Trace Panel and Polish the UI
The best way to learn how a system like this works is to see its reasoning. In this final step, you'll add a debug trace that shows every decision the engine made — which chunks scored what, why the router picked a particular workflow, and what keywords triggered it. You'll also give the whole page a final visual polish so it looks like a real tool.
Add a collapsible "Engine Trace" section to semantic-workflow-engine.html that appears after each query run. It should be collapsed by default with a toggle button labelled "Show Engine Trace ▼". When expanded, it displays: (1) a table showing all 3 chunks with their cosine similarity scores for this query, highlighting the winner in green; (2) a workflow routing breakdown showing each template's keyword match score and which keywords from the query matched; (3) a line showing the final decision: "Retrieved: Chunk X | Workflow: [Name] | Trigger match: [keywords]". Style this panel with an amber accent and monospace text to give it a terminal/debug feel. Then do a final UI polish pass: add a subtle gradient header bar at the top with the tool name and a one-line description ("Semantic retrieval + reusable workflows, visualised"), ensure consistent spacing between all panels, and add a thin brand-green left border to the "Assembled Workflow Prompt" panel to make it stand out as the key output. Make sure the Copy Assembled Prompt button works correctly.What to look for: After running a query, click "Show Engine Trace" and verify you can see all three similarity scores in a table and the keyword match breakdown per workflow. The winner row should be highlighted in green. The assembled prompt panel should have a green left border making it visually the most prominent output. This trace is your proof that you understand the internals — it's what separates someone who uses RAG from someone who understands RAG.
Common Issues
All similarity scores come back as 0%
Your stop-word filter is probably stripping too many words. Ask your AI: "The similarity scorer returns 0 for everything. Can you print the tokenised word arrays for both the query and each chunk to the console so I can debug what words remain after filtering?" Then open browser DevTools (F12) to read the output.
The workflow router always picks the same template
This usually means the trigger keywords aren't matching the query text. Ask your AI to add a console.log inside routeWorkflow() that prints each template's score. Try using queries that explicitly contain a trigger keyword, like "summarise this for me" or "explain this concept".
The {{RETRIEVED_CHUNK}} placeholder isn't being replaced
JavaScript's string .replace() only replaces the first occurrence by default. Make sure the AI used a global regex replace: template.replaceAll('{{RETRIEVED_CHUNK}}', chunkText) or a /{{RETRIEVED_CHUNK}}/g regex. Ask your AI to check this specifically.
The assembled prompt looks garbled or truncated
This happens when the chunk textarea text contains special characters that break string interpolation. Ask your AI to wrap the chunk text extraction in a .trim() call and escape backticks if template literals are being used. Alternatively, switch to regular string concatenation instead of template literals.
What You Learned
How Embeddings Actually Work
You built a working similarity scorer that mimics the core job of an embedding model — turning text into a comparable representation and ranking chunks by relevance. Real embedding models do this in 1,536 dimensions instead of word counts, but the cosine similarity maths is identical.
What RAG Actually Does Step by Step
You built each stage of a RAG pipeline manually — chunked knowledge base, retrieval scoring, context injection — so you can now visualise what happens inside every RAG product you use. You also understand why retrieval quality matters so much: garbage in, garbage out.
Reusable MCP-Style Prompt Workflows
You designed structured prompt templates with named placeholders — exactly the pattern MCP Prompts use. Instead of writing a new prompt every time, you built a library of workflows that slot in context automatically. That's a production-grade prompting pattern.
Intent Routing and System Architecture
You built a router that reads user intent and picks the right downstream workflow — a pattern used in every serious AI agent and RAG system. Understanding this layer is what separates prompt engineers from AI systems thinkers.
Tips for Going Further
- →Connect to a real embedding API. Ask your AI to swap the word-overlap scorer for a call to OpenAI's text-embedding-3-small API. You'll immediately see how much better semantic matching becomes — queries like "how do neural nets encode meaning" will find the embeddings chunk even without the word "embeddings" present.
- →→Add more workflow templates. Build a "Draft" template that turns retrieved context into a first draft, or a "Q&A" template that extracts likely questions from the chunk. The router logic already supports unlimited templates.
- →Let the user add their own chunks. Add an "Add Chunk" button that appends new textareas dynamically, letting users paste in their own documents. This turns the tool into a personal RAG sandbox.
- →Export and import your template library. Ask your AI to add a JSON export/import feature for WORKFLOW_TEMPLATES so you can save your best prompt workflows and reload them later — a real MCP Prompts workflow library.
- →Add a fine-tuning vs RAG decision helper. Build a fourth template that — given a use case description in the query — outputs a recommendation for whether to use RAG or fine-tuning, with reasons. This ties back directly to the first tutorial in this week's set.