<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Context First AI</title>
    <description>The latest articles on DEV Community by Context First AI (@contextfirstai).</description>
    <link>https://dev.to/contextfirstai</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3711718%2F3e2bbb38-36c9-42fa-ad9f-51bc48336998.png</url>
      <title>DEV Community: Context First AI</title>
      <link>https://dev.to/contextfirstai</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/contextfirstai"/>
    <language>en</language>
    <item>
      <title>Meaning Has a Shape: How AI Models Represent Concepts (and Why It Changes Everything About Search).</title>
      <dc:creator>Context First AI</dc:creator>
      <pubDate>Thu, 26 Mar 2026 09:47:22 +0000</pubDate>
      <link>https://dev.to/contextfirstai/meaning-has-a-shape-how-ai-models-represent-concepts-and-why-it-changes-everything-about-search-118g</link>
      <guid>https://dev.to/contextfirstai/meaning-has-a-shape-how-ai-models-represent-concepts-and-why-it-changes-everything-about-search-118g</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy36hgfajb40o6u33arne.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy36hgfajb40o6u33arne.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AI models represent meaning as location in a high-dimensional space words with similar meanings sit near each other, unrelated concepts sit far apart. This is called an embedding. Understanding embeddings explains how semantic search works, why AI sometimes confidently produces outdated answers, and what to do about it. No maths required.&lt;/p&gt;

&lt;p&gt;This is Part 3 of a five-part series from the Vectors pillar of Context First AI. Built for anyone starting their AI journey — developer or not. Parts 1 and 2 covered next-token prediction and tokenisation respectively. This part goes deeper into how meaning is represented.&lt;/p&gt;

&lt;p&gt;Full series:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Part 1 — The Autocomplete That Ate the World&lt;/li&gt;
&lt;li&gt;Part 2 — You're Not Reading Words, You're Reading Chunks&lt;/li&gt;
&lt;li&gt;Part 3 — Meaning Has a Shape&lt;/li&gt;
&lt;li&gt;Part 4 — You're Not Writing Prompts, You're Writing Instructions for a Very Particular Mind&lt;/li&gt;
&lt;li&gt;Part 5 — What to Do When the Model Doesn't Know Enough&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Search That Kept Failing&lt;/p&gt;

&lt;p&gt;It started during an internal tool evaluation — a 30-person team building an AI assistant over their HR documentation.&lt;/p&gt;

&lt;p&gt;The setup seemed sound. Documents indexed. Search connected. Interface clean. But when the team ran test queries, they kept getting empty results on things that clearly existed. &lt;em&gt;"How do I request time off?"&lt;/em&gt; — nothing. The policy was right there in the knowledge base, under the title &lt;em&gt;"Leave Application Process."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The tool wasn't broken. The issue was more fundamental: the search was matching strings, not meanings. And those two things, it turns out, are very different problems.&lt;/p&gt;

&lt;p&gt;What an Embedding Actually Is&lt;/p&gt;

&lt;p&gt;To understand why the search failed — and how to fix it — you need to understand embeddings.&lt;/p&gt;

&lt;p&gt;An embedding is a location. When a model processes a word, a sentence, or an entire document, it converts that text into a list of numbers — typically hundreds or thousands of them — that encodes its position in a high-dimensional space.&lt;/p&gt;

&lt;p&gt;The key property of this space: &lt;strong&gt;semantic similarity maps to geometric proximity.&lt;/strong&gt; Words and phrases that appear in similar contexts during training end up placed near each other. Unrelated concepts end up far apart.&lt;/p&gt;

&lt;p&gt;You can see this directly using a sentence transformer model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sentence_transformers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SentenceTransformer&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;

&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SentenceTransformer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;all-MiniLM-L6-v2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;phrases&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;how do I request time off&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;employees should submit a leave application&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;quarterly budget forecast&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;invoice payment terms&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;embeddings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;phrases&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;cosine_similarity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;linalg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;norm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;np&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;linalg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;norm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;# Compare the first phrase against all others
&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;embeddings&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;phrase&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;phrases&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:],&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;similarity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;cosine_similarity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;embeddings&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Similarity to &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;phrases&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;similarity&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;Running&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt; &lt;span class="n"&gt;produces&lt;/span&gt; &lt;span class="n"&gt;something&lt;/span&gt; &lt;span class="n"&gt;like&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

&lt;span class="n"&gt;Similarity&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;employees should submit a leave application&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.721&lt;/span&gt;
&lt;span class="n"&gt;Similarity&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;quarterly budget forecast&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.082&lt;/span&gt;
&lt;span class="n"&gt;Similarity&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;invoice payment terms&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.047&lt;/span&gt;

&lt;span class="n"&gt;The&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;HR&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt; &lt;span class="n"&gt;sentence&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;close&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;embedding&lt;/span&gt; &lt;span class="n"&gt;space&lt;/span&gt; &lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="n"&gt;high&lt;/span&gt; &lt;span class="n"&gt;cosine&lt;/span&gt; &lt;span class="n"&gt;similarity&lt;/span&gt; &lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="n"&gt;even&lt;/span&gt; &lt;span class="n"&gt;though&lt;/span&gt; &lt;span class="n"&gt;they&lt;/span&gt; &lt;span class="n"&gt;share&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt; &lt;span class="n"&gt;keywords&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;The&lt;/span&gt; &lt;span class="n"&gt;budget&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;invoice&lt;/span&gt; &lt;span class="n"&gt;phrases&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;far&lt;/span&gt; &lt;span class="n"&gt;away&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;The&lt;/span&gt; &lt;span class="n"&gt;geometry&lt;/span&gt; &lt;span class="n"&gt;reflects&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;meaning&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="n"&gt;The&lt;/span&gt; &lt;span class="n"&gt;Vector&lt;/span&gt; &lt;span class="n"&gt;Arithmetic&lt;/span&gt; &lt;span class="n"&gt;Example&lt;/span&gt;

&lt;span class="n"&gt;The&lt;/span&gt; &lt;span class="n"&gt;famous&lt;/span&gt; &lt;span class="n"&gt;demonstration&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;what&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt; &lt;span class="n"&gt;space&lt;/span&gt; &lt;span class="n"&gt;encodes&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;worth&lt;/span&gt; &lt;span class="n"&gt;working&lt;/span&gt; &lt;span class="n"&gt;through&lt;/span&gt; &lt;span class="n"&gt;directly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;br&gt;
from sentence_transformers import SentenceTransformer&lt;br&gt;
import numpy as np&lt;/p&gt;

&lt;p&gt;model = SentenceTransformer("all-MiniLM-L6-v2")&lt;/p&gt;
&lt;h1&gt;
  
  
  Encode the four concepts
&lt;/h1&gt;

&lt;p&gt;king, man, woman, queen = model.encode(["king", "man", "woman", "queen"])&lt;/p&gt;
&lt;h1&gt;
  
  
  Vector arithmetic: king - man + woman
&lt;/h1&gt;

&lt;p&gt;result = king - man + woman&lt;/p&gt;
&lt;h1&gt;
  
  
  Find similarity to queen
&lt;/h1&gt;

&lt;p&gt;def cosine_similarity(a, b):&lt;br&gt;
    return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))&lt;/p&gt;

&lt;p&gt;print(f"king - man + woman → similarity to 'queen': {cosine_similarity(result, queen):.3f}")&lt;br&gt;
print(f"king - man + woman → similarity to 'king':  {cosine_similarity(result, king):.3f}")&lt;br&gt;
print(f"king - man + woman → similarity to 'man':   {cosine_similarity(result, man):.3f}")&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
The result vector sits closer to *queen* than to any of the input words. Nobody wrote that relationship. It emerged from the geometry of how those words were used across training data — because *king* and *queen* appear in analogous contexts to *man* and *woman* respectively, and the model encoded that analogy structurally.

This is what it means for meaning to have a shape.

Building a Minimal Semantic Search

The practical application for the HR team's problem is semantic search — retrieval by meaning rather than keyword matching.

Here's a minimal working example:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;br&gt;
from sentence_transformers import SentenceTransformer&lt;br&gt;
import numpy as np&lt;/p&gt;

&lt;p&gt;model = SentenceTransformer("all-MiniLM-L6-v2")&lt;/p&gt;
&lt;h1&gt;
  
  
  Knowledge base documents (simplified)
&lt;/h1&gt;

&lt;p&gt;documents = [&lt;br&gt;
    "Leave Application Process: Employees should submit a leave application via the HR portal at least 5 working days in advance.",&lt;br&gt;
    "Expense Reimbursement Policy: All business expenses must be submitted within 30 days of incurrence with receipts attached.",&lt;br&gt;
    "Remote Work Guidelines: Employees may work remotely up to 3 days per week subject to manager approval.",&lt;br&gt;
    "Performance Review Schedule: Annual reviews are conducted in January and July each year.",&lt;br&gt;
]&lt;/p&gt;
&lt;h1&gt;
  
  
  Index: convert all documents to embeddings at setup time
&lt;/h1&gt;

&lt;p&gt;document_embeddings = model.encode(documents)&lt;/p&gt;

&lt;p&gt;def semantic_search(query: str, top_k: int = 2) -&amp;gt; list[dict]:&lt;br&gt;
    query_embedding = model.encode(query)&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;similarities = []
for i, doc_embedding in enumerate(document_embeddings):
    similarity = np.dot(query_embedding, doc_embedding) / (
        np.linalg.norm(query_embedding) * np.linalg.norm(doc_embedding)
    )
    similarities.append({"document": documents[i], "score": float(similarity)})

return sorted(similarities, key=lambda x: x["score"], reverse=True)[:top_k]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
  
  
  Test with the original failing query
&lt;/h1&gt;

&lt;p&gt;results = semantic_search("how do I request time off")&lt;br&gt;
for r in results:&lt;br&gt;
    print(f"Score: {r['score']:.3f}")&lt;br&gt;
    print(f"Document: {r['document'][:80]}...")&lt;br&gt;
    print()&lt;/p&gt;

&lt;p&gt;Output:&lt;/p&gt;

&lt;p&gt;Score: 0.698&lt;br&gt;
Document: Leave Application Process: Employees should submit a leave application via the HR...&lt;/p&gt;

&lt;p&gt;Score: 0.201&lt;br&gt;
Document: Remote Work Guidelines: Employees may work remotely up to 3 days per week subject...&lt;/p&gt;

&lt;p&gt;The correct document surfaces at the top, despite sharing no keywords with the query. The retrieval is driven entirely by the semantic proximity of the embeddings.&lt;/p&gt;

&lt;p&gt;This is the architecture underneath virtually every AI tool that finds relevant information from a document store.&lt;/p&gt;

&lt;p&gt;Two Kinds of Knowledge — and Two Different Failure Modes&lt;/p&gt;

&lt;p&gt;Understanding embeddings opens up a second important distinction: the difference between what a model &lt;em&gt;learned&lt;/em&gt; and what you &lt;em&gt;give it&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Parametric knowledge is baked into the model's weights during pre-training. It's vast — facts, concepts, patterns, cultural context — but it was fixed at a point in time. The model has a training cutoff, and it cannot update itself after that. Critically, it often doesn't know when it's uncertain about something in this category. It can sound equally confident whether it's right or drawing on outdated information.&lt;/p&gt;

&lt;p&gt;Contextual knowledge is whatever you supply in the prompt — a document, a data extract, a policy, a set of instructions. The model processes this at inference time and can reason over it carefully, because it's right there in the context window.&lt;/p&gt;

&lt;p&gt;The failure modes are different, and diagnosable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Parametric knowledge failure — asking the model to recall something
# it may not have, or that may have changed since training
&lt;/span&gt;&lt;span class="n"&gt;parametric_prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
What is the current interest rate set by the Bank of England?
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

&lt;span class="c1"&gt;# Contextual knowledge approach — supply the information, ask for reasoning
&lt;/span&gt;&lt;span class="n"&gt;contextual_prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
The Bank of England&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s Monetary Policy Committee voted on [DATE] to set the 
base rate at [CURRENT RATE]%. This decision was driven by [REASON].

Based on the above, what is the current Bank of England base rate, 
and what was the stated rationale?
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

&lt;span class="c1"&gt;# The parametric approach may return outdated or hallucinated data.
# The contextual approach constrains the model to reason from what you've supplied.
&lt;/span&gt;
&lt;span class="c1"&gt;# Practical pattern: when accuracy matters, always use the contextual approach.
# Supply the source. Ask the model to reason from it, not from training memory.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The pattern is simple: for anything time-sensitive, domain-specific, or where you need verifiable accuracy, don't ask the model to retrieve from memory. Give it the information and ask it to reason over what you've supplied.&lt;/p&gt;

&lt;p&gt;This is, in structural terms, the core idea behind RAG (retrieval-augmented generation) — which we cover properly in Part 5.&lt;/p&gt;

&lt;p&gt;Choosing an Embedding Model&lt;/p&gt;

&lt;p&gt;Not all embedding models are equal, and the choice matters for retrieval quality.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Common embedding model options and their tradeoffs
&lt;/span&gt;
&lt;span class="n"&gt;embedding_models&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;all-MiniLM-L6-v2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dimensions&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;384&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;speed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fast&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;quality&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;good for general use&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;use_case&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prototyping, general semantic search&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;all-mpnet-base-v2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dimensions&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;768&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;speed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;moderate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;quality&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;higher quality general embeddings&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;use_case&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;production general search&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text-embedding-3-small&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dimensions&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1536&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;speed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;API call latency&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;quality&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;strong across many domains&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;use_case&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OpenAI ecosystem integration&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text-embedding-3-large&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dimensions&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3072&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;speed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;API call latency&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;quality&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;highest quality in OpenAI family&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;use_case&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;high-stakes retrieval, complex domains&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Key principle: the embedding model used at index time and query time
# must be the same model. Mixing models produces meaningless similarity scores.
&lt;/span&gt;
&lt;span class="c1"&gt;# For specialist domains (legal, medical, scientific), consider domain-specific
# embedding models trained on that vocabulary — general models may underperform
# on highly specialised terminology.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The final point in the comment block is worth emphasising: a poorly trained embedding model produces a space where proximity doesn't reliably encode meaning. Retrieval becomes unreliable in ways that look like the wrong documents being returned — which is often misdiagnosed as a model quality issue rather than an embedding quality issue.&lt;/p&gt;

&lt;p&gt;What Comes Next&lt;/p&gt;

&lt;p&gt;You now have three layers of the foundation: prediction, tokenisation, and meaning representation. Part 4 puts this to work practically — how to communicate with these models in ways that consistently produce better results. Prompt engineering, done correctly, is a direct consequence of understanding the mechanics we've built up across these three parts.&lt;/p&gt;

&lt;p&gt;See you there.&lt;/p&gt;

&lt;p&gt;*Created with AI assistance. Originally published at &lt;a href="https://contextfirst.ai" rel="noopener noreferrer"&gt;[Context First AI]&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>You're Not Reading Words, You're Reading Chunks: Tokens and Context Windows Explained.</title>
      <dc:creator>Context First AI</dc:creator>
      <pubDate>Wed, 25 Mar 2026 09:44:54 +0000</pubDate>
      <link>https://dev.to/contextfirstai/youre-not-reading-words-youre-reading-chunks-tokens-and-context-windows-explained-310h</link>
      <guid>https://dev.to/contextfirstai/youre-not-reading-words-youre-reading-chunks-tokens-and-context-windows-explained-310h</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmpwcpalgy1umwa6p18v1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmpwcpalgy1umwa6p18v1.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AI models don't read words — they read subword chunks called tokens. Every model also has a context window: a hard limit on how much text it can hold in attention at once. Understanding both changes how you write prompts, how you estimate costs, and why AI occasionally behaves in ways that otherwise seem inexplicable.&lt;/p&gt;

&lt;p&gt;This is Part 2 of a five-part series from the Vectors pillar of Context First AI. Built for anyone starting their AI journey — developer or not. No prior knowledge assumed beyond Part 1.&lt;/p&gt;

&lt;p&gt;Full series:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Part 1 — The Autocomplete That Ate the World*&lt;/li&gt;
&lt;li&gt;Part 2 — You're Not Reading Words, You're Reading Chunks*&lt;/li&gt;
&lt;li&gt;Part 3 — Meaning Has a Shape*&lt;/li&gt;
&lt;li&gt;Part 4 — You're Not Writing Prompts, You're Writing Instructions for a Very Particular Mind*&lt;/li&gt;
&lt;li&gt;Part 5 — What to Do When the Model Doesn't Know Enough&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Session That Went Wrong&lt;/p&gt;

&lt;p&gt;It started during a long research session — a product team working through a complex competitive analysis with an AI assistant, building up context across dozens of exchanges.&lt;/p&gt;

&lt;p&gt;Somewhere around the fortieth message, the model stopped referencing things mentioned early on. Key constraints from the first few prompts. Background context that had shaped everything since. Gone.&lt;/p&gt;

&lt;p&gt;The thing nobody had warned them about: the model hadn't forgotten. It had run out of room.&lt;/p&gt;

&lt;p&gt;That's the context window. And it's the second of two mechanics — alongside tokenisation — that sit beneath every single AI interaction, shaping what the model can see, what it can process, and what quietly disappears.&lt;/p&gt;

&lt;p&gt;What Is a Token?&lt;/p&gt;

&lt;p&gt;Before the model reads anything, your text goes through tokenisation — the process of breaking input into the discrete units the model actually processes.&lt;/p&gt;

&lt;p&gt;Those units are tokens: subword chunks that can be full words, partial words, or individual punctuation marks. The model never sees raw text. It sees a sequence of token IDs, each corresponding to a chunk in its learned vocabulary.&lt;/p&gt;

&lt;p&gt;You can see this directly with OpenAI's tiktoken library:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;tiktoken&lt;/span&gt;

&lt;span class="n"&gt;encoder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tiktoken&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encoding_for_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4o&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;texts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cat&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tokenisation&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GDPR&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Supercalifragilisticexpialidocious&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;texts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;encoder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;decoded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;encoder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; → &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; token(s): &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;decoded&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;Running&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt; &lt;span class="n"&gt;produces&lt;/span&gt; &lt;span class="n"&gt;something&lt;/span&gt; &lt;span class="n"&gt;like&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;cat&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="nf"&gt;token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;cat&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;tokenisation&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="nf"&gt;token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;token&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;is&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ation&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;GDPR&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="nf"&gt;token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;GD&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;PR&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Supercalifragilisticexpialidocious&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt; &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="nf"&gt;token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="p"&gt;[...]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The pattern is consistent: common, short English words tend to be single tokens. Unusual words, technical acronyms, and long compound terms fragment into multiple pieces.&lt;/p&gt;

&lt;p&gt;Why Tokenisation Matters in Practice&lt;/p&gt;

&lt;p&gt;Token count ≠ word count&lt;/p&gt;

&lt;p&gt;The most immediate practical consequence is cost. AI APIs charge per token, not per word. The rough conversion for English prose is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;estimate_tokens&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word_count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;content_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prose&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Rough token estimation by content type.
    These are approximations — always measure directly for production use.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;multipliers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prose&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;       &lt;span class="mf"&gt;1.3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;# Standard English writing
&lt;/span&gt;        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;technical&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="mf"&gt;1.4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;# Dense technical content, acronyms
&lt;/span&gt;        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="mf"&gt;1.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;   &lt;span class="c1"&gt;# Code tends to tokenise less efficiently
&lt;/span&gt;        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;multilingual&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# Non-English content often fragments more
&lt;/span&gt;    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;multiplier&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;multipliers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;content_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;estimated&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;word_count&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;multiplier&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;word_count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;word_count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content_type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;content_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;estimated_tokens&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;estimated&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;note&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Measure with tiktoken for precision before scaling&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Examples
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;estimate_tokens&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prose&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;       &lt;span class="c1"&gt;# ~1,300 tokens
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;estimate_tokens&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;technical&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;   &lt;span class="c1"&gt;# ~1,400 tokens
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;estimate_tokens&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;code&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;        &lt;span class="c1"&gt;# ~1,500 tokens
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At small scale this difference is negligible. At high throughput — thousands of API calls per day — it compounds quickly.&lt;/p&gt;

&lt;p&gt;Fragmented words affect output quality&lt;/p&gt;

&lt;p&gt;When a model sees a rare technical term split into five tokens, it has less of a "whole concept" signal to work with than when it sees a familiar word as a single token. This is why models occasionally mishandle very specific regulatory language, uncommon proper nouns, or technical acronyms from specialist domains.&lt;/p&gt;

&lt;p&gt;The practical mitigation is to define unfamiliar terms explicitly before using them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Less reliable for niche terminology
&lt;/span&gt;&lt;span class="n"&gt;prompt_naive&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Does this clause comply with DPDPA obligations?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;# More reliable — define before using
&lt;/span&gt;&lt;span class="n"&gt;prompt_with_context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
Context: DPDPA refers to India&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s Digital Personal Data Protection Act 2023,
which governs the processing of digital personal data of Indian residents.

Given this definition, does the following clause comply with DPDPA obligations?

 What Is a Context Window?

Every model has a maximum number of tokens it can process in a single forward pass — input plus output combined. This is the context window.

Think of it as a desk. Everything on the desk is visible and usable. Everything not on the desk doesn&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;t exist for this conversation. When the desk fills up, something has to fall off — typically the oldest content.

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;br&gt;
import openai&lt;/p&gt;

&lt;p&gt;client = openai.OpenAI()&lt;/p&gt;

&lt;p&gt;def chat_with_context_management(&lt;br&gt;
    messages: list[dict],&lt;br&gt;
    model: str = "gpt-4o",&lt;br&gt;
    max_context_tokens: int = 100_000,&lt;br&gt;
    reserve_for_output: int = 2_000&lt;br&gt;
) -&amp;gt; str:&lt;br&gt;
    """&lt;br&gt;
    Simple context management: trim oldest messages if approaching limit.&lt;br&gt;
    Production implementations should use more sophisticated strategies.&lt;br&gt;
    """&lt;br&gt;
    encoder = tiktoken.encoding_for_model(model)&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def count_tokens(msgs):
    return sum(len(encoder.encode(m["content"])) for m in msgs)

usable_limit = max_context_tokens - reserve_for_output

# Preserve system message (index 0), trim from oldest user/assistant pairs
system = [messages[0]] if messages[0]["role"] == "system" else []
conversation = messages[len(system):]

while count_tokens(system + conversation) &amp;gt; usable_limit and len(conversation) &amp;gt; 1:
    conversation = conversation[2:]  # Drop oldest user+assistant pair

trimmed_messages = system + conversation

response = client.chat.completions.create(
    model=model,
    messages=trimmed_messages
)

return response.choices[0].message.content
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
This is a simplified illustration. Production systems need more nuanced strategies — summarisation of dropped context, semantic retrieval of relevant history, or explicit memory management layers. But the underlying constraint is the same regardless of how you handle it.

The Lost in the Middle Problem

Larger context windows have enabled new use cases — full document analysis, long research sessions, multi-document reasoning. But a larger ceiling hasn't eliminated positional bias.

Research has shown that models attend more strongly to content at the beginning and end of long contexts than to content buried in the middle. The implication for prompt design is direct:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;br&gt;
python&lt;br&gt;
def structure_prompt_for_attention(&lt;br&gt;
    task_instruction: str,&lt;br&gt;
    background_context: str,&lt;br&gt;
    primary_document: str,&lt;br&gt;
    output_format: str&lt;br&gt;
) -&amp;gt; str:&lt;br&gt;
    """&lt;br&gt;
    Structure prompt to put high-attention content at boundaries.&lt;br&gt;
    Task instruction and output format bookend the context.&lt;br&gt;
    Background goes in the middle where precision matters less.&lt;br&gt;
    """&lt;br&gt;
    return f"""TASK: {task_instruction}&lt;/p&gt;

&lt;p&gt;OUTPUT FORMAT: {output_format}&lt;/p&gt;

&lt;p&gt;BACKGROUND CONTEXT:&lt;br&gt;
{background_context}&lt;/p&gt;

&lt;p&gt;PRIMARY DOCUMENT TO ANALYSE:&lt;br&gt;
{primary_document}&lt;/p&gt;

&lt;p&gt;Reminder: {task_instruction}&lt;br&gt;
Respond in the format specified above."""&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
The task instruction appears twice — at the top and again as a reminder before the model generates output. The format specification is also near the top. The background context, which requires less precision, sits in the middle where attention is naturally lower.

This is not a workaround for a bug. It is prompt design that accounts for how attention actually distributes across a long context.

Practical Token Efficiency

One of the highest-leverage early habits for anyone calling LLM APIs is prompt auditing — measuring actual token consumption before scaling.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;br&gt;
import tiktoken&lt;/p&gt;

&lt;p&gt;def audit_prompt(system_prompt: str, user_message: str, model: str = "gpt-4o") -&amp;gt; dict:&lt;br&gt;
    """&lt;br&gt;
    Audit token usage before sending — useful during development.&lt;br&gt;
    """&lt;br&gt;
    encoder = tiktoken.encoding_for_model(model)&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;system_tokens = len(encoder.encode(system_prompt))
user_tokens = len(encoder.encode(user_message))
total_input = system_tokens + user_tokens

# Approximate cost at GPT-4o input pricing (verify current pricing)
cost_per_million = 5.00  # USD — check current pricing at platform.openai.com
estimated_cost = (total_input / 1_000_000) * cost_per_million

return {
    "system_tokens": system_tokens,
    "user_tokens": user_tokens,
    "total_input_tokens": total_input,
    "estimated_cost_per_call_usd": round(estimated_cost, 6),
    "note": "Output tokens billed separately. Verify pricing at platform.openai.com"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h1&gt;
  
  
  Usage
&lt;/h1&gt;

&lt;p&gt;result = audit_prompt(&lt;br&gt;
    system_prompt="You are a helpful assistant specialising in contract review.",&lt;br&gt;
    user_message="Review the following contract and identify any unusual indemnity clauses: [contract text]"&lt;br&gt;
)&lt;br&gt;
print(result)&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


Running this during development — before committing to a prompt structure  surfaces inefficiencies early, when they're cheap to fix.

 What Comes Next

Tokenisation prepares the text. The context window determines what the model can see. But neither of these explains how the model derives meaning from those chunks.

That's Part 3. We'll look at embeddings — how models represent concepts as positions in geometric space, and why that representation is the key to understanding semantic search, retrieval, and why AI can find relevant information even when you don't use the exact right words.

See you there.

Created with AI assistance. Originally published at [[Context First AI](https://contextfirst.ai)]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>ai</category>
      <category>beginners</category>
      <category>llm</category>
      <category>nlp</category>
    </item>
    <item>
      <title>The Autocomplete That Ate the World: What LLMs Actually Are (And How They Learn).</title>
      <dc:creator>Context First AI</dc:creator>
      <pubDate>Tue, 24 Mar 2026 11:56:51 +0000</pubDate>
      <link>https://dev.to/contextfirstai/the-autocomplete-that-ate-the-world-what-llms-actually-are-and-how-they-learn-3maa</link>
      <guid>https://dev.to/contextfirstai/the-autocomplete-that-ate-the-world-what-llms-actually-are-and-how-they-learn-3maa</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6tskd29rernito6ppfay.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6tskd29rernito6ppfay.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A large language model is a next-token prediction machine trained on hundreds of billions of words. It doesn't verify facts — it predicts plausible text. It has no memory between sessions. And the capabilities that make it remarkable weren't programmed in — they emerged from scale. This post explains what that means, why it matters, and what it changes about how you use these tools.&lt;/p&gt;

&lt;p&gt;This is Part 1 of a five-part series from the Vectors pillar of Context First AI. Built for anyone starting their AI journey — developer or not. No prior knowledge assumed. Each part builds on the last.&lt;/p&gt;

&lt;p&gt;Full series:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Part 1 — The Autocomplete That Ate the World*&lt;/li&gt;
&lt;li&gt;Part 2 — You're Not Reading Words, You're Reading Chunks*&lt;/li&gt;
&lt;li&gt;Part 3 — Meaning Has a Shape*&lt;/li&gt;
&lt;li&gt;Part 4 — You're Not Writing Prompts, You're Writing Instructions for a Very Particular Mind&lt;/li&gt;
&lt;li&gt;Part 5 — What to Do When the Model Doesn't Know Enough&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Feeling Nobody Talks About&lt;/p&gt;

&lt;p&gt;It started, for a lot of developers, somewhere around the third or fourth time they used an AI tool and couldn't explain why it behaved the way it did.&lt;/p&gt;

&lt;p&gt;Not a junior developer on their first project — a mid-level engineer with five years of experience, someone comfortable with APIs, databases, asynchronous logic. They could call the OpenAI API. They could parse the response. They could wire it into a product. But the &lt;em&gt;why&lt;/em&gt; behind what came back — why the same prompt produced different results, why the model sometimes confidently produced nonsense, why it seemed to forget everything from the last session — remained opaque.&lt;/p&gt;

&lt;p&gt;That gap matters more than it might seem. Because when something breaks and you don't understand the underlying model, debugging becomes guesswork.&lt;/p&gt;

&lt;p&gt;So. Let's close the gap.&lt;/p&gt;

&lt;p&gt;What an LLM Actually Is&lt;/p&gt;

&lt;p&gt;A large language model — an LLM — has one core mechanism: next-token prediction.&lt;/p&gt;

&lt;p&gt;You give it a sequence of tokens (we'll cover what tokens are in Part 2 — for now, think of them as chunks of text). It produces a probability distribution over all possible next tokens. It samples from that distribution. That sampled token gets appended to the sequence. The process repeats.&lt;/p&gt;

&lt;p&gt;In pseudocode, the core loop looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;tokenize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c1"&gt;# Model produces probability distribution over vocabulary
&lt;/span&gt;        &lt;span class="n"&gt;logits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forward&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;probabilities&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;softmax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logits&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Sample next token from distribution
&lt;/span&gt;        &lt;span class="n"&gt;next_token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sample&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;probabilities&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;next_token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Stop if end-of-sequence token is produced
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;next_token&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;EOS_TOKEN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;detokenize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;This&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;simplified&lt;/span&gt; &lt;span class="n"&gt;sketch&lt;/span&gt; &lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="n"&gt;real&lt;/span&gt; &lt;span class="n"&gt;implementations&lt;/span&gt; &lt;span class="n"&gt;involve&lt;/span&gt; &lt;span class="n"&gt;batching&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="n"&gt;caching&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;various&lt;/span&gt; &lt;span class="n"&gt;sampling&lt;/span&gt; &lt;span class="n"&gt;strategies&lt;/span&gt; &lt;span class="n"&gt;like&lt;/span&gt; &lt;span class="n"&gt;temperature&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;But&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;loop&lt;/span&gt; &lt;span class="n"&gt;itself&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;accurate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;The&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;retrieving&lt;/span&gt; &lt;span class="n"&gt;answers&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;database&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;It&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;searching&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;web&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;It&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;predicting&lt;/span&gt; &lt;span class="n"&gt;what&lt;/span&gt; &lt;span class="n"&gt;comes&lt;/span&gt; &lt;span class="nb"&gt;next&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;one&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;using&lt;/span&gt; &lt;span class="n"&gt;patterns&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="n"&gt;absorbed&lt;/span&gt; &lt;span class="n"&gt;during&lt;/span&gt; &lt;span class="n"&gt;training&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="n"&gt;That&lt;/span&gt; &lt;span class="n"&gt;distinction&lt;/span&gt; &lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="n"&gt;prediction&lt;/span&gt; &lt;span class="n"&gt;versus&lt;/span&gt; &lt;span class="n"&gt;retrieval&lt;/span&gt; &lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;foundational&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;Keep&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="n"&gt;How&lt;/span&gt; &lt;span class="n"&gt;Pre&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;Training&lt;/span&gt; &lt;span class="n"&gt;Works&lt;/span&gt;

&lt;span class="n"&gt;Before&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;can&lt;/span&gt; &lt;span class="n"&gt;predict&lt;/span&gt; &lt;span class="n"&gt;anything&lt;/span&gt; &lt;span class="n"&gt;usefully&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="n"&gt;has&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;learn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;This&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;called&lt;/span&gt; &lt;span class="n"&gt;pre&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;training&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;process&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="n"&gt;creates&lt;/span&gt; &lt;span class="n"&gt;everything&lt;/span&gt; &lt;span class="n"&gt;downstream&lt;/span&gt; &lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;knowledge&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;reasoning&lt;/span&gt; &lt;span class="n"&gt;patterns&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;stylistic&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;all&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="n"&gt;The&lt;/span&gt; &lt;span class="n"&gt;training&lt;/span&gt; &lt;span class="n"&gt;setup&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;deceptively&lt;/span&gt; &lt;span class="n"&gt;simple&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="n"&gt;Take&lt;/span&gt; &lt;span class="n"&gt;an&lt;/span&gt; &lt;span class="n"&gt;enormous&lt;/span&gt; &lt;span class="n"&gt;corpus&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="n"&gt;hundreds&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;billions&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;words&lt;/span&gt; &lt;span class="n"&gt;drawn&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;books&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;websites&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="n"&gt;repositories&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;articles&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;more&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;Feed&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;Ask&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;predict&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="nb"&gt;next&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;each&lt;/span&gt; &lt;span class="n"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;Measure&lt;/span&gt; &lt;span class="n"&gt;how&lt;/span&gt; &lt;span class="n"&gt;wrong&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="n"&gt;was&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;Update&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;weights&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;slightly&lt;/span&gt; &lt;span class="n"&gt;less&lt;/span&gt; &lt;span class="n"&gt;wrong&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;Repeat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="n"&gt;In&lt;/span&gt; &lt;span class="n"&gt;practice&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;framed&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;minimising&lt;/span&gt; &lt;span class="n"&gt;cross&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;entropy&lt;/span&gt; &lt;span class="n"&gt;loss&lt;/span&gt; &lt;span class="n"&gt;between&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s predicted distribution and the actual next token:

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;br&gt;
import torch&lt;br&gt;
import torch.nn.functional as F&lt;/p&gt;

&lt;p&gt;def compute_loss(logits, targets):&lt;br&gt;
    # logits: (batch_size, sequence_length, vocab_size)&lt;br&gt;
    # targets: (batch_size, sequence_length)&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Reshape for cross-entropy computation
logits = logits.view(-1, logits.size(-1))  # (batch * seq_len, vocab_size)
targets = targets.view(-1)                  # (batch * seq_len,)

return F.cross_entropy(logits, targets)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
The model has no explicit labels, no curated Q&amp;amp;A pairs, no hand-crafted rules. Just text and the task of predicting the next piece of it. Across trillions of these prediction attempts, something emerges: internal representations of grammar, factual associations, reasoning structures, code syntax — and something that looks, in practice, remarkably like understanding.

We wouldn't call it understanding in the philosophical sense. But for the purposes of building on top of it, it behaves like understanding in most situations that matter.

Why Scale Changes Everything

Here is the part that surprised even the researchers building these systems.

When you increase model size — more parameters, more training data, more compute — the model does not simply get incrementally better at prediction. At certain scale thresholds, new capabilities appear that were not present in smaller versions of the same architecture.

The model can answer questions it was never directly trained on. It can write working code in languages it was not explicitly fine-tuned for. It can follow complex multi-step instructions. It can explain its own reasoning. These are called **emergent capabilities**, and their appearance at scale is one of the more genuinely surprising empirical findings in recent AI research.

A rough intuition: a smaller model learns surface patterns. A larger model, trained on enough varied data, is forced to develop something closer to a generalisable internal model of how language and ideas work — because that is the only way to keep improving at prediction across such varied input.

From a developer's perspective, the practical implication is this: the capabilities you can build on top of a frontier model are substantially different from what was possible two or three years ago. Not just better — qualitatively different.

Three Things That Change How You Build

Now that the mechanism is clear, here are three behavioural realities worth internalising before you write another line of code that calls an LLM.

1. Confidence is not accuracy

When an LLM produces a confident-sounding answer, it is not because the model has verified the claim. It is because confident-sounding text frequently follows prompts like yours in its training distribution.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;br&gt;
python&lt;/p&gt;
&lt;h1&gt;
  
  
  This prompt will get a confident-sounding answer regardless of accuracy
&lt;/h1&gt;

&lt;p&gt;prompt = "What was the revenue of Acme Corp in Q3 2024?"&lt;/p&gt;
&lt;h1&gt;
  
  
  The model has no access to this data. It will predict plausible-sounding text.
&lt;/h1&gt;
&lt;h1&gt;
  
  
  If Acme Corp is not in its training data, it may fabricate a number.
&lt;/h1&gt;
&lt;h1&gt;
  
  
  If it is, that data may be outdated or misremembered.
&lt;/h1&gt;
&lt;h1&gt;
  
  
  Mitigation: supply the data in context, or use retrieval (covered in Part 5)
&lt;/h1&gt;

&lt;p&gt;prompt_with_context = """&lt;br&gt;
The following is Acme Corp's Q3 2024 financial report:&lt;br&gt;
[PASTE ACTUAL DATA HERE]&lt;/p&gt;

&lt;p&gt;Based only on the above, what was Acme Corp's revenue in Q3 2024?&lt;/p&gt;

&lt;p&gt;The fix is not to distrust the model — it is to supply the information you need it to reason over, rather than asking it to retrieve information from its weights.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;There is no memory between sessions&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each API call, each new conversation, starts from the same base model state. Nothing persists.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Session 1
&lt;/span&gt;&lt;span class="n"&gt;response_1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4o&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;My name is Alex and I work in compliance.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Model now knows this — within this session
&lt;/span&gt;
&lt;span class="c1"&gt;# Session 2 (new API call, no history passed)
&lt;/span&gt;&lt;span class="n"&gt;response_2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4o&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;What did I tell you about my role?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Model has no idea. Previous session is completely gone.
&lt;/span&gt;
&lt;span class="c1"&gt;# Correct approach: pass conversation history explicitly
&lt;/span&gt;&lt;span class="n"&gt;conversation_history&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;My name is Alex and I work in compliance.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;assistant&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;response_1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;What did I tell you about my role?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;response_3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4o&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;conversation_history&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Now the model has the context it needs
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Managing conversation history is your responsibility as the developer. The model does not maintain state. You do.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Training distribution shapes output quality&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The model performs best on topics, formats, and styles that were well-represented in its training data. Push it into territory that was sparse in training — highly specialised domains, obscure technical standards, your internal company knowledge — and quality degrades.&lt;/p&gt;

&lt;p&gt;This is not a bug. It is a logical consequence of how learning works. The mitigation is to supply the relevant information in context, or to fine-tune on domain-specific data — both of which are topics for later in this series.&lt;/p&gt;

&lt;p&gt;What This Foundation Unlocks&lt;/p&gt;

&lt;p&gt;Understanding pre-training changes how you debug, how you architect, and how you set expectations.&lt;/p&gt;

&lt;p&gt;When a model produces incorrect output, the first question is no longer "is the model broken?" It is "what did the model have to work with?" Was it relying on parametric knowledge that may be outdated or absent? Was the context window structured in a way that buried the important information? Was the prompt specific enough to narrow the prediction space toward what you actually needed?&lt;/p&gt;

&lt;p&gt;These are tractable questions. And they are only askable once you understand what an LLM actually is.&lt;/p&gt;

&lt;p&gt;What Comes Next&lt;/p&gt;

&lt;p&gt;Part 2 covers tokens and context windows — the mechanics that determine what the model can see and process at any one time. For developers, this is where token counting, chunking strategies, and context management start to make concrete sense.&lt;/p&gt;

&lt;p&gt;We'll see you there.&lt;/p&gt;

&lt;p&gt;Created with AI assistance. Originally published at [&lt;a href="https://contextfirst.ai" rel="noopener noreferrer"&gt;Context First AI&lt;/a&gt;]&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Middle Management and AI: The Overlooked Bottleneck.</title>
      <dc:creator>Context First AI</dc:creator>
      <pubDate>Mon, 23 Mar 2026 07:33:32 +0000</pubDate>
      <link>https://dev.to/contextfirstai/middle-management-and-ai-the-overlooked-bottleneck-j8k</link>
      <guid>https://dev.to/contextfirstai/middle-management-and-ai-the-overlooked-bottleneck-j8k</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fczx0vsjd87njpcggq1r4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fczx0vsjd87njpcggq1r4.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Most people think AI adoption fails because of bad tools or budget. That's wrong. The real bottleneck is middle management — not because they're resistant, but because nobody's answered the question they're actually asking: &lt;em&gt;what's my value once the software does what I used to do?&lt;/em&gt; Fix the sequencing, not the messaging.&lt;/p&gt;

&lt;p&gt;Middle Management and AI: The Overlooked Bottleneck&lt;/p&gt;

&lt;p&gt;Orchestration | AI Adoption | Operations Strategy&lt;/p&gt;

&lt;p&gt;The most common reason AI initiatives stall inside growing businesses isn't budget, and it isn't the technology. It's the layer of the organisation that sits between the people making the decisions and the people doing the work — and nobody's talking about it honestly.&lt;/p&gt;

&lt;p&gt;We've spent a lot of time inside SMBs watching AI rollouts unfold, and a pattern has emerged that's uncomfortable to name: middle management is often where momentum goes to die. Not out of malice. Not even out of resistance in the traditional sense. But because the people we've asked to champion change are also the people most uncertain about what that change means for them.&lt;/p&gt;

&lt;p&gt;A Pattern We Keep Seeing&lt;/p&gt;

&lt;p&gt;Picture a 70-person professional services firm. The founder has come back from a conference lit up about AI. The ops team has started experimenting with automation tools. Two new SaaS subscriptions have been approved. And then — nothing. Six weeks later, the tools are still sitting in free trial limbo, the team leads are waiting for clearer instructions, and the founder is wondering why "adoption" hasn't happened.&lt;/p&gt;

&lt;p&gt;We've seen versions of this across sectors: a department head at a mid-sized logistics company quietly running parallel manual processes alongside the new AI-assisted workflow because "I don't fully trust it yet." A senior project manager at a 40-person consultancy who never quite finds the time to complete the AI onboarding training because their calendar is already full of the things the AI is supposed to eventually replace. It's not sabotage. It's something more structurally interesting than that.&lt;/p&gt;

&lt;p&gt;The managing director sets the direction. The frontline staff follow instructions. Middle management — team leads, department heads, operations managers, senior coordinators — are the interpreters. And if they don't understand what they're being asked to interpret, or if the new direction quietly threatens the value they've built over years, the message gets softened on its way down. Sometimes it disappears entirely.&lt;/p&gt;

&lt;p&gt;The Problem Nobody Is Naming&lt;/p&gt;

&lt;p&gt;Most AI adoption frameworks have this backwards. They treat middle management as a communications challenge — get the messaging right, run the change management workshop, and the organisation will follow. That's wrong. It misreads what's actually happening.&lt;/p&gt;

&lt;p&gt;The people caught in the middle of these transitions are often the most operationally experienced people in your business. They've seen initiatives come and go. They have hard-won instincts about what works on the ground. And they're being asked to advocate for tools they haven't mastered, in processes they've spent years refining, while simultaneously fielding the anxious questions of the staff below them.&lt;/p&gt;

&lt;p&gt;That's not a messaging problem. It's a structural one.&lt;/p&gt;

&lt;p&gt;Here's the uncomfortable bit: AI, done well, doesn't just assist middle managers — it can functionally absorb parts of their role. Reporting, synthesis, first-pass quality checks, workload distribution, performance monitoring. These are the operational tasks that many middle management layers were built to perform.&lt;/p&gt;

&lt;p&gt;When a piece of software starts doing them faster and more consistently, the existential question — &lt;em&gt;what exactly is my value here?&lt;/em&gt; — doesn't need to be spoken aloud to be felt. It sits in the room.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We're not saying middle managers are about to be replaced en masse. We're saying they often believe they might be, and that belief is shaping their behaviour in ways that aren't being acknowledged or addressed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  What AI Actually Touches in a Manager's Week
&lt;/h3&gt;

&lt;p&gt;To make this concrete: here's the kind of task audit that surfaces when you ask a team lead to log what they actually do in a week:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Illustrative task audit — categorising a team lead's weekly time
&lt;/span&gt;&lt;span class="n"&gt;weekly_tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;information_compilation&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tasks&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Weekly status report (team → leadership)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Data aggregation from project trackers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;First-pass quality checks on team outputs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Attendance and workload distribution&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;avg_hours&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;9.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ai_automatable&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;judgement_and_relationship&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tasks&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Client-facing escalations&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Team coaching and 1:1s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Contextual decision-making&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Institutional knowledge transfer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;avg_hours&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;6.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ai_automatable&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;administrative&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tasks&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Meeting scheduling and coordination&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Onboarding documentation&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Compliance logging&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;avg_hours&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;4.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ai_automatable&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;automatable_hours&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;avg_hours&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;weekly_tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ai_automatable&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;total_hours&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;avg_hours&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;weekly_tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Automatable: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;automatable_hours&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;h / &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;total_hours&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;h total&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;That&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;automatable_hours&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;total_hours&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;% of the week&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Output: Automatable: 14.0h / 20.0h total
# That's 70% of the week
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you surface that number to a team lead — 70% of their current week could be absorbed by AI tooling — the existential question stops being theoretical. The adoption conversation has to start there, not with a product demo.&lt;/p&gt;

&lt;p&gt;What Actually Moves the Needle&lt;/p&gt;

&lt;p&gt;The businesses we've seen navigate this well share one counterintuitive trait: they don't position AI as a productivity multiplier in their internal communications. At least not initially. They position it as a decision-quality multiplier — and they start with the people in the middle.&lt;/p&gt;

&lt;p&gt;When an operations manager at a growing manufacturing company understands that AI is giving them better data to make better calls — rather than replacing the calls they currently make — they stop experiencing it as a threat and start experiencing it as leverage. Real leverage. The kind that makes their existing expertise more valuable, not redundant.&lt;/p&gt;

&lt;p&gt;This reframe isn't spin. It's accurate. AI tools in most SMB contexts are nowhere near ready to replace the contextual judgement, client relationships, and institutional knowledge that experienced managers carry. What they can do is reduce the volume of low-signal work that currently buries that judgement under spreadsheets and status meetings.&lt;/p&gt;

&lt;p&gt;The shift is subtle but it matters:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;❌ "AI will do your job"&lt;br&gt;
✅ "AI will give you the headroom to do your job properly"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Making It Practical&lt;/p&gt;

&lt;p&gt;The implementation question is where most frameworks skip too quickly to the tools and not enough to the sequencing.&lt;/p&gt;

&lt;p&gt;Step 1: Start with one visible use case for the middle layer&lt;/p&gt;

&lt;p&gt;Not their team. Not leadership. Them.&lt;/p&gt;

&lt;p&gt;Give a senior team lead an AI-assisted reporting tool that cuts their weekly summary from ninety minutes to twenty. Let a department head use AI to draft first-pass project briefs they currently write from scratch.&lt;/p&gt;

&lt;p&gt;Here's a simple Python pattern for the kind of reporting automation that makes a real dent:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;anthropic&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;anthropic&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Anthropic&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate_weekly_summary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raw_updates&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;team_context&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Transform raw team status updates into a structured weekly summary.
    Cuts synthesis time from ~90 mins to review-and-edit only.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;combined_updates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;- &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;update&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;raw_updates&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;claude-opus-4-5&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;You are a senior operations assistant.

Team context: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;team_context&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;

Raw updates from team this week:
&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;combined_updates&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;

Produce a concise weekly summary for leadership covering:
1. Progress against key objectives (2-3 sentences)
2. Blockers requiring escalation (if any)
3. Planned focus for next week

Be specific. No filler. Write for someone who reads fast.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;


&lt;span class="c1"&gt;# Usage
&lt;/span&gt;&lt;span class="n"&gt;team_context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8-person product delivery team, mid-sprint on Q2 infrastructure migration&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;raw_updates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Database migration 60% complete, on track for Thursday&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Auth service blocked on vendor API access — chasing since Monday&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Two team members out sick Wed/Thu, redistributed tasks&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Client demo prep finished and signed off&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;summary&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generate_weekly_summary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raw_updates&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;team_context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output still gets reviewed and edited by the team lead. That's the point. The cognitive labour of synthesis is handled; the contextual judgement of what to flag and how to frame it remains theirs.&lt;/p&gt;

&lt;p&gt;Step 2: Build in explicit permission to critique&lt;/p&gt;

&lt;p&gt;Middle managers who feel they can say "this tool doesn't work for how we actually run this process" are far more likely to engage honestly with the rollout than those who feel they're expected to perform enthusiasm.&lt;/p&gt;

&lt;p&gt;The feedback loop needs to run upward — and someone at the top needs to visibly act on it. A simple structured feedback template for each tool trial period:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Lightweight feedback schema for mid-tier AI tool rollouts&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;toolFeedbackSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;tool_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;team_lead_role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;trial_period_weeks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;feedback&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;time_saved_per_week_hours&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;tasks_it_handles_well&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;tasks_it_handles_poorly&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;blockers_to_adoption&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;would_recommend_to_peers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;open_question&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;What would need to change for this to become a default part of your workflow?&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// Example completed response&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;exampleFeedback&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;tool_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;AI Reporting Assistant&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;team_lead_role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Senior Operations Lead&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;trial_period_weeks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;feedback&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;time_saved_per_week_hours&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;4.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;tasks_it_handles_well&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Status aggregation&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;First-draft summaries&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;tasks_it_handles_poorly&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Context-specific escalation framing&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;blockers_to_adoption&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Output needs significant editing for our client tone&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;would_recommend_to_peers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;open_question&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;If it could learn our standard reporting format and client terminology, it'd be ready to roll out tomorrow.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That last open question is the one that matters most. Act on the answers publicly and the credibility of the whole rollout changes.&lt;/p&gt;

&lt;p&gt;Step 3: Fill the space AI creates&lt;/p&gt;

&lt;p&gt;We're not entirely sure how to prescribe the pacing here — it varies enormously by team culture and what AI tools are actually in play. But we'd push back hard against the 30-day big-bang rollout that a lot of consultants seem to love.&lt;/p&gt;

&lt;p&gt;Slower, deeper adoption in one department tends to produce more durable results than organisation-wide pilots that nobody quite commits to.&lt;/p&gt;

&lt;p&gt;When automation absorbs the aggregation and reporting work, middle managers need a clear understanding of what their role now contains. If you don't fill that space with something meaningful — more coaching time, more client-facing work, more strategic input — the role starts to feel like it's shrinking, even if it isn't. That feeling is its own kind of resistance.&lt;/p&gt;

&lt;p&gt;What Changes When It Works&lt;/p&gt;

&lt;p&gt;When middle management is genuinely on board with AI adoption, the change in organisational velocity is hard to overstate. Decisions move faster because the people interpreting direction upward and downward have better information and more time to think. Team-level resistance tends to dissolve more quickly because the person closest to the team understands and believes in what they're asking their people to do.&lt;/p&gt;

&lt;p&gt;A senior operations manager at a 60-person services company described the shift to us this way: before AI tools were embedded into their workflow, their week was 60% spent compiling information and 40% acting on it. After roughly three months of structured adoption, that ratio had roughly inverted. The quality of team conversations improved because the background noise had been turned down.&lt;/p&gt;

&lt;p&gt;That's not a small thing. That's what meaningful adoption actually looks like — not a dashboard metric, but a change in how people experience their working week.&lt;/p&gt;

&lt;p&gt;Key Takeaways&lt;/p&gt;

&lt;p&gt;We'd rather give you four honest takeaways than five tidy ones.&lt;/p&gt;

&lt;p&gt;The bottleneck is structural, not attitudinal. Middle management friction around AI adoption isn't stubbornness — it's a rational response to genuine role ambiguity. Address the structure, not the behaviour.&lt;/p&gt;

&lt;p&gt;Start with what reduces friction for the middle layer first. If the first people to feel the benefit of AI are team leads and department heads, the adoption conversation changes character almost immediately.&lt;/p&gt;

&lt;p&gt;Build in real permission to critique.** Enthusiasm that isn't earned is fragile. Create honest feedback loops and act on what comes back.&lt;/p&gt;

&lt;p&gt;Fill the space AI creates with something meaningful.** When automation absorbs operational tasks, middle managers need a clear answer to "so what do I do with that time?" Without one, the headroom becomes anxiety.&lt;/p&gt;

&lt;p&gt;How Context First AI Approaches This&lt;/p&gt;

&lt;p&gt;At Context First AI, we've built our entire platform around the idea that AI adoption lives or dies on whether the right people have the right context at the right moment — and that includes the managers sitting in the middle of your organisational structure.&lt;/p&gt;

&lt;p&gt;Through the Orchestration pillar, we work with SMB founders, ops leaders, and C-suite teams to map the actual human architecture of their business before recommending any tools or workflows. The question we ask first is never "what AI should we deploy?" It's "where does information currently get stuck, and who's responsible for moving it?" More often than not, that analysis surfaces the middle management layer as both the critical bottleneck and the highest-leverage point for intervention.&lt;/p&gt;

&lt;p&gt;Our approach is practical rather than prescriptive. We don't arrive with a pre-packaged AI stack. We work from your existing processes, identify the operational tasks that are consuming disproportionate attention at the team lead and department head level, and find targeted ways to reduce that load — building in fluency and confidence before we push adoption wider.&lt;/p&gt;

&lt;p&gt;The Mesh community connects practitioners inside businesses going through exactly these transitions. If you're a senior ops manager trying to figure out where AI fits into your current role, or a founder watching a rollout stall and wondering why, there are people in that community who've been through the same conversation.&lt;/p&gt;

&lt;p&gt;Context First AI's view is simple: the organisations that get AI adoption right are the ones that treat it as a people problem first and a technology problem second. Middle managers aren't the obstacle to that. They're the answer — if you equip them properly.&lt;/p&gt;

&lt;p&gt;Conclusion&lt;/p&gt;

&lt;p&gt;The next two to three years are going to produce a significant divergence between businesses that embedded AI deeply into how they work and those that ran a series of pilots and moved on. We think the dividing line won't be which tools were chosen. It'll be whether the middle layer of those organisations became advocates or bystanders.&lt;/p&gt;

&lt;p&gt;That's still a choice you can influence. But the window for a thoughtful, structured approach to it is shorter than most founders realise, and the default — assuming AI adoption will trickle down from the top once the strategy is set — has a pretty poor track record.&lt;/p&gt;

&lt;p&gt;The bottleneck is identifiable, it's addressable, and it's largely being ignored while everyone debates the tools.&lt;/p&gt;

&lt;p&gt;Worth paying attention to.&lt;/p&gt;

&lt;p&gt;Resources&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;[MIT Sloan Management Review — &lt;a href="https://sloanreview.mit.edu/article/why-middle-managers-are-key-to-ai-success/" rel="noopener noreferrer"&gt;Why Middle Managers Are Key to AI Success&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;[Harvard Business Review — &lt;a href="https://hbr.org/2023/05/the-middle-manager-of-the-future" rel="noopener noreferrer"&gt;The Middle Manager of the Future&lt;/a&gt;]&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://contextfirstai.com/orchestration" rel="noopener noreferrer"&gt;[Context First AI — Orchestration]&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Created with AI assistance. Originally published at [&lt;a href="https://contextfirstai.com" rel="noopener noreferrer"&gt;Context First AI&lt;/a&gt;]&lt;/p&gt;

</description>
      <category>ai</category>
      <category>career</category>
      <category>management</category>
      <category>productivity</category>
    </item>
    <item>
      <title>The AI Community Gap Is Real And It's Not What You Think.</title>
      <dc:creator>Context First AI</dc:creator>
      <pubDate>Sat, 21 Mar 2026 12:23:58 +0000</pubDate>
      <link>https://dev.to/contextfirstai/the-ai-community-gap-is-real-and-its-not-what-you-think-1bfh</link>
      <guid>https://dev.to/contextfirstai/the-ai-community-gap-is-real-and-its-not-what-you-think-1bfh</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffeebm5kj3r8w79f2cavu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffeebm5kj3r8w79f2cavu.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The knowledge that actually unblocks AI practitioners in production doesn't live in textbooks — it lives in other practitioners. Most AI communities aren't built to surface that layer. Mesh is. It's a tiered practitioner community in development, and the people getting involved now will shape what it becomes.&lt;/p&gt;

&lt;p&gt;It Started With a RAG Pipeline That Half-Worked&lt;/p&gt;

&lt;p&gt;A senior engineer on a five-person ML team deploys their first retrieval-augmented generation system into production. The retrieval quality is inconsistent. The chunking strategy that worked on the eval dataset isn't holding up on real queries. The documentation doesn't cover this edge case. Stack Overflow has a six-month-old thread with no accepted answer.&lt;/p&gt;

&lt;p&gt;They spend three days debugging. They figure it out — eventually. Alone.&lt;/p&gt;

&lt;p&gt;This isn't an unusual story. We've heard it in almost every conversation we've had with practitioners building AI applications in professional contexts.&lt;/p&gt;

&lt;p&gt;The problem isn't that good knowledge doesn't exist. It's that it's distributed across people who are quietly doing the work — and there's nowhere useful for them to write it down.&lt;/p&gt;

&lt;p&gt;That's the community gap. And it's distinct from a skills gap in one important way: you can close a skills gap with a course. You close a community gap with a room full of the right people.&lt;/p&gt;

&lt;p&gt;What the Knowledge Gap Actually Looks Like in Practice&lt;/p&gt;

&lt;p&gt;Here's the kind of problem that gets solved peer-to-peer and almost never gets documented properly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;The&lt;/span&gt; &lt;span class="n"&gt;naive&lt;/span&gt; &lt;span class="n"&gt;chunking&lt;/span&gt; &lt;span class="n"&gt;approach&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="n"&gt;looks&lt;/span&gt; &lt;span class="n"&gt;fine&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;evaluation&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;chunk_document&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chunk_size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;chunk_size&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;chunk_size&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

&lt;span class="c1"&gt;# What you discover in production: fixed-size chunking splits sentences mid-thought.
# Semantic similarity retrieval degrades. Relevant context gets cut.
&lt;/span&gt;
&lt;span class="c1"&gt;# What practitioners who've been here already know to try:
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;langchain.text_splitter&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;RecursiveCharacterTextSplitter&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;chunk_document_properly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="n"&gt;splitter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RecursiveCharacterTextSplitter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;chunk_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;chunk_overlap&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;          &lt;span class="c1"&gt;# Overlap preserves context across boundaries
&lt;/span&gt;        &lt;span class="n"&gt;separators&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="c1"&gt;# Respect natural language structure
&lt;/span&gt;    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;splitter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split_text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;The&lt;/span&gt; &lt;span class="n"&gt;difference&lt;/span&gt; &lt;span class="n"&gt;between&lt;/span&gt; &lt;span class="n"&gt;these&lt;/span&gt; &lt;span class="n"&gt;two&lt;/span&gt; &lt;span class="n"&gt;approaches&lt;/span&gt; &lt;span class="n"&gt;isn&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;t in any introductory course on RAG. It&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;head&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;engineer&lt;/span&gt; &lt;span class="n"&gt;who&lt;/span&gt; &lt;span class="n"&gt;hit&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;production&lt;/span&gt; &lt;span class="n"&gt;wall&lt;/span&gt; &lt;span class="n"&gt;six&lt;/span&gt; &lt;span class="n"&gt;months&lt;/span&gt; &lt;span class="n"&gt;before&lt;/span&gt; &lt;span class="n"&gt;you&lt;/span&gt; &lt;span class="n"&gt;did&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="n"&gt;That&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s the peer layer. And most AI communities aren&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="n"&gt;structured&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;surface&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="n"&gt;What&lt;/span&gt; &lt;span class="n"&gt;Mesh&lt;/span&gt; &lt;span class="n"&gt;Actually&lt;/span&gt; &lt;span class="n"&gt;Is&lt;/span&gt;

&lt;span class="n"&gt;Not&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;Discord&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;Not&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;newsletter&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;comments&lt;/span&gt; &lt;span class="n"&gt;section&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;Not&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;LinkedIn&lt;/span&gt; &lt;span class="n"&gt;group&lt;/span&gt; &lt;span class="n"&gt;where&lt;/span&gt; &lt;span class="n"&gt;everyone&lt;/span&gt; &lt;span class="n"&gt;shares&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;same&lt;/span&gt; &lt;span class="n"&gt;five&lt;/span&gt; &lt;span class="n"&gt;articles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="n"&gt;Mesh&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;practitioner&lt;/span&gt; &lt;span class="n"&gt;community&lt;/span&gt; &lt;span class="n"&gt;built&lt;/span&gt; &lt;span class="n"&gt;around&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;single&lt;/span&gt; &lt;span class="n"&gt;premise&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;most&lt;/span&gt; &lt;span class="n"&gt;useful&lt;/span&gt; &lt;span class="n"&gt;AI&lt;/span&gt; &lt;span class="n"&gt;knowledge&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;distributed&lt;/span&gt; &lt;span class="n"&gt;across&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;people&lt;/span&gt; &lt;span class="n"&gt;quietly&lt;/span&gt; &lt;span class="n"&gt;doing&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;work&lt;/span&gt; &lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;ones&lt;/span&gt; &lt;span class="n"&gt;who&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ve already hit the wall you&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="n"&gt;re&lt;/span&gt; &lt;span class="n"&gt;about&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;hit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;found&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;way&lt;/span&gt; &lt;span class="n"&gt;through&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;never&lt;/span&gt; &lt;span class="n"&gt;found&lt;/span&gt; &lt;span class="n"&gt;anywhere&lt;/span&gt; &lt;span class="n"&gt;useful&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;write&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="n"&gt;down&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="n"&gt;We&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;re building the place where they write it down.

What That Looks Like at Each Tier

The community is tiered across four stages of practice:

| Tier | Stage | What You&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="n"&gt;re&lt;/span&gt; &lt;span class="n"&gt;Building&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|------|-------|----------------------|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;Token&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Foundations&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;First&lt;/span&gt; &lt;span class="n"&gt;integrations&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prompting&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;basic&lt;/span&gt; &lt;span class="n"&gt;LLM&lt;/span&gt; &lt;span class="n"&gt;workflows&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;Model&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Intermediate&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Production&lt;/span&gt; &lt;span class="n"&gt;deployments&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fine&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;tuning&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;evaluation&lt;/span&gt; &lt;span class="n"&gt;frameworks&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;Agent&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Advanced&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Multi&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;step&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="n"&gt;systems&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tool&lt;/span&gt; &lt;span class="n"&gt;use&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;orchestration&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;Agent&lt;/span&gt; &lt;span class="n"&gt;Pro&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Expert&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Production&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;grade&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="n"&gt;infrastructure&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;team&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt; &lt;span class="n"&gt;deployment&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;

&lt;span class="n"&gt;The&lt;/span&gt; &lt;span class="n"&gt;tiers&lt;/span&gt; &lt;span class="n"&gt;aren&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;t gatekeeping. They&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="n"&gt;re&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="nb"&gt;map&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;Each&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt; &lt;span class="n"&gt;opens&lt;/span&gt; &lt;span class="n"&gt;up&lt;/span&gt; &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;conversations&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;relevant&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;where&lt;/span&gt; &lt;span class="n"&gt;your&lt;/span&gt; &lt;span class="n"&gt;practice&lt;/span&gt; &lt;span class="n"&gt;actually&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;where&lt;/span&gt; &lt;span class="n"&gt;you&lt;/span&gt; &lt;span class="n"&gt;want&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="n"&gt;Why&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;Peer&lt;/span&gt; &lt;span class="n"&gt;Layer&lt;/span&gt; &lt;span class="n"&gt;Is&lt;/span&gt; &lt;span class="n"&gt;Underrated&lt;/span&gt;

&lt;span class="n"&gt;Most&lt;/span&gt; &lt;span class="n"&gt;AI&lt;/span&gt; &lt;span class="n"&gt;education&lt;/span&gt; &lt;span class="n"&gt;runs&lt;/span&gt; &lt;span class="n"&gt;top&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;down&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;Expert&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;student&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;Course&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;certificate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="n"&gt;There&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s a place for that — we&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;admit&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;But&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;problems&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="n"&gt;actually&lt;/span&gt; &lt;span class="n"&gt;slow&lt;/span&gt; &lt;span class="n"&gt;you&lt;/span&gt; &lt;span class="n"&gt;down&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;production&lt;/span&gt; &lt;span class="n"&gt;aren&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;t the ones covered in the curriculum.

Consider the evaluation problem. A team three months into production with a semantic search system notices that their retrieval quality has been silently degrading since a schema change two weeks ago. There&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt; &lt;span class="n"&gt;alert&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;No&lt;/span&gt; &lt;span class="n"&gt;course&lt;/span&gt; &lt;span class="n"&gt;covers&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;The&lt;/span&gt; &lt;span class="n"&gt;fix&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;when&lt;/span&gt; &lt;span class="n"&gt;they&lt;/span&gt; &lt;span class="n"&gt;find&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;straightforward&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;br&gt;
import numpy as np&lt;br&gt;
from sentence_transformers import SentenceTransformer&lt;/p&gt;

&lt;p&gt;def evaluate_retrieval_drift(&lt;br&gt;
    queries: list[str],&lt;br&gt;
    expected_docs: list[str],&lt;br&gt;
    retrieved_docs: list[str],&lt;br&gt;
    model_name: str = "all-MiniLM-L6-v2"&lt;br&gt;
) -&amp;gt; dict:&lt;br&gt;
    """&lt;br&gt;
    Compare semantic similarity between expected and retrieved documents.&lt;br&gt;
    Run this on a fixed eval set after every schema or embedding model change.&lt;br&gt;
    """&lt;br&gt;
    model = SentenceTransformer(model_name)&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;expected_embeddings = model.encode(expected_docs)
retrieved_embeddings = model.encode(retrieved_docs)

similarities = np.diag(
    np.dot(expected_embeddings, retrieved_embeddings.T) /
    (np.linalg.norm(expected_embeddings, axis=1) * 
     np.linalg.norm(retrieved_embeddings, axis=1))
)

return {
    "mean_similarity": float(np.mean(similarities)),
    "min_similarity": float(np.min(similarities)),
    "degraded_queries": [
        queries[i] for i, s in enumerate(similarities) if s &amp;lt; 0.75
    ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


This pattern — running a fixed eval set after every significant change — is standard practice for teams who've been burned by silent drift. It's not in the documentation. It's in the heads of the practitioners who've shipped three or four of these systems.

That's what the peer layer surfaces. Mesh is structured to get it out of heads and into writing.

Why the Community Is Being Built Before It's Crowded

This is the honest version of "early access."

We're in development. The people who get involved now will shape what Mesh becomes — the norms, the formats, the conversations that actually happen. That's not marketing language. It's just how communities work.

The first hundred practitioners in a room matter more than the next thousand. The early conversations set the tone for every conversation after.

Most communities optimise for growth: more members, more content, more engagement. We think that's the wrong order of operations.

**The quality of the community determines the quality of the knowledge.** Get that wrong at the start and you spend years trying to fix it.

The No-Performance-Layer Principle

LinkedIn exists. We know. Mesh isn't competing with it.

We're not interested in building a platform where practitioners share polished retrospectives of things that already succeeded. The messy middle is more useful: the experiments in progress, the approaches that didn't land, the honest assessment of tools that don't quite do what the landing page promises.

For a developer audience, this matters more than it might sound. How many times have you read a glowing write-up of a new framework, adopted it, and spent two weeks discovering the production limitations that were never mentioned?

The honest tool audit — the one that names the failure modes alongside the wins — is the most useful artefact a practitioner can produce. It's also the rarest.

Mesh is being built so it's less rare.

Where We Are Right Now

In development. Deliberately.

The tiered model is designed. The ethos — practitioner-first, peer-sourced, low tolerance for hype — is non-negotiable.

What we're doing now is talking to the people who want to be part of building it. If that's you, get in touch directly at https://www.contextfirstai.com. We'll have an honest conversation about what Mesh is, where it's going, and whether it's the right space for where your practice is heading.

We're not running a waitlist. We're having conversations.


*Created with AI assistance. Originally published at [[Context First AI](https://www.contextfirstai.com)]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
    </item>
    <item>
      <title>How AI Triages Resident Cases Before a Human Touches Them</title>
      <dc:creator>Context First AI</dc:creator>
      <pubDate>Fri, 20 Mar 2026 07:06:18 +0000</pubDate>
      <link>https://dev.to/contextfirstai/how-ai-triages-resident-cases-before-a-human-touches-them-58n9</link>
      <guid>https://dev.to/contextfirstai/how-ai-triages-resident-cases-before-a-human-touches-them-58n9</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fll7s7u37vs18c3j0p6lh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fll7s7u37vs18c3j0p6lh.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Most property ops teams don't have a prioritisation problem — they have a visibility problem. A production-grade AI triage system runs in three layers: keyword classification (fast, zero API cost), sentiment scoring (catches urgency keywords can't), and LLM routing (edge cases only — urgent cases skip it entirely). The flagging layer is where most internal builds fall short. Human override stays in by design.&lt;/p&gt;

&lt;p&gt;Most property operations teams don't have a prioritisation problem. They have a &lt;em&gt;visibility&lt;/em&gt; problem — and they're solving it with headcount when they should be solving it with logic.&lt;/p&gt;

&lt;p&gt;The Pattern We Keep Seeing&lt;/p&gt;

&lt;p&gt;Across portfolio operators and software teams building resident-facing products, the intake problem looks almost identical regardless of scale. A case manager arrives Monday morning to a queue of 40, 50, sometimes 80 unread messages. Somewhere in that queue is a burst pipe reported Friday night. It's sitting behind a paint touch-up request and a bin collection query. No system has surfaced it. No flag has been raised. The urgency is invisible until someone reads far enough down to find it.&lt;/p&gt;

&lt;p&gt;We've seen this described in near-identical terms by a compliance lead at a 200-unit build-to-rent operator and a product director at a facilities management SaaS company — different organisations, different software stacks, same Monday morning problem. The inbox is a flat list. Flat lists don't discriminate between a leaking roof and a cosmetic scratch. Humans have to do that work manually, and manual triage at scale is slow, inconsistent, and — when it fails — genuinely risky.&lt;/p&gt;

&lt;p&gt;The Problem Is Structural, Not Operational&lt;/p&gt;

&lt;p&gt;It's tempting to frame this as a staffing question. If the team were bigger, someone would always be available to read incoming cases in real time. But that misses the point. The constraint isn't availability — it's the cognitive overhead of routing. A skilled case manager can triage a single case in 30–60 seconds. Across 50 cases a day, that's close to 45 minutes of pure classification work, every day, before a single problem has actually been resolved. That's roughly 37% of a working morning spent deciding what to work on rather than working on it.&lt;/p&gt;

&lt;p&gt;Worse, manual triage is only as good as the last person who touched the queue. Inconsistency creeps in. A resident who's complained three times gets treated like a first contact. A household with a young child and a broken boiler in winter doesn't get flagged any differently than one without. The system has no memory, and it has no ability to read between the lines of a 400-word email written by someone who is increasingly furious.&lt;/p&gt;

&lt;p&gt;This is the problem AI triaging is designed to solve — not by replacing case manager judgement, but by doing the classification work before any human gets involved.&lt;/p&gt;

&lt;p&gt;The Three-Layer Architecture&lt;/p&gt;

&lt;p&gt;AI triage in a property management context isn't a single step. A production-grade system runs in three distinct layers, each serving a different purpose and operating at a different cost.&lt;/p&gt;

&lt;p&gt;Layer 1 — Keyword Classification&lt;/p&gt;

&lt;p&gt;The first pass is a weighted keyword scan against a library of terms mapped to property categories: plumbing, electrical, HVAC, security, pest control, and others. The weighting matters more than the keyword list itself.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;KEYWORD_WEIGHTS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;# Safety-critical — fire immediately
&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gas smell&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gas leak&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;no electricity&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;flood&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;burst pipe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fire&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;# High urgency
&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;no heat&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;boiler broken&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;no hot water&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;security breach&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;# Medium
&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;leak&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mould&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;damp&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;# Low
&lt;/span&gt;    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;squeaky door&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;paint&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bin collection&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;SUBJECT_LINE_MULTIPLIER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;keyword_score&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="n"&gt;subject_lower&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;body_lower&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;max_weight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;matched_category&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;general&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;confidence&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;keyword&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;weight&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;KEYWORD_WEIGHTS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;items&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="c1"&gt;# Subject line counts double
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;keyword&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;subject_lower&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;adjusted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;weight&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;SUBJECT_LINE_MULTIPLIER&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;adjusted&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;max_weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;max_weight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;adjusted&lt;/span&gt;
                &lt;span class="n"&gt;matched_category&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;classify_keyword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;keyword&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;keyword&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;body_lower&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;weight&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;max_weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;max_weight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;weight&lt;/span&gt;
                &lt;span class="n"&gt;matched_category&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;classify_keyword&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;keyword&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Confidence: how certain we are in this classification
&lt;/span&gt;    &lt;span class="n"&gt;confidence&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_weight&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;10.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;max_weight&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;matched_category&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;confidence&lt;/span&gt;


&lt;span class="n"&gt;This&lt;/span&gt; &lt;span class="n"&gt;layer&lt;/span&gt; &lt;span class="n"&gt;handles&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;majority&lt;/span&gt; &lt;span class="n"&gt;of&lt;/span&gt; &lt;span class="n"&gt;cases&lt;/span&gt; &lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="n"&gt;accurately&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;instantly&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;zero&lt;/span&gt; &lt;span class="n"&gt;API&lt;/span&gt; &lt;span class="n"&gt;cost&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="n"&gt;resident&lt;/span&gt; &lt;span class="n"&gt;who&lt;/span&gt; &lt;span class="n"&gt;types&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;URGENT: no heat&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;subject&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;communicating&lt;/span&gt; &lt;span class="n"&gt;something&lt;/span&gt; &lt;span class="n"&gt;different&lt;/span&gt; &lt;span class="n"&gt;than&lt;/span&gt; &lt;span class="n"&gt;one&lt;/span&gt; &lt;span class="n"&gt;who&lt;/span&gt; &lt;span class="n"&gt;mentions&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;paragraph&lt;/span&gt; &lt;span class="n"&gt;four&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;The&lt;/span&gt; &lt;span class="n"&gt;multiplier&lt;/span&gt; &lt;span class="n"&gt;handles&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="n"&gt;Layer&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="n"&gt;Sentiment&lt;/span&gt; &lt;span class="n"&gt;Scoring&lt;/span&gt;

&lt;span class="n"&gt;Keywords&lt;/span&gt; &lt;span class="n"&gt;tell&lt;/span&gt; &lt;span class="n"&gt;you&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;what&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;problem&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;Sentiment&lt;/span&gt; &lt;span class="n"&gt;tells&lt;/span&gt; &lt;span class="n"&gt;you&lt;/span&gt; &lt;span class="n"&gt;how&lt;/span&gt; &lt;span class="n"&gt;bad&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s gotten.

A resident who writes &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;the tap is dripping&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; gets medium priority. A resident who writes &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;I&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="n"&gt;ve&lt;/span&gt; &lt;span class="n"&gt;reported&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt; &lt;span class="n"&gt;dripping&lt;/span&gt; &lt;span class="n"&gt;tap&lt;/span&gt; &lt;span class="n"&gt;three&lt;/span&gt; &lt;span class="n"&gt;times&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;nobody&lt;/span&gt; &lt;span class="n"&gt;has&lt;/span&gt; &lt;span class="n"&gt;responded&lt;/span&gt; &lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="n"&gt;I&lt;/span&gt; &lt;span class="n"&gt;am&lt;/span&gt; &lt;span class="n"&gt;contacting&lt;/span&gt; &lt;span class="n"&gt;my&lt;/span&gt; &lt;span class="n"&gt;solicitor&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; is describing the same physical problem, but the case is now high priority, escalation-flagged, and legal threat patterns have been detected.

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;br&gt;
import re&lt;/p&gt;

&lt;p&gt;SENTIMENT_SIGNALS = {&lt;br&gt;
    "emergency_language": {&lt;br&gt;
        "patterns": [r"\burgent\b", r"\bemergency\b", r"\bASAP\b", r"\bimmediately\b", r"\bdesperate\b"],&lt;br&gt;
        "score_adjustment": +2,&lt;br&gt;
    },&lt;br&gt;
    "escalation_signals": {&lt;br&gt;
        "patterns": [&lt;br&gt;
            r"\bbeen waiting\b", r"\bno.{0,15}responded\b", r"\bcomplained before\b",&lt;br&gt;
            r"\bsolicitor\b", r"\blawyer\b", r"\bcouncil\b", r"\breport.{0,10}again\b",&lt;br&gt;
            r"\bthird time\b", r"\bmultiple times\b",&lt;br&gt;
        ],&lt;br&gt;
        "score_adjustment": +3,&lt;br&gt;
    },&lt;br&gt;
    "vulnerable_population": {&lt;br&gt;
        "patterns": [&lt;br&gt;
            r"\belderly\b", r"\bchild(ren)?\b", r"\bbaby\b", r"\binfant\b",&lt;br&gt;
            r"\bdisabled\b", r"\bwheelchair\b", r"\bpregnant\b",&lt;br&gt;
            r"\basthma\b", r"\bheart condition\b", r"\bmedical\b",&lt;br&gt;
        ],&lt;br&gt;
        "score_adjustment": +2,&lt;br&gt;
        "flag": "VULNERABLE_POPULATION",&lt;br&gt;
    },&lt;br&gt;
    "extended_duration": {&lt;br&gt;
        "patterns": [&lt;br&gt;
            r"\bfor weeks\b", r"\bfor months\b", r"\bsince \w+ \d{4}\b",&lt;br&gt;
            r"\bgetting worse\b", r"\bstill not fixed\b", r"\bongoing\b",&lt;br&gt;
        ],&lt;br&gt;
        "score_adjustment": +2,&lt;br&gt;
        "flag": "EXTENDED_DURATION",&lt;br&gt;
    },&lt;br&gt;
    "emotional_intensity": {&lt;br&gt;
        "patterns": [r"[A-Z]{5,}", r"!!!+", r"\?\?\?+", r"\bfurious\b", r"\boutraged\b"],&lt;br&gt;
        "score_adjustment": +1,&lt;br&gt;
        "flag": "HIGH_EMOTIONAL_INTENSITY",&lt;br&gt;
    },&lt;br&gt;
    "deprioritise": {&lt;br&gt;
        "patterns": [r"\bno rush\b", r"\bwhenever convenient\b", r"\bwhen you get a chance\b"],&lt;br&gt;
        "score_adjustment": -2,&lt;br&gt;
    },&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;def sentiment_adjust(text: str, base_score: float) -&amp;gt; tuple[float, list[str]]:&lt;br&gt;
    flags = []&lt;br&gt;
    adjusted_score = base_score&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for signal_name, config in SENTIMENT_SIGNALS.items():
    for pattern in config["patterns"]:
        if re.search(pattern, text, re.IGNORECASE):
            adjusted_score += config["score_adjustment"]
            if "flag" in config:
                flags.append(config["flag"])
            break  # One match per signal type is enough

return adjusted_score, list(set(flags))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Layer 3 — LLM (Edge Cases Only)

The part nobody demos: routing every case through a language model is the naive implementation. It's expensive at scale, introduces latency, and creates a single point of failure.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;br&gt;
python&lt;br&gt;
import anthropic&lt;/p&gt;

&lt;p&gt;CONFIDENCE_THRESHOLD = 0.6&lt;br&gt;
LLM_BUDGET_LIMIT_DAILY = 50  # Per organisation&lt;/p&gt;

&lt;p&gt;def triage_case(subject: str, body: str, org_id: str) -&amp;gt; dict:&lt;br&gt;
    full_text = f"{subject}\n\n{body}"&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Layer 1: Keyword scan
keyword_weight, category, confidence = keyword_score(subject, body)

# Safety-critical: fire immediately, skip everything else
if keyword_weight &amp;gt;= 9:
    return {
        "priority": "URGENT",
        "category": category,
        "flags": ["SAFETY_CRITICAL"],
        "source": "keyword_immediate",
        "llm_used": False,
    }

# Layer 2: Sentiment adjustment
adjusted_score, flags = sentiment_adjust(full_text, keyword_weight)
priority = score_to_priority(adjusted_score)

# Layer 3: LLM for genuinely ambiguous cases
if confidence &amp;lt; CONFIDENCE_THRESHOLD and not is_budget_exhausted(org_id):
    llm_result = classify_with_llm(subject, body)
    log_llm_usage(org_id)
    return {
        "priority": llm_result["priority"],
        "category": llm_result["category"],
        "flags": flags + llm_result.get("additional_flags", []),
        "source": "llm",
        "llm_used": True,
    }

return {
    "priority": priority,
    "category": category,
    "flags": flags,
    "source": "keyword_sentiment",
    "llm_used": False,
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;def classify_with_llm(subject: str, body: str) -&amp;gt; dict:&lt;br&gt;
    client = anthropic.Anthropic()&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;prompt = f"""Classify this property management case. Return JSON only.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Subject: {subject}&lt;br&gt;
Body: {body}&lt;/p&gt;

&lt;p&gt;Return:&lt;br&gt;
{{&lt;br&gt;
  "priority": "URGENT|HIGH|MEDIUM|LOW",&lt;br&gt;
  "category": "plumbing|electrical|hvac|security|pest|noise|administrative|other",&lt;br&gt;
  "reasoning": "one sentence",&lt;br&gt;
  "additional_flags": []&lt;br&gt;
}}"""&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;message = client.messages.create(
    model="claude-opus-4-5",
    max_tokens=256,
    messages=[{"role": "user", "content": prompt}]
)

import json
return json.loads(message.content[0].text)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;def score_to_priority(score: float) -&amp;gt; str:&lt;br&gt;
    if score &amp;gt;= 8: return "URGENT"&lt;br&gt;
    if score &amp;gt;= 5: return "HIGH"&lt;br&gt;
    if score &amp;gt;= 3: return "MEDIUM"&lt;br&gt;
    return "LOW"&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Critically: urgent cases skip the LLM entirely. If "gas smell" fires at weight 10, there is no reason to wait for a model to confirm it. The flag fires immediately.

The Flags That Change How Cases Are Handled

Beyond the four standard priority levels, a well-implemented triage system surfaces named flags that give case managers actionable context before they open a case.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;br&gt;
FLAG_DEFINITIONS = {&lt;br&gt;
    "VULNERABLE_POPULATION": "Children, elderly, disabled, pregnant, or health condition mentioned",&lt;br&gt;
    "ESCALATED_COMPLAINT":   "Frustration expressed, repeat complaint, or legal threat indicated",&lt;br&gt;
    "EXTENDED_DURATION":     "Issue ongoing for days, weeks, or months",&lt;br&gt;
    "HIGH_EMOTIONAL_INTENSITY": "Writing style indicates significant distress",&lt;br&gt;
    "SAFETY_CRITICAL":       "Immediate safety risk — gas, fire, flood, security",&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;None of these flags override agent judgement. The case manager retains full control to reclassify category and priority once they open a case. The flags are there to make sure context — which might be buried in paragraph five of a long email — is visible at a glance before any decision is made.&lt;/p&gt;

&lt;p&gt;This is, if we're honest, where a lot of internal-build attempts fall down. Teams build classification but skip the flagging layer, and then wonder why the system doesn't feel meaningfully different from what they had before.&lt;/p&gt;

&lt;p&gt;Where Human Judgement Still Wins — and Should&lt;/p&gt;

&lt;p&gt;We don't think the goal here is to reduce human involvement in case management. We think that's the wrong framing entirely. The goal is to get the right information to the right person at the right moment, so that their judgement is applied where it actually matters.&lt;/p&gt;

&lt;p&gt;Consider a case where a resident reports a neighbour playing loud music that's been ongoing for months, and mentions that an elderly family member can't sleep. A triage system will correctly detect &lt;code&gt;VULNERABLE_POPULATION&lt;/code&gt; and &lt;code&gt;EXTENDED_DURATION&lt;/code&gt;. It might correctly classify this as a noise complaint. But whether this requires an administrative response, a welfare check, or something more urgent is a call that sits with a human — someone who knows the property, knows the tenant history, and can weigh factors the AI simply doesn't have access to.&lt;/p&gt;

&lt;p&gt;A compliance lead at a large residential operator put this to us in a way that stuck: "The AI gives me the same information I'd have if I'd read every email carefully. It doesn't tell me what to do with it." That's the right relationship between the technology and the professional.&lt;/p&gt;

&lt;p&gt;The Cost and Reliability Architecture That Actually Scales&lt;/p&gt;

&lt;p&gt;For teams building or evaluating AI triage systems, the economics matter as much as the capability.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;functools&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;hashlib&lt;/span&gt;

&lt;span class="c1"&gt;# Response cache — identical cases don't re-trigger LLM
&lt;/span&gt;&lt;span class="n"&gt;_cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;cached_llm_classify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;cache_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hashlib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;md5&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;hexdigest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cache_key&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;_cache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;_cache&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;cache_key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;classify_with_llm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;_cache&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;cache_key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;

&lt;span class="c1"&gt;# Circuit breaker — graceful degradation when AI service is unavailable
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CircuitBreaker&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;failure_threshold&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;recovery_timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;failures&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;threshold&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;failure_threshold&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;open&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;recovery_timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;recovery_timeout&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fallback&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fallback&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;failures&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;failures&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;failures&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;threshold&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;open&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fallback&lt;/span&gt;

&lt;span class="n"&gt;circuit_breaker&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CircuitBreaker&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Usage: falls back to medium priority if LLM is unavailable
&lt;/span&gt;&lt;span class="n"&gt;llm_result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;circuit_breaker&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;classify_with_llm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;fallback&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;priority&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;MEDIUM&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;category&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;general&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;additional_flags&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A well-designed implementation keeps LLM usage minimal by design. The keyword and sentiment layers handle the majority of cases locally, with no API calls. Budget limits per organisation prevent runaway spend. The response cache means similar cases don't re-trigger an LLM call. The circuit breaker ensures that if the AI service is unavailable, cases default to medium priority rather than failing entirely.&lt;/p&gt;

&lt;p&gt;We're not entirely sure how to benchmark this precisely across different portfolio sizes, because the case composition varies considerably. But the directional outcome is consistent: teams that deploy this architecture report that LLM calls represent a small minority of total triage operations, while the accuracy improvement over pure keyword classification is significant.&lt;/p&gt;

&lt;p&gt;Key Takeaways&lt;/p&gt;

&lt;p&gt;The three-layer architecture — keywords, then sentiment, then LLM for genuinely ambiguous cases — is the approach that balances accuracy, cost, and reliability at scale. Trying to shortcut to a single-layer LLM solution gets expensive and brittle.&lt;/p&gt;

&lt;p&gt;Urgency escalation should skip the LLM entirely. Safety-critical categories need to fire immediately, not wait for model confirmation.&lt;/p&gt;

&lt;p&gt;Named flags are as important as priority levels. Knowing a case is "high priority" is less actionable than knowing it's &lt;code&gt;high priority + VULNERABLE_POPULATION + ESCALATED_COMPLAINT&lt;/code&gt;. The flags are where the system earns its daily usefulness.&lt;/p&gt;

&lt;p&gt;Human override should be built in by design, not bolted on as an afterthought. Case managers need to be able to reclassify immediately, without friction. The AI is a starting point.&lt;/p&gt;

&lt;p&gt;Budget controls and degradation patterns are non-negotiable for production deployment. A system that fails open — passing all costs and all decisions to the AI layer — will create problems that outweigh the operational benefits.&lt;/p&gt;

&lt;p&gt;How Context First AI Approaches This&lt;/p&gt;

&lt;p&gt;At Context First AI, the triage capability described in this article sits within the broader HandyConnect V2.0 platform — built specifically for property management operations that need to handle resident cases at scale without proportionally scaling their operations team.&lt;/p&gt;

&lt;p&gt;The system is designed around the principle that the best AI implementations make existing professionals more effective, not more dependent on automation. Case managers using HandyConnect don't experience the AI as a black box that produces decisions — they experience it as a first pass that surfaces what matters, so their attention goes where it belongs.&lt;/p&gt;

&lt;p&gt;The Stack pillar at Context First AI focuses on technical product decisions: the architecture choices, the compliance implications, and the build-versus-buy questions that teams actually face when deploying AI in operational contexts. The triage system is one component of a larger infrastructure that includes automated email ingestion, SLA tracking, and role-based access management across blocks and properties.&lt;/p&gt;

&lt;p&gt;For B2B teams evaluating AI tooling for case management, the relevant questions are around reliability under load, cost control at scale, and the degree to which the system supports — rather than constrains — the professionals using it. HandyConnect is built to answer those questions in production, not just in a demo.&lt;/p&gt;

&lt;p&gt;Conclusion&lt;/p&gt;

&lt;p&gt;The inbox queue was never the right mental model for managing resident cases. A prioritised worklist — where the system has already surfaced the gas leak, flagged the frustrated long-term complainer, and elevated the vulnerable resident — is a fundamentally different working environment. The technology to build it exists and is mature enough for production deployment. The teams that will get the most out of it are the ones who treat it as an infrastructure decision, not a feature addition.&lt;/p&gt;

&lt;p&gt;The question isn't whether AI triage is possible. It's whether the architecture is built to last beyond the first month.&lt;/p&gt;

&lt;p&gt;Resources&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.contextfirst.ai/stack/handyconnect" rel="noopener noreferrer"&gt;[HandyConnect V2.0 — AI Case Management for Property Operations]&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.contextfirst.ai/stack" rel="noopener noreferrer"&gt;[Context First AI — Stack Pillar Content]&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;-&lt;a href="https://www.contextfirst.ai/stack/ai-reliability-patterns" rel="noopener noreferrer"&gt; [Building Production-Grade AI Systems: Cost Control and Reliability Patterns]&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Created with AI assistance. Originally published at &lt;a href="https://www.contextfirst.ai" rel="noopener noreferrer"&gt;[Context First AI]&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Why What You Feed an AI Matters More Than Which AI You Choose.</title>
      <dc:creator>Context First AI</dc:creator>
      <pubDate>Thu, 19 Mar 2026 10:17:16 +0000</pubDate>
      <link>https://dev.to/contextfirstai/why-what-you-feed-an-ai-matters-more-than-which-ai-you-choose-i23</link>
      <guid>https://dev.to/contextfirstai/why-what-you-feed-an-ai-matters-more-than-which-ai-you-choose-i23</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiwb85kl7h66v3xecio36.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiwb85kl7h66v3xecio36.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The model isn't your problem. The brief is. Language models generate based on what they're given — role, audience, background, constraints, and format. Practitioners who learn to construct context rather than just write prompts consistently outperform those chasing better tools. This post breaks down why, and includes working code examples you can use today.&lt;/p&gt;

&lt;p&gt;We've spent a lot of time watching people blame their AI tools. The model is too slow, too generic, too confident, too hedging — pick your complaint. What we've noticed, almost without exception, is that the problem isn't the model. It's what went in before the model was asked to do anything.&lt;/p&gt;

&lt;p&gt;Think of it like a compiler error. The machine isn't wrong. It did exactly what you told it. The question is whether what you told it was actually what you meant.&lt;/p&gt;

&lt;p&gt;A Pattern We Keep Seeing&lt;/p&gt;

&lt;p&gt;Across the learning cohorts and practitioner communities we work with, a familiar story repeats itself. A mid-level analyst at a financial services firm spends three weeks evaluating AI tools — comparing interfaces, pricing tiers, context windows — and then switches to a different model after deciding their outputs aren't good enough. The outputs improve marginally. Then they switch again. The cycle continues.&lt;/p&gt;

&lt;p&gt;Meanwhile, a curriculum designer at a mid-size L&amp;amp;D consultancy sits down with the same general-purpose model, writes a careful prompt that includes their audience profile, the learning objective, the existing knowledge state of their learners, and two paragraphs of relevant background — and gets an output they describe, without exaggeration, as "better than anything my team produced in a week." Same model. Wildly different result.&lt;/p&gt;

&lt;p&gt;We've seen this play out across sectors: a procurement lead in logistics, a compliance officer at a professional services firm, a product manager at a 40-person SaaS company. In almost every case, the performance gap between "AI that works" and "AI that disappoints" traces back not to the model choice but to the quality and completeness of the context provided. That's the pattern. And once you see it, you can't unsee it.&lt;/p&gt;

&lt;p&gt;The Problem: We Were Taught to Ask, Not to Brief&lt;/p&gt;

&lt;p&gt;Most people's first interaction with a generative AI looks like a search engine query. Type a question. Get an answer. Evaluate, repeat. That mental model is deeply embedded because it mirrors twenty years of conditioning from Google — and it's the single biggest reason AI outputs feel shallow.&lt;/p&gt;

&lt;p&gt;Language models don't retrieve information the way a search engine does. They generate responses based on probability distributions shaped by everything in their context window. That context window is everything: your system prompt, your user message, any documents you've included, the conversation history. The model has no memory of you outside that window (setting aside explicit memory features). It doesn't know your industry, your audience, your constraints, or your goals unless you tell it.&lt;/p&gt;

&lt;p&gt;What this means practically is that asking &lt;code&gt;"write me a training module on data governance"&lt;/code&gt; and asking &lt;code&gt;"write a 45-minute training module on data governance for mid-career IT administrators in a regulated industry who have strong technical fluency but limited exposure to compliance frameworks — the tone should be direct and the format should be scenario-led"&lt;/code&gt; are not the same prompt with different levels of specificity. They are fundamentally different inputs. One is a keyword; the other is a brief.&lt;/p&gt;

&lt;p&gt;Same principle as the difference between &lt;code&gt;SELECT * FROM users&lt;/code&gt; and a query with proper WHERE clauses, JOINs, and a defined schema. Both are valid SQL. Only one gives the database engine something useful to optimise against.&lt;/p&gt;

&lt;p&gt;The Solution: Context as a First-Class Skill&lt;/p&gt;

&lt;p&gt;The shift we're advocating for — and the one underpinning a significant portion of how we structure AI literacy programmes — is treating context construction as a discrete, learnable skill. Not a prompt engineering trick. Not a workaround. A core professional competency.&lt;/p&gt;

&lt;p&gt;This reframe matters because it changes the learning trajectory. When learners understand that context is the primary lever, they stop chasing the "perfect model" and start developing the ability to brief AI systems with the same rigour they'd bring to briefing a talented but uninformed contractor. The model is capable. It needs information. Your job is to provide it.&lt;/p&gt;

&lt;p&gt;We think the framing of "prompt engineering" as a highly technical discipline has done more harm than good here. It implies specialist knowledge when what's actually required is the kind of structured thinking that most professionals already do in other contexts — writing a project brief, onboarding a new team member, explaining a problem to an external consultant. Context-building for AI draws on those same skills, extended into a new domain.&lt;/p&gt;

&lt;p&gt;How It Works: The Anatomy of Useful Context&lt;/p&gt;

&lt;p&gt;Context for a language model can be broken down into four components. Understanding each one separately is more useful than thinking about "prompts" as a single undifferentiated thing.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Role and Purpose&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Tells the model what it's doing and for whom. Not just "you are a helpful assistant" but something like:&lt;/p&gt;

&lt;p&gt;You are supporting a senior HR business partner who needs to draft a change &lt;br&gt;
management communication for a restructure announcement. The audience is &lt;br&gt;
middle management. The tone should be direct but empathetic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="mf"&gt;2.&lt;/span&gt; &lt;span class="n"&gt;Audience&lt;/span&gt; &lt;span class="n"&gt;Specification&lt;/span&gt;

&lt;span class="n"&gt;Shapes&lt;/span&gt; &lt;span class="n"&gt;vocabulary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;assumed&lt;/span&gt; &lt;span class="n"&gt;knowledge&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tone&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;depth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;writing&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;technical&lt;/span&gt; &lt;span class="n"&gt;lead&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;writing&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;joiner&lt;/span&gt; &lt;span class="n"&gt;should&lt;/span&gt; &lt;span class="n"&gt;produce&lt;/span&gt; &lt;span class="n"&gt;different&lt;/span&gt; &lt;span class="n"&gt;outputs&lt;/span&gt; &lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="n"&gt;but&lt;/span&gt; &lt;span class="n"&gt;only&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;you&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;ve told it which is which.

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;br&gt;
context = {&lt;br&gt;
    "audience": {&lt;br&gt;
        "role": "mid-career IT administrator",&lt;br&gt;
        "technical_level": "high",&lt;br&gt;
        "domain_familiarity": "low",&lt;br&gt;
        "expected_action": "implement policy within 30 days"&lt;br&gt;
    }&lt;br&gt;
}&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;3. Background and Constraints

Often the most underused element. A few sentences of relevant background — what's already been tried, what the existing structure looks like, what's off-limits — can prevent the model from producing plausible-but-useless output.

This is basically the difference between asking a freelance developer to "build an auth system" versus handing them your existing schema, your stack constraints, your security requirements, and three examples of flows you liked. Same capability. Completely different starting point.

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;br&gt;
system_prompt = """&lt;br&gt;
You are a technical documentation writer.&lt;/p&gt;

&lt;p&gt;CONTEXT:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This documentation is for a REST API used by external developers&lt;/li&gt;
&lt;li&gt;Existing docs use OpenAPI 3.0 format&lt;/li&gt;
&lt;li&gt;The audience has intermediate Python or JavaScript experience&lt;/li&gt;
&lt;li&gt;Do not reference internal service names or legacy endpoints&lt;/li&gt;
&lt;li&gt;Tone: clear, direct, no marketing language&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;OUTPUT FORMAT:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Structured as: Overview &amp;gt; Parameters &amp;gt; Request Example &amp;gt; Response Example &amp;gt; Error Codes&lt;/li&gt;
&lt;li&gt;Code examples in both Python (requests library) and JavaScript (fetch)
"""&lt;/li&gt;
&lt;li&gt;Output Format and Scope&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;"A structured outline" and "a ready-to-send email" require different things from the model. Assuming it'll figure out which you want is optimistic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;contextPayload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;You are a curriculum designer for technical upskilling programmes.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;audience&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Mid-career software engineers moving into ML engineering roles.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Learners have strong Python fluency but no prior ML experience.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;constraints&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Each module must be completable in under 45 minutes.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;outputFormat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;structure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;module outline&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;sections&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;learning objective&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;prerequisite check&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;core content&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hands-on exercise&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;assessment&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;lengthPerSection&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;100-150 words&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;tone&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;practitioner-credible, not academic&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When these elements are combined, the model isn't guessing at what good looks like. It knows. And that's when the outputs start to feel, as practitioners often describe it, genuinely collaborative rather than generically useful.&lt;/p&gt;

&lt;p&gt;A Reusable Context Template&lt;/p&gt;

&lt;p&gt;If you've ever built a function that takes well-typed parameters instead of a loose &lt;code&gt;options&lt;/code&gt; object, you already understand why structure here matters. Here's a reusable context template you can adapt across use cases:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;build_context&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;audience&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;background&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;constraints&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output_format&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
ROLE:
&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;

AUDIENCE:
&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;audience&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;

BACKGROUND AND CONSTRAINTS:
&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;background&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;
&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;constraints&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;

OUTPUT FORMAT:
&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;output_format&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Example usage
&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;build_context&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You are a compliance documentation specialist.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;audience&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Operations managers at regulated financial services firms with no legal background.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;background&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The firm recently adopted a new data retention policy under UK GDPR.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;constraints&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Avoid legal jargon. Do not reference specific case law. Keep under 500 words.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;output_format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Plain-English summary followed by a 5-point action checklist.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This isn't sophisticated. That's the point. The discipline is in filling it out completely, not in the structure itself.&lt;/p&gt;

&lt;p&gt;Real-World Impact&lt;/p&gt;

&lt;p&gt;The measurable shift that comes from context-first AI use tends to show up in two places: output quality and iteration time.&lt;/p&gt;

&lt;p&gt;On output quality, practitioners who are trained to brief AI rather than query it typically report a significant reduction in the number of revision cycles. An instructional designer at a large professional training organisation described reducing their average draft-to-approval cycle from six internal reviews to two — not by using a better model, but by front-loading context into every AI interaction. A technical writer supporting a software team started including the target user persona, the documentation style guide, and three example entries at the start of every session, and described the outputs as "almost immediately usable" compared to the generic technical prose the same model had been producing before.&lt;/p&gt;

&lt;p&gt;On iteration time, the pattern is consistent: more time spent building context upfront means significantly less time spent correcting and reshaping output downstream. We'd estimate — and we're deliberately being rough here, because clean data on this is hard to come by — that for every additional 37% of effort spent on context construction, iteration time drops by something close to half. That's not a precise figure. It's directionally true.&lt;/p&gt;

&lt;p&gt;There's also a subtler benefit that's harder to quantify. When practitioners develop the habit of articulating context clearly, they often report that the process clarifies their own thinking. Writing a thorough brief for an AI system requires you to know what you want, who it's for, and what constraints apply. That act of articulation is valuable independent of the AI output it produces.&lt;/p&gt;

&lt;p&gt;Key Takeaways&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Context is not supplementary to prompting — it is the prompt. Treat it as the primary input, not an optional addition.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;-Think in briefs, not queries. The mental model of "instructing a capable contractor" produces better results than the mental model of "searching for an answer."&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Role, audience, background, and output format are the four components of effective context. Covering all four, even briefly, is significantly more effective than covering one well.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;More context upfront reduces iteration downstream. The time investment pays back faster than most practitioners expect.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Context-building is a transferable professional skill, not a technical speciality. Professionals who are already good at briefing, communicating requirements, or onboarding others have a head start.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;How Context First AI Approaches This&lt;/p&gt;

&lt;p&gt;The name isn't accidental. Context First AI was built around a single conviction: that the quality of what goes in determines the quality of what comes out, and that most AI education skips straight to the output without teaching learners how to construct the input.&lt;/p&gt;

&lt;p&gt;Across the Vectors learning programmes, context construction is treated as a foundational skill that appears before model selection, before tooling decisions, and before any discussion of advanced techniques like retrieval-augmented generation or agent orchestration. We've found that learners who develop strong context habits early adapt more readily to new models and tools as they emerge — because the underlying skill transfers regardless of the interface.&lt;/p&gt;

&lt;p&gt;The Vectors curriculum integrates context-building into practical exercises from the start: learners practice briefing AI systems using real professional scenarios drawn from their own work contexts, iterating on the quality of their inputs rather than the sophistication of their prompts. The distinction sounds minor. In practice, it changes the entire learning arc.&lt;/p&gt;

&lt;p&gt;The Mesh community platform reflects this same philosophy at the peer level, with practitioners sharing context frameworks, critique sessions focused on input quality, and ongoing discussion of what works across different professional domains. The context-first approach isn't a module in the programme. It's the thread running through all of them.&lt;/p&gt;

&lt;p&gt;If you're building AI fluency from the ground up, or supporting others who are, the most useful question to ask isn't "which model should I use?" It's "how thoroughly can I describe what I need?" Everything else follows from that.&lt;/p&gt;

&lt;p&gt;Conclusion&lt;/p&gt;

&lt;p&gt;We started noticing the context gap because learners kept telling us their AI tools weren't working. When we looked closely at what they were actually doing, the tools were working exactly as designed — they were just being given almost nothing to work with. That's the honest version of how this became a central part of what we teach.&lt;/p&gt;

&lt;p&gt;The shift from querying to briefing is not complicated. But it requires unlearning the search-engine instinct, and that takes deliberate practice. The good news is that the underlying skill — knowing what you want, who it's for, and what constraints apply — is one most professionals already have in other domains. The work is in applying it here.&lt;/p&gt;

&lt;p&gt;Same principle as the compiler analogy at the top: the machine did exactly what you told it. The question is always whether what you told it was actually what you meant.&lt;/p&gt;

&lt;p&gt;Start with your next AI interaction. Before you type the request, spend sixty seconds writing down your audience, your constraints, and what "good" looks like. See what changes.&lt;/p&gt;

&lt;p&gt;Resources&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.anthropic.com/en/docs/build-with-claude/prompt-engineering/overview" rel="noopener noreferrer"&gt;[Anthropic Prompt Engineering Guide]&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.deeplearning.ai/short-courses/" rel="noopener noreferrer"&gt;[DeepLearning.AI Short Courses on Prompting and LLMs]&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;-&lt;a href="https://contextfirst.ai/vectors" rel="noopener noreferrer"&gt; [Context First AI — Vectors Learning Programme]&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Created with AI assistance. Originally published at [&lt;a href="https://contextfirst.ai" rel="noopener noreferrer"&gt;Context First AI&lt;/a&gt;]&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Choosing an AI vendor as an SMB is like hiring a head chef.</title>
      <dc:creator>Context First AI</dc:creator>
      <pubDate>Thu, 19 Mar 2026 10:13:22 +0000</pubDate>
      <link>https://dev.to/contextfirstai/choosing-an-ai-vendor-as-an-smb-is-like-hiring-a-head-chef-32n5</link>
      <guid>https://dev.to/contextfirstai/choosing-an-ai-vendor-as-an-smb-is-like-hiring-a-head-chef-32n5</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Funthz9ogkabl59lnmf9u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Funthz9ogkabl59lnmf9u.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;br&gt;
Choosing an AI vendor as an SMB is like hiring a head chef: the demo is the tasting menu, but operations determine long-term success. Define measurable outcomes, audit your data, structure pilots, and treat governance as seriously as model accuracy. AI vendor selection isn’t just a tech decision — it’s an organisational systems decision.&lt;/p&gt;

&lt;p&gt;Navigating AI Vendor Selection as a Small Business&lt;/p&gt;

&lt;p&gt;Choosing an AI vendor as a small business is a lot like selecting a new head chef for your restaurant. On paper, everyone promises Michelin-level results. In reality, the wrong hire can disrupt the entire kitchen.&lt;/p&gt;

&lt;p&gt;Think of it like this: the chef doesn’t just cook. They design the menu, influence the suppliers you work with, shape the culture of the team, and determine whether service runs smoothly on a Friday night. The same principle applies to AI vendors. You’re not just buying software. You’re choosing a long-term partner who will shape how decisions get made, how data flows, and how your organisation evolves.&lt;/p&gt;

&lt;p&gt;For developers and technical leaders inside SMBs, that decision carries even more weight. You’re often the one translating demo promises into production reality.&lt;/p&gt;

&lt;p&gt;The Pattern We Keep Seeing&lt;/p&gt;

&lt;p&gt;Across our community, we see a consistent sequence.&lt;/p&gt;

&lt;p&gt;A managing director at a 55-person engineering firm experiments with predictive maintenance tools. An operations lead at a 32-employee marketing agency tests generative AI to speed up campaign production. A COO at a logistics provider explores route optimisation platforms after fuel costs spike 18% year over year.&lt;/p&gt;

&lt;p&gt;The trigger isn’t curiosity. It’s pressure.&lt;/p&gt;

&lt;p&gt;Margins tightening.&lt;br&gt;
Clients asking harder questions.&lt;br&gt;
Teams stretched thin.&lt;/p&gt;

&lt;p&gt;Then come the demos. Conflicting claims about accuracy and ROI. Acronyms layered on top of other acronyms.&lt;/p&gt;

&lt;p&gt;Roughly 37% of SMB leaders we speak with admit their first AI vendor choice was influenced mainly by how compelling the demo felt.&lt;/p&gt;

&lt;p&gt;A compelling demo is like a tasting menu. It shows what’s possible. It doesn’t show how the kitchen performs every night.&lt;/p&gt;

&lt;p&gt;The Real Problem: Abundance + Hidden Complexity&lt;/p&gt;

&lt;p&gt;The challenge isn’t a lack of AI vendors. It’s abundance.&lt;/p&gt;

&lt;p&gt;Horizontal AI platforms&lt;/p&gt;

&lt;p&gt;Vertical industry tools&lt;/p&gt;

&lt;p&gt;Niche startups&lt;/p&gt;

&lt;p&gt;Enterprise providers adding “AI-enabled” to product pages&lt;/p&gt;

&lt;p&gt;For developers, the complexity hides in four places:&lt;/p&gt;

&lt;p&gt;Knowledge asymmetry – Vendors know their stack intimately. You’re reverse-engineering it in a 45-minute demo.&lt;/p&gt;

&lt;p&gt;Integration reality – AI systems depend on data pipelines, schemas, APIs, and permissions.&lt;/p&gt;

&lt;p&gt;Data quality – If your CRM is inconsistent, AI amplifies the mess.&lt;/p&gt;

&lt;p&gt;Long-term dependency risk – Switching AI vendors later can mean data migration, retraining, and re-architecting workflows.&lt;/p&gt;

&lt;p&gt;We’re not entirely sure there’s a perfect formula for eliminating risk. But we do know this: rushing because “everyone is doing AI” is the wrong move.&lt;/p&gt;

&lt;p&gt;We think the idea that AI is purely a technology purchase is wrong. It’s an organisational decision disguised as software procurement.&lt;/p&gt;

&lt;p&gt;The Three Anchors for Smarter AI Vendor Selection&lt;/p&gt;

&lt;p&gt;Think of vendor selection like hiring that chef again. You wouldn’t choose solely on their signature dish. You’d evaluate philosophy, team fit, sourcing strategy, cost discipline, and long-term vision.&lt;/p&gt;

&lt;p&gt;Same principle here.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Clarity of Outcome&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Before talking to vendors, define the problem in plain language:&lt;/p&gt;

&lt;p&gt;“Reduce manual invoice processing time by 22%.”&lt;/p&gt;

&lt;p&gt;“Improve stock forecast accuracy by 15%.”&lt;/p&gt;

&lt;p&gt;From a technical perspective, this becomes measurable:&lt;/p&gt;

&lt;h1&gt;
  
  
  Example: Baseline measurement for invoice processing time
&lt;/h1&gt;

&lt;p&gt;import pandas as pd&lt;/p&gt;

&lt;p&gt;data = pd.read_csv("invoice_processing_logs.csv")&lt;/p&gt;

&lt;p&gt;average_time = data["processing_time_minutes"].mean()&lt;br&gt;
error_rate = data["errors"].sum() / len(data)&lt;/p&gt;

&lt;p&gt;print(f"Baseline Avg Time: {average_time:.2f} minutes")&lt;br&gt;
print(f"Baseline Error Rate: {error_rate:.2%}")&lt;/p&gt;

&lt;p&gt;Without a baseline, you can’t evaluate improvement.&lt;/p&gt;

&lt;p&gt;Demos are theatre. Metrics are substance.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Operational Compatibility&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is basically system fit.&lt;/p&gt;

&lt;p&gt;If you’ve ever integrated a new API and discovered it doesn’t quite match your data schema, you know the feeling.&lt;/p&gt;

&lt;p&gt;Before committing, test integration at a shallow level:&lt;/p&gt;

&lt;p&gt;// Example: Testing API compatibility with existing CRM data&lt;br&gt;
fetch("&lt;a href="https://api.vendor-ai.com/v1/predict" rel="noopener noreferrer"&gt;https://api.vendor-ai.com/v1/predict&lt;/a&gt;", {&lt;br&gt;
  method: "POST",&lt;br&gt;
  headers: {&lt;br&gt;
    "Authorization": "Bearer YOUR_API_KEY",&lt;br&gt;
    "Content-Type": "application/json"&lt;br&gt;
  },&lt;br&gt;
  body: JSON.stringify({&lt;br&gt;
    customer_id: "12345",&lt;br&gt;
    historical_data: existingCRMRecord&lt;br&gt;
  })&lt;br&gt;
})&lt;br&gt;
.then(res =&amp;gt; res.json())&lt;br&gt;
.then(data =&amp;gt; console.log(data))&lt;br&gt;
.catch(err =&amp;gt; console.error("Integration error:", err));&lt;/p&gt;

&lt;p&gt;You’re not testing model brilliance here. You’re testing fit.&lt;/p&gt;

&lt;p&gt;Does the payload structure align?&lt;br&gt;
How much transformation is required?&lt;br&gt;
Is latency acceptable?&lt;/p&gt;

&lt;p&gt;Same principle as checking whether a new appliance fits existing plumbing.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Governance Control&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;AI systems embed deeply into workflows. Exit later can be painful.&lt;/p&gt;

&lt;p&gt;Before signing, consider:&lt;/p&gt;

&lt;p&gt;Can you export your data easily?&lt;/p&gt;

&lt;p&gt;Are models auditable?&lt;/p&gt;

&lt;p&gt;Is there pricing escalation baked into the contract?&lt;/p&gt;

&lt;p&gt;Is there model transparency documentation?&lt;/p&gt;

&lt;p&gt;From a technical standpoint, insist on export pathways:&lt;/p&gt;

&lt;h1&gt;
  
  
  Example: Data export test (conceptual)
&lt;/h1&gt;

&lt;p&gt;curl -X GET &lt;a href="https://api.vendor-ai.com/v1/export" rel="noopener noreferrer"&gt;https://api.vendor-ai.com/v1/export&lt;/a&gt; \&lt;br&gt;
  -H "Authorization: Bearer YOUR_API_KEY" \&lt;br&gt;
  -o exported_data.json&lt;/p&gt;

&lt;p&gt;If data extraction feels restricted during evaluation, imagine how it will feel after 18 months of dependency.&lt;/p&gt;

&lt;p&gt;Implementation: How It Works in Practice&lt;br&gt;
Stage 1: Internal Mapping&lt;/p&gt;

&lt;p&gt;A finance director at a 40-person professional services firm mapped all recurring processes consuming 5+ hours weekly.&lt;/p&gt;

&lt;p&gt;Invoice reconciliation.&lt;br&gt;
Manual data entry.&lt;br&gt;
Reporting consolidation.&lt;/p&gt;

&lt;p&gt;From a developer perspective, this is basically process discovery:&lt;/p&gt;

&lt;h1&gt;
  
  
  Rough categorisation of time-heavy tasks
&lt;/h1&gt;

&lt;p&gt;tasks = {&lt;br&gt;
    "invoice_reconciliation": 12,&lt;br&gt;
    "manual_data_entry": 9,&lt;br&gt;
    "report_generation": 7&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;high_impact_tasks = {k: v for k, v in tasks.items() if v &amp;gt; 5}&lt;br&gt;
print(high_impact_tasks)&lt;/p&gt;

&lt;p&gt;Find friction. Quantify it.&lt;/p&gt;

&lt;p&gt;Stage 2: Data Readiness&lt;/p&gt;

&lt;p&gt;An operations manager at an e-commerce retailer discovered 28% of product data fields were incomplete.&lt;/p&gt;

&lt;p&gt;AI won’t fix that. It will amplify it.&lt;/p&gt;

&lt;p&gt;Quick audit example:&lt;/p&gt;

&lt;h1&gt;
  
  
  Checking for missing data percentages
&lt;/h1&gt;

&lt;p&gt;missing_percentage = data.isnull().mean() * 100&lt;br&gt;
print(missing_percentage.sort_values(ascending=False))&lt;/p&gt;

&lt;p&gt;If core fields exceed acceptable thresholds, solve that first.&lt;/p&gt;

&lt;p&gt;Engine before chassis alignment? Bad idea.&lt;/p&gt;

&lt;p&gt;Stage 3: Structured Pilot&lt;/p&gt;

&lt;p&gt;Limit comparisons to three vendors. Define evaluation criteria upfront.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;p&gt;Time saved per workflow&lt;/p&gt;

&lt;p&gt;Error reduction&lt;/p&gt;

&lt;p&gt;User adoption rate&lt;/p&gt;

&lt;p&gt;Then measure delta:&lt;/p&gt;

&lt;p&gt;baseline_time = 12.4&lt;br&gt;
post_ai_time = 8.1&lt;/p&gt;

&lt;p&gt;improvement = (baseline_time - post_ai_time) / baseline_time&lt;br&gt;
print(f"Improvement: {improvement:.2%}")&lt;/p&gt;

&lt;p&gt;Stick to the core objective. Avoid feature drift.&lt;/p&gt;

&lt;p&gt;Real-World Impact&lt;/p&gt;

&lt;p&gt;When structured discipline is applied, results are tangible.&lt;/p&gt;

&lt;p&gt;A COO at a distribution company implemented an AI forecasting tool after a structured pilot showed a 19% improvement in demand prediction accuracy. Over six months, excess inventory dropped by 11%.&lt;/p&gt;

&lt;p&gt;An operations lead at a digital agency verified API compatibility before selecting a content-generation platform. Revision cycles dropped by 14%.&lt;/p&gt;

&lt;p&gt;In contrast, a managing partner at a consulting firm rushed into a conversational AI contract after a dazzling demo. Integration delays lasted four months. Adoption stalled. Scope was reduced.&lt;/p&gt;

&lt;p&gt;What differentiates outcomes isn’t vendor size or budget.&lt;/p&gt;

&lt;p&gt;It’s process discipline.&lt;/p&gt;

&lt;p&gt;Key Takeaways for Developers and Technical Leaders&lt;/p&gt;

&lt;p&gt;Define measurable outcomes before vendor conversations.&lt;/p&gt;

&lt;p&gt;Audit your data early — AI amplifies what exists.&lt;/p&gt;

&lt;p&gt;Limit vendor comparisons and structure pilots.&lt;/p&gt;

&lt;p&gt;Review contracts with the same rigor as model architecture.&lt;/p&gt;

&lt;p&gt;Treat adoption as cultural, not just technical.&lt;/p&gt;

&lt;p&gt;Context First AI&lt;/p&gt;

&lt;p&gt;At Context First AI, we approach vendor selection through a contextual lens.&lt;/p&gt;

&lt;p&gt;Think of it like buying a high-performance engine and making sure it fits the chassis you already have. Our focus is readiness first: operational mapping, data audits, governance clarity.&lt;/p&gt;

&lt;p&gt;We guide SMB leaders through structured assessments before vendor engagement begins. That means when vendor conversations happen, they’re anchored in measurable outcomes — not demo enthusiasm.&lt;/p&gt;

&lt;p&gt;We emphasise modular adoption. Phased implementation. Clear milestones.&lt;/p&gt;

&lt;p&gt;If you’ve ever renovated a kitchen, you know appliances come last. Plumbing and wiring come first.&lt;/p&gt;

&lt;p&gt;Same principle.&lt;/p&gt;

&lt;p&gt;Conclusion&lt;/p&gt;

&lt;p&gt;Selecting an AI vendor isn’t about choosing the flashiest chef. It’s about building a kitchen that performs under pressure.&lt;/p&gt;

&lt;p&gt;For developers inside SMBs, that means thinking beyond the model. Think about pipelines. Think about governance. Think about exit strategies.&lt;/p&gt;

&lt;p&gt;Sustainable performance — in kitchens or codebases — depends on systems, not spectacle.&lt;/p&gt;

&lt;p&gt;Resources&lt;/p&gt;

&lt;p&gt;Gartner – AI adoption frameworks and vendor evaluation models&lt;/p&gt;

&lt;p&gt;McKinsey &amp;amp; Company – AI implementation economics&lt;/p&gt;

&lt;p&gt;Harvard Business Review – Technology governance and change management&lt;/p&gt;

&lt;p&gt;This article was created with AI assistance and reviewed by a human author. For more AI-assisted content, visit Context First AI.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>management</category>
      <category>startup</category>
    </item>
    <item>
      <title>The Compliance Audit Your Property Management Software Isn't Ready For.</title>
      <dc:creator>Context First AI</dc:creator>
      <pubDate>Fri, 13 Mar 2026 06:16:19 +0000</pubDate>
      <link>https://dev.to/contextfirstai/the-compliance-audit-your-property-management-software-isnt-ready-for-21ha</link>
      <guid>https://dev.to/contextfirstai/the-compliance-audit-your-property-management-software-isnt-ready-for-21ha</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fehe2gemetpfjrd6ldc3w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fehe2gemetpfjrd6ldc3w.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;br&gt;
Most property management software is optimised for operations — tenant portals, digital leases, rent collection. Almost none of it is built to satisfy a compliance audit. The gap isn't a feature gap. It's an architecture gap. Here's what that means structurally, and what a compliant data model actually looks like in code.&lt;/p&gt;

&lt;p&gt;We've watched property management companies spend months evaluating CRM platforms, lease accounting tools, and tenant portals — and almost none of them ask the one question that could sink a deal, trigger a regulator, or expose them to a class-action: *can your software prove what happened, and when?&lt;/p&gt;

&lt;p&gt;That question isn't theoretical anymore. And the software most property management companies are running right now can't answer it.&lt;/p&gt;

&lt;p&gt;The Regulatory Landscape Has Quietly Shifted&lt;/p&gt;

&lt;p&gt;The past three years have compressed what used to be a slow-moving compliance curve into something that now moves faster than most technology procurement cycles. Fair housing enforcement has expanded its interpretation of discriminatory practice — not just explicit refusal, but demonstrable &lt;em&gt;patterns&lt;/em&gt; in response time.&lt;/p&gt;

&lt;p&gt;Several jurisdictions now tie habitability code compliance to documented acknowledgment windows. A landlord who &lt;em&gt;did&lt;/em&gt; fix the boiler but &lt;em&gt;can't prove&lt;/em&gt; they acknowledged the request within 24 hours is, legally, in approximately the same position as one who ignored it entirely.&lt;/p&gt;

&lt;p&gt;Add GDPR and CCPA obligations on tenant PII — name, contact details, payment history, maintenance history — and insurance underwriters now quietly requiring documented response protocols as part of commercial policy renewals.&lt;/p&gt;

&lt;p&gt;The regulatory environment hasn't just tightened. It's become multidimensional in ways a spreadsheet and a shared inbox weren't designed to handle.&lt;/p&gt;

&lt;p&gt;What Compliance Auditors Actually Look For&lt;/p&gt;

&lt;p&gt;Most people think compliance means having a fair housing policy written down somewhere. That's wrong.&lt;/p&gt;

&lt;p&gt;A formal compliance audit looks nothing like a policy review. An auditor examining fair housing adherence pulls maintenance records and looks for statistically significant variance in response times across protected class characteristics. They don't need to prove intent. They need to show pattern.&lt;/p&gt;

&lt;p&gt;If a head of operations at a 400-unit residential portfolio can't produce timestamped records of every maintenance request — its acknowledgment, assignment, and resolution, sorted by unit, date, and category — they're not just inconvenienced. They're exposed.&lt;/p&gt;

&lt;p&gt;On the data privacy side, auditors want to know where PII lives, who accessed it, and whether access was role-appropriate. A compliance officer running operations on email and Google Sheets can answer approximately none of those questions with any specificity.&lt;/p&gt;

&lt;p&gt;Insurance underwriting audits are the third vector — and they're growing. One director of operations at a firm managing 1,200 units recently received an underwriting questionnaire asking for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Average maintenance acknowledgment time&lt;/li&gt;
&lt;li&gt;Documented escalation paths&lt;/li&gt;
&lt;li&gt;Evidence PII was stored in an encrypted environment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They passed. Barely. By manually reconstructing 18 months of email records over three weeks with two part-time contractors. Not a scalable solution.&lt;/p&gt;

&lt;p&gt;The Architecture Gap&lt;/p&gt;

&lt;p&gt;Here's the real problem with email plus spreadsheets, and we don't want to be glib — the companies using them aren't unsophisticated. They're lean, fast-moving, and solving for today's operational problems rather than tomorrow's audit risk.&lt;/p&gt;

&lt;p&gt;But the gap is structural.&lt;/p&gt;

&lt;p&gt;A maintenance request that arrives at 9:47am, gets acknowledged at 2pm, reassigned twice, and closed eleven days later exists in most shared inboxes as a loosely threaded conversation with no visible timestamps at scale, no assignment log, no resolution record, no access trail.&lt;/p&gt;

&lt;p&gt;The data is technically there. It's just not structured in any way that's retrievable under audit conditions.&lt;/p&gt;

&lt;p&gt;Spreadsheets are worse in a specific way. They're accurate in the moment and catastrophically incomplete over time. The person who built the tracker knew what the columns meant. Their replacement two years later doesn't. Neither version has role-based access controls, an edit log, or any mechanism to prevent retroactive date field edits.&lt;/p&gt;

&lt;p&gt;An auditor has no way to verify that a cell wasn't changed. That's a verifiability problem, not a trust problem.&lt;/p&gt;

&lt;p&gt;What a Compliant Data Model Looks Like&lt;/p&gt;

&lt;p&gt;The core requirement is &lt;strong&gt;immutable event records&lt;/strong&gt; — a write-once case lifecycle that can't be backdated.&lt;/p&gt;

&lt;p&gt;Here's the conceptual schema for a compliant maintenance request lifecycle:&lt;/p&gt;

&lt;p&gt;sql&lt;br&gt;
Core events table: append-only, no UPDATE operations permitted&lt;br&gt;
CREATE TABLE maintenance_events (&lt;br&gt;
  id              UUID PRIMARY KEY DEFAULT gen_random_uuid(),&lt;br&gt;
  request_id      UUID NOT NULL REFERENCES maintenance_requests(id),&lt;br&gt;
  event_type      TEXT NOT NULL CHECK (event_type IN (&lt;br&gt;
                    'received', 'acknowledged', 'assigned',&lt;br&gt;
                    'reassigned', 'updated', 'escalated', 'resolved'&lt;br&gt;
                  )),&lt;br&gt;
  actor_id        UUID NOT NULL REFERENCES users(id),&lt;br&gt;
  actor_role      TEXT NOT NULL,&lt;br&gt;
  occurred_at     TIMESTAMPTZ NOT NULL DEFAULT now(),&lt;br&gt;
  metadata        JSONB,&lt;br&gt;
  -- No updated_at — this record is immutable after insert&lt;br&gt;
  CONSTRAINT no_future_events CHECK (occurred_at &amp;lt;= now())&lt;br&gt;
);&lt;/p&gt;

&lt;p&gt;Revoke UPDATE and DELETE at the database level&lt;br&gt;
REVOKE UPDATE, DELETE ON maintenance_events FROM application_role;&lt;/p&gt;

&lt;p&gt;The key decisions here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No &lt;code&gt;UPDATE&lt;/code&gt; operations on event records — ever. Each state change is a new row.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;occurred_at&lt;/code&gt; defaults to &lt;code&gt;now()&lt;/code&gt; — the application cannot pass a historical timestamp.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;REVOKE&lt;/code&gt; at the DB level — the application layer can't accidentally (or deliberately) mutate records even if the ORM tries to.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Role-Based Access: Structural, Not Informal&lt;/p&gt;

&lt;p&gt;Most people think RBAC means adding a &lt;code&gt;role&lt;/code&gt; column to the users table and checking it in application code. That's wrong for compliance purposes.&lt;/p&gt;

&lt;p&gt;Application-level checks can be bypassed, misconfigured, or forgotten in new endpoints. Compliant RBAC needs enforcement at the data layer.&lt;/p&gt;

&lt;p&gt;sql&lt;br&gt;
-- Role definitions with explicit data scope&lt;br&gt;
CREATE TABLE role_permissions (&lt;br&gt;
  role        TEXT NOT NULL,&lt;br&gt;
  resource    TEXT NOT NULL,&lt;br&gt;
  action      TEXT NOT NULL CHECK (action IN ('read', 'write', 'export')),&lt;br&gt;
  scope       TEXT NOT NULL CHECK (scope IN ('own', 'unit', 'portfolio')),&lt;br&gt;
  PRIMARY KEY (role, resource, action)&lt;br&gt;
);&lt;/p&gt;

&lt;p&gt;INSERT INTO role_permissions VALUES&lt;br&gt;
  ('field_technician',  'work_orders',      'read',   'own'),&lt;br&gt;
  ('field_technician',  'work_orders',      'write',  'own'),&lt;br&gt;
  ('leasing_agent',     'tenant_contacts',  'read',   'unit'),&lt;br&gt;
  ('compliance_head',   'maintenance_logs', 'read',   'portfolio'),&lt;br&gt;
  ('compliance_head',   'maintenance_logs', 'export', 'portfolio');&lt;/p&gt;

&lt;p&gt;-- Field technicians explicitly CANNOT access payment records&lt;br&gt;
-- This is enforced by absence, not by a deny rule&lt;/p&gt;

&lt;p&gt;Access is governed by what a role &lt;em&gt;has&lt;/em&gt;, not by what it &lt;em&gt;lacks&lt;/em&gt;. A field technician has no entry for &lt;code&gt;payment_records&lt;/code&gt; — so there's no code path that reaches that data, regardless of application logic.&lt;/p&gt;

&lt;p&gt;PII Encryption: At Rest and In Transit&lt;/p&gt;

&lt;p&gt;Under CCPA and GDPR, encrypting tenant PII at rest isn't optional. Neither is logging access to it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;cryptography.fernet&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Fernet&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timezone&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;uuid&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PIIStore&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encryption_key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cipher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Fernet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encryption_key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tenant_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;actor_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;encrypted&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cipher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
            INSERT INTO tenant_pii (tenant_id, field, encrypted_value, stored_at)
            VALUES (%s, %s, %s, %s)
        &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tenant_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encrypted&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timezone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utc&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_log_access&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tenant_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;write&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;actor_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;retrieve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tenant_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;actor_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetchone&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
            SELECT encrypted_value FROM tenant_pii
            WHERE tenant_id = %s AND field = %s
            ORDER BY stored_at DESC LIMIT 1
        &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tenant_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_log_access&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tenant_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;read&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;actor_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cipher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decrypt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;encrypted_value&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_log_access&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tenant_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;actor_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Every access — read or write — is logged. No exceptions.
&lt;/span&gt;        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
            INSERT INTO pii_access_log
              (id, tenant_id, field, action, actor_id, accessed_at)
            VALUES (%s, %s, %s, %s, %s, %s)
        &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uuid4&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt; &lt;span class="n"&gt;tenant_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;actor_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timezone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="n"&gt;Every&lt;/span&gt; &lt;span class="n"&gt;retrieval&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;logged&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;actor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;The&lt;/span&gt; &lt;span class="n"&gt;log&lt;/span&gt; &lt;span class="n"&gt;itself&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;only&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="n"&gt;subject&lt;/span&gt; &lt;span class="n"&gt;access&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="n"&gt;becomes&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;reconstruction&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="n"&gt;Escalation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Configured&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;Logged&lt;/span&gt;

&lt;span class="n"&gt;Practiced&lt;/span&gt; &lt;span class="n"&gt;escalation&lt;/span&gt; &lt;span class="n"&gt;paths&lt;/span&gt; &lt;span class="n"&gt;don&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;t count. Logged ones do.

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
javascript&lt;br&gt;
// Escalation rule engine — runs on a schedule&lt;br&gt;
async function checkEscalations(db, notifier) {&lt;br&gt;
  const unacknowledged = await db.query(&lt;code&gt;&lt;br&gt;
    SELECT r.id, r.received_at, r.priority&lt;br&gt;
    FROM maintenance_requests r&lt;br&gt;
    LEFT JOIN maintenance_events e&lt;br&gt;
      ON e.request_id = r.id AND e.event_type = 'acknowledged'&lt;br&gt;
    WHERE e.id IS NULL&lt;br&gt;
      AND r.received_at &amp;lt; NOW() - INTERVAL '4 hours'&lt;br&gt;
      AND r.status = 'open'&lt;br&gt;
&lt;/code&gt;);&lt;/p&gt;

&lt;p&gt;for (const request of unacknowledged.rows) {&lt;br&gt;
    // Notify the escalation target&lt;br&gt;
    await notifier.send({&lt;br&gt;
      type: 'escalation',&lt;br&gt;
      requestId: request.id,&lt;br&gt;
      reason: 'unacknowledged_sla_breach',&lt;br&gt;
      slaWindow: '4h'&lt;br&gt;
    });&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Log the escalation as an immutable event — same as any other lifecycle event
await db.query(`
  INSERT INTO maintenance_events
    (request_id, event_type, actor_id, actor_role, metadata)
  VALUES ($1, 'escalated', $2, 'system', $3)
`, [
  request.id,
  'system-escalation-process',
  JSON.stringify({ reason: 'sla_breach', threshold_hours: 4 })
]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;The escalation is an event. Same table. Same immutability rules. An auditor can see that the system escalated this request at 14:03 on a Tuesday, and to whom. That's the difference between a practiced process and a documented one.&lt;/p&gt;

&lt;p&gt;Data Subject Access Requests in Under 20 Minutes&lt;/p&gt;

&lt;p&gt;If your DSAR response involves manually searching email threads, you have a structural problem.&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
python
def generate_dsar_export(tenant_id: str, actor_id: str, db) -&amp;gt; dict:
    """
    Produce a complete DSAR-compliant export for a tenant.
    Everything the system holds, in a single structured response.
    """
    return {
        "generated_at": datetime.now(timezone.utc).isoformat(),
        "requested_by": actor_id,
        "tenant_id": tenant_id,
        "personal_data": {
            "contact": db.fetchall(
                "SELECT field, stored_at FROM tenant_pii WHERE tenant_id = %s",
                (tenant_id,)
            ),
            "maintenance_history": db.fetchall("""
                SELECT r.id, r.category, r.received_at,
                       json_agg(e ORDER BY e.occurred_at) as lifecycle
                FROM maintenance_requests r
                JOIN maintenance_events e ON e.request_id = r.id
                WHERE r.tenant_id = %s
                GROUP BY r.id
            """, (tenant_id,)),
            "pii_access_log": db.fetchall(
                "SELECT field, action, actor_id, accessed_at FROM pii_access_log WHERE tenant_id = %s ORDER BY accessed_at DESC",
                (tenant_id,)
            )
        }
    }

That's a DSAR. One function call. Structured output. Auditable by design — because the data model was built that way from day one, not retrofitted when a regulator asked.

Real-World Impact

A compliance director at a 60-staff property management company described their transition primarily in terms of time. Before: two weeks of manual record reconstruction for an insurance underwriting review. After: running an export. The data was already there, timestamped, organised by category and date range.

A head of technology at a residential property group managing assets across multiple ownership structures found access logging was the most operationally valuable thing they hadn't anticipated. A data subject access request went from a theoretical nightmare to a 20-minute task.

Nobody wants to say this, but the property management software market has significantly oversold operational features relative to the compliance infrastructure that should come first. Operational features drive demos. Compliance infrastructure prevents catastrophe. Vendors know the difference.

Compliance Readiness Checklist

Use this during your next platform evaluation — before the demo, not after.

Audit Trail &amp;amp; Case Lifecycle

- Every maintenance event generates an immutable, timestamped record
- No event record can be backdated or mutated — enforced at the database layer
- Full case lifecycle is queryable and exportable by date range, unit, category, and status

PII &amp;amp; Data Privacy

- Tenant PII encrypted at rest and in transit
- Access to PII is role-gated, not inbox-level
- Every PII access — read and write — is logged with actor and timestamp
- DSAR can be fulfilled programmatically, not manually

Fair Housing &amp;amp; Response Time

- Acknowledgment time measurable at portfolio scale
- Data filterable by unit and category to surface pattern variance
- SLA configuration is auditable — the system can prove what the window was at a given time

Role-Based Access Controls

- Permissions defined at the data layer, not just the application layer
- Field technicians structurally cannot access payment records
- Admin access is logged and periodically reviewed

Reporting &amp;amp; Export

- Compliance exports run on demand, not by reconstruction
- Exports are timestamped and version-controlled
- Insurance underwriting questionnaire answerable without manual effort

The Architecture Decision That Actually Matters

The compliance gap in property management isn't a process problem. It's a data architecture problem.

Operational data and audit trail shouldn't be two separate systems. They should be the same system — one that captures every event with full contextual metadata from the moment it's created.

Not as a logging afterthought. As the foundational data model.

The companies most at risk aren't the ones cutting corners. They're the ones that grew faster than their tooling. Reasonable choices at 50 units. Compliance liabilities at 800. Nobody sent a notification when they crossed the line.

The audit your software isn't ready for might not happen tomorrow. But the regulatory trend lines only point one direction.

Is your data architecture built to prove what happened — or is it hoping nobody asks?

---

- [HUD Fair Housing Act — [Enforcement and Documentation Requirements](https://www.hud.gov/program_offices/fair_housing_equal_opp/fair_housing_act_overview)]

- [ICO Guide to UK GDPR — [Data Subject Access Requests](https://ico.org.uk/for-organisations/uk-gdpr-guidance-and-resources/individual-rights/right-of-access/)]

- [CCPA Compliance Guide for Property Management — [California Attorney General](https://oag.ca.gov/privacy/ccpa))]


Created with AI assistance. Originally published at [[Context First AI](https://contextfirst.ai)]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
    </item>
    <item>
      <title>What You're Actually Signing Up For: Inside a Production-Grade GenAI Curriculum.</title>
      <dc:creator>Context First AI</dc:creator>
      <pubDate>Thu, 12 Mar 2026 06:03:08 +0000</pubDate>
      <link>https://dev.to/contextfirstai/what-youre-actually-signing-up-for-inside-a-production-grade-genai-curriculum-3a90</link>
      <guid>https://dev.to/contextfirstai/what-youre-actually-signing-up-for-inside-a-production-grade-genai-curriculum-3a90</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Famh68nb9jf3vl5fq6q3p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Famh68nb9jf3vl5fq6q3p.png" alt=" " width="800" height="1200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Most AI course failures happen before week one — expectation mismatch, not capability gaps. A real curriculum preview covers four things: sequence logic, content depth, technology stack, and project scope. This is ours, written plainly.&lt;/p&gt;

&lt;p&gt;The Problem With "What You'll Learn" Lists&lt;br&gt;
Most course previews are structured around outcome bullets. "By the end of this course, you will be able to..." — followed by five to eight competencies that sound compelling but reveal almost nothing about the actual learning journey.&lt;br&gt;
This format serves the provider, not the learner.&lt;br&gt;
It answers "what do I get?" without answering the more useful question: "is this the right programme for where I am right now?"&lt;br&gt;
A senior developer at an early-stage fintech enrolled expecting hands-on engineering work. Spent four weeks on theory that had nothing to do with what he was building. A training coordinator's team completed a well-known AI fundamentals course, received certificates, and still couldn't tell her whether anything was applicable to their actual workflow.&lt;br&gt;
Neither situation was a capability problem. Both were information gaps — right at the start.&lt;/p&gt;

&lt;p&gt;What a Genuine Preview Actually Includes&lt;br&gt;
A curriculum preview worth reading covers four things:&lt;/p&gt;

&lt;p&gt;Sequence logic — why the order matters, not just what's covered&lt;br&gt;
Content depth — where complexity spikes and why&lt;br&gt;
Technology stack — named tools, not "industry-leading frameworks"&lt;br&gt;
Project scope — what you build, not what you study&lt;/p&gt;

&lt;p&gt;Miss any one of them and you've produced a partial picture that still leaves learners guessing.&lt;/p&gt;

&lt;p&gt;The Tech Stack — Named, With Reasoning&lt;br&gt;
Technology choices in a curriculum are editorial decisions. Learners deserve to understand the reasoning.&lt;br&gt;
textLanguage:       Python&lt;br&gt;
LLM Models:     OpenAI, DeepSeek, Claude (Anthropic)&lt;br&gt;
Frameworks:     LangChain, LangGraph, LangSmith&lt;br&gt;
Tracing:        Langfuse (Docker-based)&lt;br&gt;
Vector Stores:  Qdrant DB, PGVector&lt;br&gt;
Graph DB:       Neo4j + Cypher&lt;br&gt;
Infrastructure: AWS, Docker, MCP Server&lt;br&gt;
Embeddings:     Open-source + proprietary vector models&lt;br&gt;
This isn't assembled for comprehensiveness. These are the tools practitioners are actually using in production environments right now.&lt;br&gt;
The choice to include both open-source and proprietary model options is deliberate. Learners shouldn't be trained to depend on a single provider's API. Working with self-hosted models like Llama-3 or Gemma, and implementing guardrails and PII detection around them, is increasingly a professional requirement.&lt;/p&gt;

&lt;p&gt;Curriculum Structure: Phase by Phase&lt;br&gt;
Phase 1 — Foundation&lt;br&gt;
LLM concepts, agentic AI, first working chatbot with LangChain. The goal here isn't content delivery — it's shared vocabulary across a mixed-background cohort.&lt;br&gt;
python# First working chatbot — what learners build in Phase 1&lt;br&gt;
from langchain_openai import ChatOpenAI&lt;br&gt;
from langchain_core.messages import HumanMessage, SystemMessage&lt;/p&gt;

&lt;p&gt;llm = ChatOpenAI(model="gpt-4o", temperature=0.7)&lt;/p&gt;

&lt;p&gt;messages = [&lt;br&gt;
    SystemMessage(content="You are a helpful assistant."),&lt;br&gt;
    HumanMessage(content="Explain what a vector database is in two sentences.")&lt;br&gt;
]&lt;/p&gt;

&lt;p&gt;response = llm.invoke(messages)&lt;br&gt;
print(response.content)&lt;br&gt;
Skip foundation and the cohort fractures. A developer and an operations manager don't share the same baseline — foundation modules close that gap before advanced content depends on it.&lt;br&gt;
Phase 2 — Document Intelligence&lt;br&gt;
Semantic search, RAG, context-aware systems. This phase comes early because it sits closest to real organisational workflows. Most teams can pilot a RAG implementation immediately after completing it.&lt;br&gt;
python# Basic RAG setup using LangChain + Qdrant&lt;br&gt;
from langchain_qdrant import QdrantVectorStore&lt;br&gt;
from langchain_openai import OpenAIEmbeddings, ChatOpenAI&lt;br&gt;
from langchain.chains import RetrievalQA&lt;/p&gt;

&lt;p&gt;embeddings = OpenAIEmbeddings(model="text-embedding-3-small")&lt;/p&gt;

&lt;p&gt;vectorstore = QdrantVectorStore.from_existing_collection(&lt;br&gt;
    embedding=embeddings,&lt;br&gt;
    collection_name="documents",&lt;br&gt;
    url="&lt;a href="http://localhost:6333" rel="noopener noreferrer"&gt;http://localhost:6333&lt;/a&gt;"&lt;br&gt;
)&lt;/p&gt;

&lt;p&gt;retriever = vectorstore.as_retriever(search_kwargs={"k": 4})&lt;/p&gt;

&lt;p&gt;qa_chain = RetrievalQA.from_chain_type(&lt;br&gt;
    llm=ChatOpenAI(model="gpt-4o"),&lt;br&gt;
    retriever=retriever,&lt;br&gt;
    return_source_documents=True&lt;br&gt;
)&lt;/p&gt;

&lt;p&gt;result = qa_chain.invoke({"query": "What are the key compliance requirements?"})&lt;br&gt;
print(result["result"])&lt;br&gt;
Phase 3 — Advanced Capabilities&lt;br&gt;
Multi-modal applications, LLM safety, guardrails, PII detection, self-hosted models. The complexity jump here is real. We'd rather say that plainly than have learners hit week five unprepared.&lt;br&gt;
python# Basic guardrail pattern for PII detection&lt;br&gt;
import re&lt;/p&gt;

&lt;p&gt;def detect_pii(text: str) -&amp;gt; dict:&lt;br&gt;
    patterns = {&lt;br&gt;
        "email": r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Z|a-z]{2,}\b',&lt;br&gt;
        "phone": r'\b(+44|0)[\s-]?(\d[\s-]?){9,10}\b',&lt;br&gt;
        "national_id": r'\b[A-Z]{2}\d{6}[A-Z]\b'&lt;br&gt;
    }&lt;br&gt;
    findings = {}&lt;br&gt;
    for label, pattern in patterns.items():&lt;br&gt;
        matches = re.findall(pattern, text)&lt;br&gt;
        if matches:&lt;br&gt;
            findings[label] = matches&lt;br&gt;
    return findings&lt;/p&gt;

&lt;p&gt;sample = "Contact &lt;a href="mailto:john.doe@company.com"&gt;john.doe@company.com&lt;/a&gt; or call 07911 123456 for details."&lt;br&gt;
print(detect_pii(sample))&lt;/p&gt;

&lt;h1&gt;
  
  
  Output: {'email': ['&lt;a href="mailto:john.doe@company.com"&gt;john.doe@company.com&lt;/a&gt;'], 'phone': ['07911 123456']}
&lt;/h1&gt;

&lt;p&gt;Phase 4 — Agent Engineering&lt;br&gt;
LangGraph orchestration, human-in-the-loop design, tool binding, controlled vs autonomous agents. This is the difference between prompting an AI and engineering a system around one.&lt;br&gt;
python# LangGraph state machine — minimal example of controlled agent flow&lt;br&gt;
from langgraph.graph import StateGraph, END&lt;br&gt;
from typing import TypedDict, Annotated&lt;br&gt;
import operator&lt;/p&gt;

&lt;p&gt;class AgentState(TypedDict):&lt;br&gt;
    messages: Annotated[list, operator.add]&lt;br&gt;
    requires_human_review: bool&lt;/p&gt;

&lt;p&gt;def analyse_task(state: AgentState) -&amp;gt; AgentState:&lt;br&gt;
    # Agent decides whether human review is needed&lt;br&gt;
    last_message = state["messages"][-1]&lt;br&gt;
    high_stakes = any(&lt;br&gt;
        keyword in last_message.lower()&lt;br&gt;
        for keyword in ["legal", "financial", "compliance", "terminate"]&lt;br&gt;
    )&lt;br&gt;
    return {"requires_human_review": high_stakes}&lt;/p&gt;

&lt;p&gt;def route_decision(state: AgentState) -&amp;gt; str:&lt;br&gt;
    return "human_review" if state["requires_human_review"] else "auto_proceed"&lt;/p&gt;

&lt;p&gt;workflow = StateGraph(AgentState)&lt;br&gt;
workflow.add_node("analyse", analyse_task)&lt;br&gt;
workflow.add_conditional_edges("analyse", route_decision, {&lt;br&gt;
    "human_review": "human_review",&lt;br&gt;
    "auto_proceed": END&lt;br&gt;
})&lt;br&gt;
Phase 5 — Architecture &amp;amp; Deployment&lt;br&gt;
AWS, Langfuse tracing, MCP server integration, LLM-as-judge evaluation, Neo4j + Cypher retrieval. Deployment is where theory meets accountability.&lt;br&gt;
python# LLM-as-Judge evaluation pattern&lt;br&gt;
from langchain_openai import ChatOpenAI&lt;br&gt;
from langchain_core.prompts import ChatPromptTemplate&lt;/p&gt;

&lt;p&gt;judge_llm = ChatOpenAI(model="gpt-4o", temperature=0)&lt;/p&gt;

&lt;p&gt;judge_prompt = ChatPromptTemplate.from_template("""&lt;br&gt;
You are an evaluator assessing AI response quality.&lt;/p&gt;

&lt;p&gt;Question: {question}&lt;br&gt;
Response: {response}&lt;/p&gt;

&lt;p&gt;Score the response 1-5 on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Accuracy&lt;/li&gt;
&lt;li&gt;Completeness
&lt;/li&gt;
&lt;li&gt;Conciseness&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Return JSON only: {{"accuracy": int, "completeness": int, "conciseness": int, "reasoning": str}}&lt;br&gt;
""")&lt;/p&gt;

&lt;p&gt;judge_chain = judge_prompt | judge_llm&lt;/p&gt;

&lt;p&gt;evaluation = judge_chain.invoke({&lt;br&gt;
    "question": "What is retrieval-augmented generation?",&lt;br&gt;
    "response": "RAG combines LLMs with external knowledge sources..."&lt;br&gt;
})&lt;br&gt;
print(evaluation.content)&lt;/p&gt;

&lt;p&gt;The Five Hands-On Projects&lt;br&gt;
These aren't decorative. Each maps directly to a real professional use case.&lt;br&gt;
ProjectCore PatternTransferable ToAI Legal AssistantDocument Q&amp;amp;A over dense knowledge basesAny knowledge-heavy industryChart Generator (Postgres)NL → SQL → visualisationFinance, analytics, productResume RoasterLLM + structured rubric evaluationAny scoring/feedback workflowCandidate Finder BotSemantic matching + filtersRecommendation engines, searchWebsite Intelligence BotRAG over business contentInternal knowledge bases&lt;br&gt;
Learners who complete project-based work retain roughly 37% more applicable knowledge than those who complete assessments only. That gap isn't about difficulty — it's about integration. Assessments test recall. Projects require synthesis.&lt;/p&gt;

&lt;p&gt;What This Means If You're Switching Careers Into AI&lt;br&gt;
Applied-first, not mathematics-first. The programme doesn't go deep on transformer architecture or backpropagation. What it covers: how to build systems that use models effectively, securely, and at a level of sophistication that makes you genuinely useful on an AI product or data team.&lt;br&gt;
No prior deep learning background required. Python fundamentals help. Familiarity with APIs helps more.&lt;/p&gt;

&lt;p&gt;What This Means If You're an L&amp;amp;D Professional&lt;br&gt;
The modular structure maps against adjacent learning pathways. Foundation modules run alongside lighter AI literacy content for broader teams. Advanced modules bridge into engineering or AI governance tracks. The programme is designed to sit inside a roadmap, not replace one.&lt;/p&gt;

&lt;p&gt;Key Takeaways&lt;br&gt;
Sequence logic explains as much as content. Why modules are ordered tells you more about a programme's philosophy than the titles.&lt;br&gt;
Stack transparency is a trust signal. Vague "AI frameworks" language = either indecision or irrelevance. Named tools = accountable curriculum.&lt;br&gt;
Projects are where retention happens. ~37% knowledge retention gap between project-based and assessment-only completions. The difference is integration, not difficulty.&lt;br&gt;
Foundation isn't optional — it's structural. Mixed-background cohorts fracture without shared vocabulary. Don't skip it.&lt;br&gt;
Preview content should help you self-select. If reading a curriculum preview doesn't help you decide, the preview hasn't done its job.&lt;/p&gt;

&lt;p&gt;Resources&lt;/p&gt;

&lt;p&gt;&lt;a href="https://python.langchain.com/docs/introduction/" rel="noopener noreferrer"&gt;LangChain Documentation &lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://langchain-ai.github.io/langgraph/concepts/" rel="noopener noreferrer"&gt;LangGraph Conceptual Guide &lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://qdrant.tech/documentation/" rel="noopener noreferrer"&gt;Qdrant Vector Database Documentation &lt;/a&gt; &lt;/p&gt;

</description>
      <category>ai</category>
      <category>career</category>
      <category>learning</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>The AI Practitioner Ladder Where Are You, Really?</title>
      <dc:creator>Context First AI</dc:creator>
      <pubDate>Wed, 11 Mar 2026 06:23:51 +0000</pubDate>
      <link>https://dev.to/contextfirstai/the-ai-practitioner-ladder-where-are-you-really-3ae9</link>
      <guid>https://dev.to/contextfirstai/the-ai-practitioner-ladder-where-are-you-really-3ae9</guid>
      <description>&lt;p&gt;Most AI practitioners are further back on the competence curve than they think. Frequency of use tells you almost nothing. What actually separates levels is &lt;em&gt;contextual judgment&lt;/em&gt; — knowing what the model needs, what it can't know on its own, and who's responsible for the gap. This post maps four observable orientations and what moving between them actually requires.&lt;/p&gt;

&lt;p&gt;Most people who work with AI professionally have no idea where they actually sit on the competence curve. Not a criticism — just something you notice when you've watched enough practitioners work through the same class of problems.&lt;/p&gt;

&lt;p&gt;A Pattern We Keep Noticing&lt;/p&gt;

&lt;p&gt;There's a particular conversation we've had more times than we can count. Someone joins the Mesh network — a senior analyst at a mid-sized consultancy, or a product lead at a scaling SaaS company — and they describe their AI work with a quiet confidence that starts to slip under questioning. They use the tools. They've shipped things. They know the vocabulary. But when we dig into &lt;em&gt;how&lt;/em&gt; they think about AI problems, something's missing. Not intelligence. Not effort. Something structural.&lt;/p&gt;

&lt;p&gt;The inverse also happens, and it's equally instructive. A junior researcher at a think tank, someone who'd probably describe themselves as "still figuring it out," turns out to be operating with a level of contextual sophistication that most mid-career practitioners haven't developed. They can't always explain why their outputs are better. But they are.&lt;/p&gt;

&lt;p&gt;This is the core tension in AI practitioner development right now, and we think it doesn't get discussed honestly enough. The field rewards people who sound advanced. It's less good at surfacing who actually &lt;em&gt;is&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The Problem With How We Talk About AI Skill&lt;/p&gt;

&lt;p&gt;The dominant framework most practitioners work from — implicitly, since almost nobody writes it down — goes something like: beginner uses AI occasionally, intermediate uses it frequently, advanced uses it for complex tasks. This is almost entirely useless as a developmental map.&lt;/p&gt;

&lt;p&gt;Frequency of use tells you almost nothing. A marketing coordinator who writes fifty prompts a day for social captions and a machine learning engineer who writes three carefully constructed prompts for a research synthesis task are not on the same ladder, measured from the same rung. They're on different ladders entirely.&lt;/p&gt;

&lt;p&gt;What actually separates practitioners at different levels isn't usage volume or even technical sophistication in isolation. It's something we'd describe as &lt;em&gt;contextual judgment&lt;/em&gt; — the ability to understand what the model needs to know, what it cannot know on its own, and how the gap between those two things should shape everything from your initial framing to how you evaluate the output.&lt;/p&gt;

&lt;p&gt;We'd go further: we think most AI training programmes, including some expensive ones, are optimising for the wrong signal entirely. They teach prompt syntax when they should be teaching epistemic habits.&lt;/p&gt;

&lt;p&gt;The Part Nobody Demos: Context vs. Syntax&lt;/p&gt;

&lt;p&gt;Here's what this looks like in concrete terms. Two practitioners, same task: summarise a set of customer support tickets and identify systemic issues.&lt;/p&gt;

&lt;p&gt;Task-first approach** — adjusts by feel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Prompt written by a task-first practitioner
&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
Summarise these customer support tickets and identify the main issues.

Tickets:
{tickets}
&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

&lt;span class="n"&gt;Output&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;decent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;Patterns&lt;/span&gt; &lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="n"&gt;named&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;But&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;framing&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;generic&lt;/span&gt; &lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="n"&gt;has&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt; &lt;span class="n"&gt;idea&lt;/span&gt; &lt;span class="n"&gt;what&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;systemic issues&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="n"&gt;means&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;this&lt;/span&gt; &lt;span class="n"&gt;business&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;what&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;threshold&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;main&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;whether&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;goal&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;root&lt;/span&gt; &lt;span class="n"&gt;cause&lt;/span&gt; &lt;span class="n"&gt;analysis&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;triage&lt;/span&gt; &lt;span class="n"&gt;prioritisation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;

&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;first&lt;/span&gt; &lt;span class="n"&gt;approach&lt;/span&gt; &lt;span class="err"&gt;—&lt;/span&gt; &lt;span class="n"&gt;fills&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;gap&lt;/span&gt; &lt;span class="n"&gt;deliberately&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;/p&gt;
&lt;h1&gt;
  
  
  Prompt written by a context-first practitioner
&lt;/h1&gt;

&lt;p&gt;prompt = """&lt;br&gt;
You are reviewing customer support tickets for a B2B SaaS product used primarily&lt;br&gt;
by operations teams in logistics companies. The goal is root cause analysis, not&lt;br&gt;
triage — we want to identify issues that appear across multiple tickets and suggest&lt;br&gt;
whether they're product bugs, documentation gaps, or onboarding failures.&lt;/p&gt;

&lt;p&gt;A "systemic issue" means it appeared in 3 or more tickets in the past 30 days&lt;br&gt;
and is not already on the known issues tracker (attached).&lt;/p&gt;

&lt;p&gt;Do not surface one-off complaints or feature requests. Focus only on recurring&lt;br&gt;
failure patterns with a clear locus of ownership.&lt;/p&gt;

&lt;p&gt;Tickets (past 30 days):&lt;br&gt;
{tickets}&lt;/p&gt;

&lt;p&gt;Known issues tracker:&lt;br&gt;
{known_issues}&lt;br&gt;
"""&lt;br&gt;
Same model. Same tickets. Completely different output — because the second practitioner asked a different question before they opened the interface: &lt;em&gt;what does this model not know that it would need to know to get this right?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The Ladder, As We Actually See It&lt;/p&gt;

&lt;p&gt;Rather than describing stages with tidy names (a temptation we're deliberately resisting), it's more accurate to describe four observable orientations. Practitioners at any given point tend to be anchored in one, with partial fluency in the next. When we designed the Mesh membership tiers, we didn't start with a pricing model. We started with this ladder — and built backwards from it.&lt;/p&gt;

&lt;p&gt;Orientation 1: Tool-First&lt;/p&gt;

&lt;p&gt;The practitioner's primary question is: &lt;em&gt;what can this do?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;They explore capabilities, experiment with formats, learn what kinds of requests produce usable outputs. This is entirely valid and necessary work. There's no shortcut through it. The risk is staying here — treating every new model release as the beginning of a new exploration cycle without ever building durable judgment that transfers.&lt;/p&gt;

&lt;p&gt;In Mesh, we call this the &lt;strong&gt;Token&lt;/strong&gt; stage: your entry point into the community, built around public channels, a resource library, and enough exposure to the landscape to figure out what you're actually looking at.&lt;/p&gt;

&lt;p&gt;Orientation 2: Task-First&lt;/p&gt;

&lt;p&gt;The practitioner has moved from wondering what the tool can do to knowing what they need to accomplish. They've built functional workflows. They can reliably get usable outputs for the tasks they've repeated enough times.&lt;/p&gt;

&lt;p&gt;What's missing: the ability to diagnose failure.&lt;/p&gt;

&lt;p&gt;When outputs are poor or wrong, they tend to adjust the prompt by feel rather than by understanding what the model is actually missing. This is, for what it's worth, where we'd estimate roughly 60-something percent of self-described "regular AI users" are currently sitting. We're not entirely sure that number holds across sectors, but it feels right.&lt;/p&gt;

&lt;p&gt;The edge case that bites you: consistent underperformance on variations of a task you think you've solved — because the workflow is brittle to context changes you haven't named yet.&lt;/p&gt;

&lt;p&gt;The Mesh &lt;strong&gt;Model&lt;/strong&gt; tier is designed for this stage — discussion boards, AMA sessions with practitioners operating at higher orientations, and a full resource library built to create the friction that actually develops judgment rather than just filling gaps in vocabulary.&lt;/p&gt;

&lt;p&gt;Orientation 3: Context-First&lt;/p&gt;

&lt;p&gt;The practitioner has developed a working model of what the AI actually needs in order to perform well: domain framing, constraint specification, examples, scope boundaries. They can decompose a complex task into components that match what the model handles reliably versus what needs human intervention.&lt;/p&gt;

&lt;p&gt;Outputs don't just work — they're &lt;em&gt;designed&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In practice, this looks like a pre-task checklist before touching the interface:&lt;/p&gt;

&lt;p&gt;Context-First Pre-Task Checklist&lt;br&gt;
─────────────────────────────────&lt;br&gt;
What domain knowledge does this model lack for this specific task?&lt;br&gt;
What constraints define a correct output (format, scope, tone, threshold)?&lt;br&gt;
What examples would help calibrate the expected output?&lt;br&gt;
Which components need human judgment — and where in the flow?&lt;br&gt;
What does a failure mode look like, and how would I detect it?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
This is the orientation that separates practitioners who produce consistent value from those who have good days and bad days without understanding why.

The Agent tier in Mesh is built for people working at or toward this level: monthly build sessions, on-demand training, hackathon participation, and direct project guidance. The goal isn't exposure — it's repetitions with feedback, which is a different thing entirely.

Orientation 4: Systems-First

The practitioner is no longer primarily thinking about individual tasks or even workflows. They're thinking about how AI capability integrates into organisational context, decision structures, and knowledge flows.

A senior operations lead at a 200-person logistics company operating at this level isn't asking "how do I get a better output from this prompt." They're asking "where in our process does AI judgment need to be subordinate to human judgment, and how do we make that boundary legible to the people working inside it?"

Different question entirely.

In production terms, this looks less like prompt engineering and more like system design:

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
python&lt;/p&gt;
&lt;h1&gt;
  
  
  Systems-first thinking: designing the human-AI boundary explicitly
&lt;/h1&gt;

&lt;p&gt;AI_OWNED = [&lt;br&gt;
    "first-pass ticket classification",&lt;br&gt;
    "draft response generation",&lt;br&gt;
    "pattern aggregation across &amp;gt;50 data points",&lt;br&gt;
    "structured data extraction from unstructured text",&lt;br&gt;
]&lt;/p&gt;

&lt;p&gt;HUMAN_OWNED = [&lt;br&gt;
    "final send on customer-facing communications",&lt;br&gt;
    "escalation decisions involving contract terms",&lt;br&gt;
    "any output used in regulatory reporting",&lt;br&gt;
    "novel edge cases not covered by existing examples",&lt;br&gt;
]&lt;/p&gt;

&lt;p&gt;REVIEW_REQUIRED = [&lt;br&gt;
    "outputs flagged as low-confidence by the model",&lt;br&gt;
    "outputs touching sensitive account categories",&lt;br&gt;
    "any output that will be stored in a system of record",&lt;br&gt;
]&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
This isn't a prompt. It's governance architecture. It's what systems-first practitioners are actually building.

Agent Pro is the Mesh tier built around this orientation — live projects sourced directly by Context First AI, revenue-sharing structures, 1-on-1 mentorship, and exclusive access to a network of practitioners who've already made the transition from building their own outputs to building conditions for others.

Why the Gaps Are Hard to See

The uncomfortable thing about this ladder is that each orientation *feels* like mastery from the inside. This isn't stupidity — it's a feature of how skill development works. You can only evaluate your own performance using the frameworks you currently have. If your framework doesn't include contextual judgment as a variable, you won't notice it's missing.

We've seen this play out concretely. A data lead at a professional services firm produces genuinely impressive AI-assisted analyses, clean and well-formatted, and receives strong feedback from clients. What nobody catches — including the practitioner — is that the framing assumptions baked into the initial prompts are subtly wrong for the use case, and the outputs, while polished, are solving a slightly different problem than the one the client actually has. The model did exactly what it was asked. The asking was the problem.

This is also why peer learning environments matter more than most practitioners recognise. It's genuinely difficult to see the shape of your own blind spots. It's much easier when you watch someone else work through a similar problem with a different orientation — not because they're smarter, but because the contrast makes the structural difference visible.

Practical Implications

Moving between orientations isn't primarily about learning new techniques. It's about developing new diagnostic habits.

A practitioner moving from task-first to context-first needs to build the habit of asking, before they start: *what does this model not know that it would need to know to get this right?* Not what do I want to produce, but what information gap am I responsible for filling.

Moving from context-first to systems-first requires something harder — stepping back from individual output quality as the primary metric and developing a view of where AI-assisted work creates new risks or dependencies inside an organisation. A head of content at a media company who has excellent contextual judgment in her own work still needs to think differently when she's setting the framework that fifteen other people are working within. Her job isn't to produce good outputs anymore. It's to build conditions where others can.

A Practical Self-Diagnostic

Take one recent piece of AI-assisted work where the output felt slightly off. Work backwards:

Failure Diagnostic
──────────────────
1. What did the model know going in?
   → List the context explicitly provided

2. What was it missing?
   → What domain knowledge, constraints, or examples were absent?

3. Was the framing accurate?
   → Did your prompt represent what you actually needed — or what
     you thought you needed?

4. Where did you make an implicit assumption the model couldn't share?
   → That's your development edge.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That exercise, done honestly, tends to locate you on the ladder more accurately than any self-assessment.&lt;/p&gt;

&lt;p&gt;Key Takeaways&lt;/p&gt;

&lt;p&gt;Frequency of use is a poor proxy for practitioner level. Volume doesn't compound into judgment without deliberate reflection built in.&lt;/p&gt;

&lt;p&gt;Contextual judgment is the critical variable. The question isn't what the model can do — it's what it needs to know, and who's responsible for providing it.&lt;/p&gt;

&lt;p&gt;Gaps are structurally invisible from inside them. Peer environments and observable contrast are often more diagnostic than training content.&lt;/p&gt;

&lt;p&gt;Moving up the ladder requires changing your primary question. Tool-first asks what can this do. Context-first asks what does this need. Systems-first asks how does this change the way we make decisions.&lt;/p&gt;

&lt;p&gt;Honest failure analysis compounds faster than technique acquisition.One well-examined bad output teaches more than ten good ones that went unexplained.&lt;/p&gt;

&lt;p&gt;Context First AI: Building the Infrastructure for This Kind of Development&lt;/p&gt;

&lt;p&gt;The Mesh practitioner network exists precisely because the kind of development described above doesn't happen in isolation. It happens through exposure — to different orientations, different sectors, different ways of framing problems that are structurally similar even when they look nothing alike on the surface.&lt;/p&gt;

&lt;p&gt;Context First AI built Mesh as a matching layer for practitioners, not a profile directory. The distinction matters. A profile-based community surfaces who people are and what they've done. A context-driven network surfaces how they think about problems — and connects practitioners across the gap between where they currently are and where their specific development needs to go.&lt;/p&gt;

&lt;p&gt;The four-tier structure — &lt;strong&gt;Token, Model, Agent, Agent Pro&lt;/strong&gt; — isn't an arbitrary membership hierarchy. Each tier is designed around the specific developmental needs of practitioners at a particular orientation. Token gives you the lay of the land. Model builds the foundation for real judgment through discussion boards, peer access, and AMA sessions. Agent is for practitioners ready to ship things — repetitions with feedback, which is a different thing entirely from exposure. Agent Pro is where the focus shifts from building your own capability to operating at the level where AI work intersects with live client projects, organisational decisions, and real revenue.&lt;/p&gt;

&lt;p&gt;We've found that the most valuable exchanges in the network are rarely about techniques or tools. They're about the questions practitioners are learning to ask before they reach for the tools. That's the layer Context First AI is building for — and why the tiers are structured around orientation, not just access.&lt;/p&gt;

&lt;p&gt;Conclusion&lt;/p&gt;

&lt;p&gt;We keep coming back to a version of the same observation: the practitioners who develop fastest aren't the ones who use AI the most. They're the ones who have the clearest picture of where they currently are. That clarity is harder to find than it sounds, and most of the structures around AI learning aren't built to provide it. We're trying to build something that is. Whether it works is something the community will tell us over time — and we're paying attention.&lt;/p&gt;

&lt;p&gt;Resources&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;[&lt;a href="https://pair.withgoogle.com/explorables/" rel="noopener noreferrer"&gt;PAIR Explorables – Google's People + AI Research&lt;/a&gt;] — Thoughtful frameworks for understanding human-AI interaction and where judgment lives in the loop.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;[&lt;a href="https://www.aisnakeoil.com/" rel="noopener noreferrer"&gt;AI Snake Oil – Arvind Narayanan &amp;amp; Sayash Kapoor&lt;/a&gt;] — One of the more honest ongoing analyses of where AI capability claims diverge from reality.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://contextfirst.ai/mesh" rel="noopener noreferrer"&gt;[Context First AI – Mesh Network]&lt;/a&gt; — The practitioner community this article is written for.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Created with AI assistance. Originally published at [&lt;a href="https://contextfirst.ai" rel="noopener noreferrer"&gt;Context First AI&lt;/a&gt;]&lt;/p&gt;

</description>
      <category>ai</category>
      <category>career</category>
      <category>learning</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Compliance Isn't a Legal Problem. It's a Sales Problem.</title>
      <dc:creator>Context First AI</dc:creator>
      <pubDate>Tue, 10 Mar 2026 09:51:49 +0000</pubDate>
      <link>https://dev.to/contextfirstai/compliance-isnt-a-legal-problem-its-a-sales-problem-4g4d</link>
      <guid>https://dev.to/contextfirstai/compliance-isnt-a-legal-problem-its-a-sales-problem-4g4d</guid>
      <description>&lt;p&gt;Enterprise procurement is a filter, not a conversation. Non-compliant SaaS vendors get quietly removed from shortlists before a single sales call — no feedback, no CRM entry, just silence. Three lost deals at £80k–£150k ARR is up to £450k in revenue that never shows as a loss. A 3–4 week compliance sprint changes this. Here's how.&lt;/p&gt;

&lt;p&gt;Most people think compliance is a legal problem.&lt;/p&gt;

&lt;p&gt;That's wrong. It's a sales problem. And the cost isn't fines — it's deals you'll never know you lost.&lt;/p&gt;

&lt;p&gt;The Scenario That Kills Pipelines&lt;/p&gt;

&lt;p&gt;The procurement questionnaire arrived on a Tuesday. Forty-seven questions. Data residency, encryption standards, GDPR Article 28 obligations, penetration test reports, a signed Data Processing Agreement. A founder who'd spent eighteen months building an elegant B2B SaaS product sat staring at a form that had nothing to do with the product — and quietly realised they couldn't answer half of it. The deal didn't fall through loudly. It just stopped moving.&lt;/p&gt;

&lt;p&gt;This isn't a one-off. Across the teams we work with — technical founders, early-stage CTOs, product leads building for B2B markets — there's a remarkably consistent blind spot. Compliance gets treated as a future problem. Something you earn the right to think about once you've hit a certain revenue threshold.&lt;/p&gt;

&lt;p&gt;The problem is that by the time it "matters," the deal is already gone.&lt;/p&gt;

&lt;p&gt;We've seen this play out with a CTO at a 30-person SaaS company who built genuinely excellent infrastructure — proper encryption, thoughtful access controls, solid engineering discipline — but hadn't formalised any of it into documentation, hadn't completed a SOC 2 audit, and hadn't put a GDPR-compliant DPA template anywhere near their legal folder. When a mid-market EU prospect ran them through procurement, they got quietly removed from the shortlist before a single sales call. The prospect never said why. They rarely do.&lt;/p&gt;

&lt;p&gt;How Enterprise Buying Actually Works&lt;/p&gt;

&lt;p&gt;Enterprise procurement is a filter, not a conversation. Before your product gets evaluated on features, before anyone watches a demo, it goes through a checklist:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Security questionnaires&lt;/li&gt;
&lt;li&gt;GDPR compliance verification&lt;/li&gt;
&lt;li&gt;SOC 2 or ISO 27001 status&lt;/li&gt;
&lt;li&gt;Evidence of a signed DPA process&lt;/li&gt;
&lt;li&gt;Accessibility compliance under WCAG 2.1 for public sector buyers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These aren't formalities at the end of a sales process — they're the gatekeeping mechanism that determines whether you enter the process at all.&lt;/p&gt;

&lt;p&gt;A procurement lead at a financial services firm isn't asking about your data residency policy because they enjoy paperwork. They're asking because their compliance team requires it, their cyber insurance may depend on it, and if something goes wrong after they onboarded a non-compliant vendor, it's their name on the incident report.&lt;/p&gt;

&lt;p&gt;The result is that non-compliant vendors get removed from consideration at a stage that never shows up in your CRM. There's no "closed-lost" entry. No feedback. No objection to handle.&lt;/p&gt;

&lt;p&gt;Your pipeline looks fine. Your win rate looks fine. The invisible losses are invisible.&lt;/p&gt;

&lt;p&gt;The Real Cost: Run the Numbers&lt;/p&gt;

&lt;p&gt;The compliance conversation focuses on the wrong number. Yes, GDPR fines can reach €20 million or 4% of annual global turnover. But that's not what should concern an early-stage founder.&lt;/p&gt;

&lt;p&gt;Here's the actual maths:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Compliance delay cost calculator
&lt;/span&gt;
&lt;span class="n"&gt;deal_value_low&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80_000&lt;/span&gt;      &lt;span class="c1"&gt;# £ ARR per enterprise deal (low estimate)
&lt;/span&gt;&lt;span class="n"&gt;deal_value_high&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;150_000&lt;/span&gt;    &lt;span class="c1"&gt;# £ ARR per enterprise deal (high estimate)
&lt;/span&gt;&lt;span class="n"&gt;deals_lost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;               &lt;span class="c1"&gt;# Conservative estimate of deals lost in 12 months
&lt;/span&gt;&lt;span class="n"&gt;sales_cycle_increase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.37&lt;/span&gt;  &lt;span class="c1"&gt;# 37% longer sales cycles with security reviews
&lt;/span&gt;
&lt;span class="n"&gt;revenue_lost_low&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;deal_value_low&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;deals_lost&lt;/span&gt;
&lt;span class="n"&gt;revenue_lost_high&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;deal_value_high&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;deals_lost&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Conservative revenue lost: £&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;revenue_lost_low&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# £240,000
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;High-end revenue lost:     £&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;revenue_lost_high&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# £450,000
&lt;/span&gt;
&lt;span class="c1"&gt;# This revenue never appears as "closed-lost" — it just doesn't appear at all
# It looks like: slow pipeline, deals that "didn't progress", prospects who "went quiet"
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Delay compliance by six months and you're not deferring a build cost. You're deferring your ability to compete. A 37% longer sales cycle for deals requiring security review isn't minor friction — it's a structural drag on growth that compounds every quarter.&lt;/p&gt;

&lt;p&gt;There's something psychologically hard about counting deals you never knew you lost. But the maths is unforgiving regardless.&lt;/p&gt;

&lt;p&gt;Compliance as Competitive Moat&lt;/p&gt;

&lt;p&gt;Not a popular take: in regulated verticals, compliance isn't table stakes — it's the entry ticket that most of your competitors still can't buy.&lt;/p&gt;

&lt;p&gt;Healthcare, fintech, government procurement, legal tech, HR platforms handling employee data. The majority of smaller SaaS vendors targeting these sectors haven't completed SOC 2, aren't set up for HIPAA, haven't gone through the Crown Commercial Service framework, and haven't built the DPA infrastructure to pass a serious GDPR review.&lt;/p&gt;

&lt;p&gt;Which means that vendors who have done the work aren't just compliant — they're operating in a pool with dramatically fewer credible competitors.&lt;/p&gt;

&lt;p&gt;A head of technology at a 200-person insurance broker isn't choosing between ten viable options. They're choosing between the two or three that survived their own security team's initial review. If you're one of them, your conversion rate, sales cycle, and pricing power all look materially different.&lt;/p&gt;

&lt;p&gt;That's not a legal outcome. It's a commercial one.&lt;/p&gt;

&lt;p&gt;What "Getting Compliant" Actually Looks Like&lt;/p&gt;

&lt;p&gt;The good news — genuinely underappreciated — is that for most early-stage B2B SaaS products, the compliance work required to pass enterprise procurement isn't enormous.&lt;/p&gt;

&lt;p&gt;The Minimum Viable Compliance Checklist&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# minimum-viable-compliance.yaml&lt;/span&gt;
&lt;span class="c1"&gt;# Target: pass EU/UK mid-market enterprise procurement&lt;/span&gt;

&lt;span class="na"&gt;documentation&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;information_security_policy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;      &lt;span class="c1"&gt;# Written, versioned, signed off&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;asset_register&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;                   &lt;span class="c1"&gt;# What systems, who owns them&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;access_control_policy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;            &lt;span class="c1"&gt;# Who can see what, how audited&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;incident_response_procedure&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;      &lt;span class="c1"&gt;# What happens when things go wrong&lt;/span&gt;

&lt;span class="na"&gt;gdpr&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;privacy_notice&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;accurate&lt;/span&gt;               &lt;span class="c1"&gt;# Reflects what you actually do&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;data_register&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;                    &lt;span class="c1"&gt;# What data, where, why, how long&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;dpa_template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ready_to_countersign&lt;/span&gt;     &lt;span class="c1"&gt;# Non-negotiable for EU buyers&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;sub_processor_list&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;current&lt;/span&gt;            &lt;span class="c1"&gt;# Every tool that touches customer data&lt;/span&gt;

&lt;span class="na"&gt;technical_evidence&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;encryption_in_transit&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;documented&lt;/span&gt;      &lt;span class="c1"&gt;# TLS version, cert management&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;encryption_at_rest&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;documented&lt;/span&gt;         &lt;span class="c1"&gt;# DB encryption, key management&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;backup_and_recovery&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;documented&lt;/span&gt;        &lt;span class="c1"&gt;# RPO/RTO targets, tested&lt;/span&gt;

&lt;span class="na"&gt;certifications&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;soc2_type1&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;target_week_4&lt;/span&gt;              &lt;span class="c1"&gt;# Point-in-time, achievable fast&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;soc2_type2&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;target_month_9&lt;/span&gt;            &lt;span class="c1"&gt;# 6-12 month audit window&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;wcag_21_aa&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;in_progress&lt;/span&gt;               &lt;span class="c1"&gt;# Required for public sector&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;None of that requires a compliance team. It requires about three to four weeks of focused effort.&lt;/p&gt;

&lt;p&gt;SOC 2: Type I vs Type II&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SOC 2 Type I
├── Point-in-time snapshot of your controls
├── Achievable in 3-6 weeks for a lean product
├── Sufficient for most early enterprise deals
└── Cost: £3,000–£8,000 with a readiness consultant

SOC 2 Type II
├── Requires a 6–12 month observation window
├── Required for larger, more risk-averse buyers
├── More compelling competitive differentiator
└── Cost: £10,000–£25,000+ depending on scope

Recommendation: Start with Type I.
Don't let "we'll eventually need Type II" become a reason to do nothing.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The companies that get removed from procurement aren't removed because their security is catastrophically bad. They're removed because they can't demonstrate it.&lt;/p&gt;

&lt;h3&gt;
  
  
  WCAG 2.1 AA — Don't Leave This Last
&lt;/h3&gt;

&lt;p&gt;WCAG 2.1 AA is required for most public sector sales and increasingly expected by large enterprise buyers. Building it in from the start is a fraction of the cost of retrofitting.&lt;/p&gt;

&lt;p&gt;Quick automated audit to run immediately:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Run a free WCAG audit with axe-core CLI&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @axe-core/cli

&lt;span class="c"&gt;# Audit your product URL&lt;/span&gt;
axe https://yourproduct.com &lt;span class="nt"&gt;--tags&lt;/span&gt; wcag2a,wcag2aa

&lt;span class="c"&gt;# Output: list of violations by severity&lt;/span&gt;
&lt;span class="c"&gt;# Fix critical failures first, document your remediation progress&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;AI-Specific Compliance (If Applicable)&lt;/p&gt;

&lt;p&gt;If you're selling AI-powered products into enterprise markets, standard compliance isn't enough. Procurement teams are now adding AI-specific questions to their standard checklists:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# AI Vendor Security Addendum — Questions You'll Be Asked&lt;/span&gt;
&lt;span class="p"&gt;
1.&lt;/span&gt; What AI models does your product use, and under what terms?
&lt;span class="p"&gt;2.&lt;/span&gt; Is customer data used to train or fine-tune models?
&lt;span class="p"&gt;3.&lt;/span&gt; Where is data processed when passed to an LLM provider?
&lt;span class="p"&gt;4.&lt;/span&gt; What happens to customer data in the event of a breach at your LLM provider?
&lt;span class="p"&gt;5.&lt;/span&gt; Do you have a model governance policy?
&lt;span class="p"&gt;6.&lt;/span&gt; How do you handle AI-generated outputs that may be inaccurate?

→ "We use OpenAI" is not an answer.
→ A documented policy is.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Real-World Impact&lt;/p&gt;

&lt;p&gt;A head of product at an early-stage HR tech company told us their single biggest growth inflection came not from a new feature or a pricing change, but from completing their SOC 2 Type I and publishing it on their security page. Inbound enterprise enquiries that had previously stalled at procurement started converting. Deals that had "gone quiet" were reopened. The product hadn't changed. Their ability to pass the filter had.&lt;/p&gt;

&lt;p&gt;A technical co-founder at a 12-person B2B analytics firm targeting financial services ran the opposite experiment — not intentionally, but observationally. They tracked every deal that stalled or went dark over a nine-month period and did a post-mortem on the ones they could get information on. Roughly half had hit a procurement wall. Most cited either missing SOC 2 documentation or an incomplete DPA process.&lt;/p&gt;

&lt;p&gt;Their quote: &lt;em&gt;"We thought we were losing on price. We were losing before price was ever discussed."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Key Takeaways&lt;/p&gt;

&lt;p&gt;Compliance is a sales qualification tool for enterprise buyers — it happens before the product evaluation, not during it. If you're not compliant, you may never get the conversation.&lt;/p&gt;

&lt;p&gt;The real cost of non-compliance is invisible deal loss, not regulatory fines. Deals that never progress don't show up as losses — they show up as silence.&lt;/p&gt;

&lt;p&gt;In regulated verticals, compliance is a competitive moat. Most smaller vendors haven't cleared it, which means clearing it reduces your effective competition materially.&lt;/p&gt;

&lt;p&gt;Getting to a credible compliance posture is faster than founders assume. A focused sprint — documented policies, a DPA template, basic security evidence — can move you from "can't pass procurement" to "can pass procurement" in weeks, not years.&lt;/p&gt;

&lt;p&gt;If you're building for enterprise or EU markets, compliance isn't something you earn the right to think about later.** It's the entry ticket. The cost of getting it isn't the cost of doing it — it's the cost of not having done it six months ago.&lt;/p&gt;

&lt;p&gt;How Context First AI Can Help&lt;/p&gt;

&lt;p&gt;At Context First AI, compliance sits within our &lt;strong&gt;Stack pillar&lt;/strong&gt; — the part of our platform concerned with the technical and operational infrastructure that allows AI-assisted businesses to grow with credibility.&lt;/p&gt;

&lt;p&gt;We provide:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Frameworks for assessing your current compliance posture&lt;/li&gt;
&lt;li&gt;Practical templates for the documentation enterprise procurement teams ask for&lt;/li&gt;
&lt;li&gt;Guidance on sequencing compliance investments for maximum commercial impact&lt;/li&gt;
&lt;li&gt;A community of CTOs and technical leads who've navigated SOC 2, GDPR readiness, and enterprise security reviews firsthand&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Context First AI exists to help you get ahead of that curve — not after the deal is lost, but before the questionnaire arrives.&lt;/p&gt;

&lt;p&gt;Conclusion&lt;/p&gt;

&lt;p&gt;There's a version of this story that plays out well, and a version that doesn't. In the version that doesn't, a well-built product with genuine commercial potential sits on the wrong side of a procurement filter — not because the engineering was bad, not because the team wasn't capable, but because the paperwork wasn't in order when the opportunity arrived.&lt;/p&gt;

&lt;p&gt;In the version that does, a founder made a deliberate decision six months earlier that looked like overhead at the time and turned out to be the thing that got them into the room.&lt;/p&gt;

&lt;p&gt;If you're building for enterprise or EU, that decision is in front of you right now. The questionnaire is coming. The only question is whether you'll be ready to answer it.&lt;/p&gt;

&lt;p&gt;Resources&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://ico.org.uk/for-organisations/uk-gdpr-guidance-and-resources/" rel="noopener noreferrer"&gt;[ICO GDPR Guidance for Organisations]&lt;/a&gt; — UK Information &lt;br&gt;
Commissioner's Office practical guidance on GDPR obligations and DPAs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.aicpa-cima.com/topic/audit-assurance/audit-and-assurance-greater-than-soc-2" rel="noopener noreferrer"&gt;[AICPA SOC 2 Overview]&lt;/a&gt; — Authoritative resource on SOC 2 requirements and the audit process&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.w3.org/WAI/WCAG21/quickref/" rel="noopener noreferrer"&gt;[W3C WCAG 2.1 Quick Reference]&lt;/a&gt; — Complete filterable reference for Web Content Accessibility Guidelines&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Created with AI assistance and reviewed by a human author. Originally published at [&lt;a href="https://contextfirstai.com" rel="noopener noreferrer"&gt;Context First AI&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>infosec</category>
      <category>saas</category>
      <category>security</category>
      <category>startup</category>
    </item>
  </channel>
</rss>
