<?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: HoverBot</title>
    <description>The latest articles on DEV Community by HoverBot (hoverbot).</description>
    <link>https://dev.to/hoverbot</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.us-east-2.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F14652%2Febe4d7ec-d533-45ec-ba8c-935b3fa625c5.png</url>
      <title>DEV Community: HoverBot</title>
      <link>https://dev.to/hoverbot</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hoverbot"/>
    <language>en</language>
    <item>
      <title>A Shopper’s Price Limit Belongs in Retrieval, Not the Reply</title>
      <dc:creator>Vitaly Goncharenko</dc:creator>
      <pubDate>Mon, 12 Oct 2026 08:12:17 +0000</pubDate>
      <link>https://dev.to/hoverbot/a-shoppers-price-limit-belongs-in-retrieval-not-the-reply-n28</link>
      <guid>https://dev.to/hoverbot/a-shoppers-price-limit-belongs-in-retrieval-not-the-reply-n28</guid>
      <description>&lt;p&gt;A shopper says “under $700.” The catalogue search finds six good matches, but the cheapest is $749. The assistant can write a perfect sentence about budget-friendly choices and still be wrong. The mistake happened before it wrote a word.&lt;/p&gt;

&lt;p&gt;Product search often starts with the nouns in a message: snowboard, jacket, desk chair. A price phrase can be reduced to background context while a keyword search returns plausible products. Once those products reach the reply model, asking it to “respect the budget” is a weak repair. The shortlist has already broken the shopper’s rule.&lt;/p&gt;

&lt;h2&gt;
  
  
  Treat the Ceiling as Part of the Query
&lt;/h2&gt;

&lt;p&gt;Separate the request into product meaning and hard constraints. The product meaning helps rank relevant matches. The ceiling limits which matches are eligible at all. Apply the limit in the catalogue query where the source supports it; otherwise filter the retrieved candidates before ranking and answer generation. Do not let relevance put an over-budget item back into the answer.&lt;/p&gt;

&lt;p&gt;This is an ordinary catalogue capability, not a prompt trick. &lt;a href="https://shopify.dev/docs/api/storefront/latest/input-objects/ProductFilter" rel="noopener noreferrer"&gt;Shopify’s product filter&lt;/a&gt; includes a price range, and its &lt;a href="https://shopify.dev/docs/api/storefront/latest/input-objects/pricerangefilter" rel="noopener noreferrer"&gt;range definition&lt;/a&gt; has an explicit maximum. A chatbot can use the same principle even when its store has a different search interface: carry the ceiling as structured search input, then verify what came back.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check the Item That Can Be Bought
&lt;/h2&gt;

&lt;p&gt;A product card may say “from $649,” while the size or finish the shopper wants costs more. &lt;a href="https://shopify.dev/docs/api/storefront/latest/objects/ProductPriceRange" rel="noopener noreferrer"&gt;Shopify distinguishes a product’s minimum and maximum variant prices&lt;/a&gt;. That distinction matters in conversation: a qualifying starting price does not make every variant eligible.&lt;/p&gt;

&lt;p&gt;Before naming a choice, check the actual available variant and the currency in which its price is shown. Keep sale and regular prices distinct. If the assistant cannot identify a purchasable choice inside the ceiling, it should not hide behind the product’s lowest possible price. This is the approach we use in HoverBot: the catalogue decides eligibility, while chat explains the eligible choices.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make No Match an Honest Answer
&lt;/h2&gt;

&lt;p&gt;An empty result is information. Say that nothing currently matches the product request within the budget. Offer to change the ceiling or another preference, but let the shopper make that choice. Quietly showing a near miss turns a stated constraint into an undisclosed suggestion.&lt;/p&gt;

&lt;p&gt;Test the boundary, not just the prose. Place products just below and above a ceiling. Add one product whose variants straddle it and another that is unavailable. Follow every route the assistant uses to search, refine and recommend. Inspect both the retrieved shortlist and the final answer. If either contains an item outside the limit, the conversation has not kept its promise.&lt;/p&gt;

&lt;p&gt;Originally published at &lt;a href="https://www.hoverbot.ai/blog/price-cap-catalog-chat" rel="noopener noreferrer"&gt;https://www.hoverbot.ai/blog/price-cap-catalog-chat&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>chatbot</category>
    </item>
    <item>
      <title>A Chat Booking Is Not Confirmed Until the Calendar Says So</title>
      <dc:creator>Vitaly Goncharenko</dc:creator>
      <pubDate>Thu, 08 Oct 2026 05:25:00 +0000</pubDate>
      <link>https://dev.to/hoverbot/a-chat-booking-is-not-confirmed-until-the-calendar-says-so-gpf</link>
      <guid>https://dev.to/hoverbot/a-chat-booking-is-not-confirmed-until-the-calendar-says-so-gpf</guid>
      <description>&lt;p&gt;The calendar record, not the chatbot’s wording, decides whether an appointment exists.&lt;/p&gt;

&lt;p&gt;A booking reply is a commit acknowledgement, not a writing task. If the calendar has not accepted the appointment, the chatbot cannot truthfully say it is booked.&lt;/p&gt;

&lt;p&gt;The failure is easy to create. A visitor asks for Tuesday afternoon. The assistant offers a time and writes, “You are booked.” Meanwhile the calendar request times out. The customer arrives expecting a slot that the business cannot see. The words were coherent; the state was wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  Separate the Choice From the Commit
&lt;/h2&gt;

&lt;p&gt;Conversation is useful for gathering the service, location, preferred time, and necessary contact details. It can explain available choices in plain language. But an offered time is provisional until the booking system accepts it. Availability can change between the question and the write.&lt;/p&gt;

&lt;p&gt;Make that boundary visible. Before the write, say the time is available to request. After a successful write, return the confirmed time, time zone, and reference. If the write fails, say the booking did not complete. If the result is unknown, say it is unconfirmed while the system checks. Never use the same confirmation sentence for all three states.&lt;/p&gt;

&lt;p&gt;Both &lt;a href="https://developers.google.com/workspace/calendar/api/guides/create-events" rel="noopener noreferrer"&gt;Google Calendar&lt;/a&gt; and &lt;a href="https://learn.microsoft.com/en-us/graph/api/user-post-events?view=graph-rest-1.0" rel="noopener noreferrer"&gt;Microsoft Graph&lt;/a&gt; create an event through an authenticated write and return an event resource. That resource, not the assistant's prose, is the evidence of a committed appointment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Retry the Same Intent, Not a New Booking
&lt;/h2&gt;

&lt;p&gt;A timeout does not reveal whether the first write succeeded. Blindly sending another create request can produce two bookings. Give the customer intent a stable identity, check for an existing result, and let a retry continue that same attempt. Google Calendar describes caller-supplied event IDs as one way to keep a local record in sync and avoid duplicates after an ambiguous result. Stripe documents the same general principle for safe request retries with an idempotency key.&lt;/p&gt;

&lt;p&gt;The exact mechanism depends on the booking provider. The design requirement does not: one customer request should lead to at most one committed reservation. If the provider cannot support that guarantee, reconcile the calendar before speaking as though the retry succeeded.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep Changes Attached to the Original Record
&lt;/h2&gt;

&lt;p&gt;Booking is a lifecycle, not a single chat turn. A customer may reschedule or cancel. Those actions need to find the original reservation, check the new conditions, commit the change, and report the resulting state. A conversational “done” with no changed record leaves the operator and customer with different versions of the appointment.&lt;/p&gt;

&lt;p&gt;This is the pattern we use in HoverBot: let chat gather and explain, but let a durable booking record decide what can be confirmed. It trades a little conversational speed for a clear answer to the question that matters: where can the business see and change this appointment?&lt;/p&gt;

&lt;p&gt;Test the awkward paths before trusting the happy one. Make the calendar write fail. Let it succeed while the response times out. Retry the same request. Ask to reschedule a booking that no longer exists. At each point, compare the transcript with the durable record. If they disagree, the assistant must stop promising and hand the case to a person.&lt;/p&gt;

&lt;p&gt;Originally published at &lt;a href="https://www.hoverbot.ai/blog/chat-booking-confirmation" rel="noopener noreferrer"&gt;https://www.hoverbot.ai/blog/chat-booking-confirmation&lt;/a&gt;&lt;/p&gt;

</description>
      <category>chatbot</category>
      <category>customersupport</category>
      <category>webdev</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Close the Loop: Chatbot Analytics That Turn Misses Into Fixes</title>
      <dc:creator>Vitaly Goncharenko</dc:creator>
      <pubDate>Thu, 08 Oct 2026 03:08:12 +0000</pubDate>
      <link>https://dev.to/hoverbot/close-the-loop-chatbot-analytics-that-turn-misses-into-fixes-2hj7</link>
      <guid>https://dev.to/hoverbot/close-the-loop-chatbot-analytics-that-turn-misses-into-fixes-2hj7</guid>
      <description>&lt;p&gt;Many chatbots stall for the same reason. Unanswered questions build up and nothing changes. Teams ship a release and move on. Users try again and give up. The way out is simple. Treat every miss as a signal. Capture it in a standard way. Decide whether it was noise or a real gap. Turn real gaps into small updates in guardrails or knowledge. Run that loop every week. Measure how fast it moves. This gives the team a way to test whether focused fixes help before changing models.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with lean instrumentation
&lt;/h2&gt;

&lt;p&gt;Analytics only works if the trail is short and consistent. Capture the user message, the decision the assistant made, the sources it consulted, the final answer, and any fallback it used. Record time to first token and time to full answer. This gives a clear picture of what happened and why. Long logs feel thorough but slow teams down. A compact record gets read and acted on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Define unanswered with clear rules
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The question is in scope and relevant, yet the reply has no supporting citation or source&lt;/li&gt;
&lt;li&gt;A fallback was needed to finish the turn such as clarify, retrieve, or hand off&lt;/li&gt;
&lt;li&gt;Confidence is below your threshold or the reply uses hedging language like "not sure" or "I think"&lt;/li&gt;
&lt;li&gt;The user reasks the same thing within a short window&lt;/li&gt;
&lt;li&gt;Retrieval returns nothing useful or cannot locate the expected document&lt;/li&gt;
&lt;li&gt;The reply conflicts with the current knowledge base&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do not count out of scope or non relevant messages as unanswered. Those belong to the guardrail stream. Use one rule set across teams so the dashboard stays trusted.&lt;/p&gt;

&lt;h2&gt;
  
  
  What guardrails really are
&lt;/h2&gt;

&lt;p&gt;Guardrails are the decision layer that determines whether a request should be answered, how it should be answered, or declined. They protect scope, safety, policy, and data hygiene before the model spends tokens. They can be rules, a policy engine, an ML classifier, or a hybrid.&lt;/p&gt;

&lt;p&gt;Keep them alive by sampling borderline cases each week, correcting mistakes, adding examples, and tracking false blocks and false allows so thresholds stay fair.&lt;/p&gt;

&lt;h2&gt;
  
  
  Separate noise from real gaps
&lt;/h2&gt;

&lt;p&gt;Not every miss deserves work. First filter out non relevant items such as spam, off topic questions, and test phrases. These belong to guardrail improvement. Then focus on relevant but unanswered questions. These are in scope, they matter to users, and they did not receive a grounded answer. This is the signal that drives action.&lt;/p&gt;

&lt;h2&gt;
  
  
  Run a weekly improvement loop
&lt;/h2&gt;

&lt;p&gt;Set a steady rhythm. Review the unanswered queue once a week. Group similar questions into clusters. Choose a remedy for each cluster. If the assistant should not answer, strengthen guardrails and improve the decline message. If the assistant should answer, add a short article or update the knowledge that powers retrieval.&lt;/p&gt;

&lt;p&gt;Publish each change with a one line note on what moved and why. Check the same clusters the next week to confirm they dropped. The goal is movement, not perfection.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep ownership tight
&lt;/h2&gt;

&lt;p&gt;Assign a single owner for each stream and metric. Product owns unanswered rate and time to first fix. Content owns missing or stale knowledge. Engineering owns guardrails, routing, and fallbacks. Keep the meeting short by design.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make privacy part of the loop
&lt;/h2&gt;

&lt;p&gt;Analytics does not need raw personal data. Mask names and identifiers before storage. Keep customers separated by tenant. Set a retention window that matches policy and delete on schedule. Log who viewed and who changed what.&lt;/p&gt;

&lt;h2&gt;
  
  
  Measure what leaders care about
&lt;/h2&gt;

&lt;p&gt;A focused dashboard keeps attention on outcomes. Put these on the top row:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unanswered rate&lt;/li&gt;
&lt;li&gt;Time to first fix&lt;/li&gt;
&lt;li&gt;Acceptance rate&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Add flow and coverage next:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Route mix&lt;/li&gt;
&lt;li&gt;Retrieval coverage&lt;/li&gt;
&lt;li&gt;Average latency&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What good looks like after a month
&lt;/h2&gt;

&lt;p&gt;After a month, look for repeat gaps that declined after a documented fix. Check whether new questions appeared, whether the assistant stayed within its defined scope, and whether people reached the next step. Attribute an improvement only when the underlying conversations support it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Weekly loop agenda
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Review top line metrics for five minutes&lt;/li&gt;
&lt;li&gt;Open the unanswered queue&lt;/li&gt;
&lt;li&gt;Cluster similar questions&lt;/li&gt;
&lt;li&gt;Decide fix for each cluster&lt;/li&gt;
&lt;li&gt;Assign owner and date&lt;/li&gt;
&lt;li&gt;Publish a one line change log&lt;/li&gt;
&lt;li&gt;Confirm next week that the cluster dropped&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>rag</category>
    </item>
    <item>
      <title>How Chatbots Remember: Short Term, Long Term and Everything in Between</title>
      <dc:creator>Vitaly Goncharenko</dc:creator>
      <pubDate>Wed, 07 Oct 2026 02:55:26 +0000</pubDate>
      <link>https://dev.to/hoverbot/how-chatbots-remember-short-term-long-term-and-everything-in-between-d99</link>
      <guid>https://dev.to/hoverbot/how-chatbots-remember-short-term-long-term-and-everything-in-between-d99</guid>
      <description>&lt;p&gt;Product teams are adding memory to AI assistants to improve continuity and personalization. Memory is not a single feature but a layered system. Designed well, it can improve continuity and trust. Designed poorly, it creates drift, privacy risk and cost.&lt;/p&gt;

&lt;h2&gt;
  
  
  What memory is and is not
&lt;/h2&gt;

&lt;p&gt;Chatbots do not retain everything by default. Models operate within a finite context window. Once that window fills, older turns drop out. Anything worth carrying forward must be deliberately persisted by the application. Teams decide what to save, how long to keep it, and when to reuse it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The four layer model
&lt;/h2&gt;

&lt;p&gt;A useful design treats memory as a stack of cooperating layers. Short term memory is the working context. It is a rolling set of recent turns that sustains coherence but fades fast. Episodic memory captures each conversation as a concise session note with goals, decisions and open items so future sessions start informed without replaying everything. Long term memory stores durable facts and preferences, retrieved with a mix of keyword and semantic search. It is powerful and therefore selective and consent driven. Procedural memory holds rules and guardrails. These are standing instructions a bot must always follow. They are kept versioned and auditable rather than transient.&lt;/p&gt;

&lt;h3&gt;
  
  
  Short term memory: the working context
&lt;/h3&gt;

&lt;p&gt;Short term memory is the rolling conversation window. It maintains coherence within a single session by keeping recent turns in the model's context. When the window fills, older exchanges drop out on a first-in-first-out basis. This layer handles immediate follow-ups, pronoun resolution, and topic continuity.&lt;/p&gt;

&lt;p&gt;Design for short term memory is about context management. Keep the window large enough for natural conversation flow but small enough to avoid diluting important information. Include system messages and guardrails that must always be present. Use compression techniques for longer conversations, such as summarizing older turns while preserving key facts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Episodic memory: session summaries
&lt;/h3&gt;

&lt;p&gt;Episodic memory captures the essence of each conversation session. When a conversation ends, the system generates a structured summary containing the user's goals, decisions made, actions taken, and open items. This summary enables future sessions to start with context without replaying the entire conversation history.&lt;/p&gt;

&lt;p&gt;Effective episodic memory focuses on outcomes rather than transcripts. Instead of storing "user asked about pricing then said thanks," store "user interested in enterprise plan, needs custom quote, follow up scheduled." This approach can reduce storage and make the summary easier to retrieve.&lt;/p&gt;

&lt;h3&gt;
  
  
  Long term memory: durable facts and preferences
&lt;/h3&gt;

&lt;p&gt;Long term memory persists user preferences, account details, and behavioral patterns across many sessions. This layer can support continuity, but only when storage and reuse are appropriate. Retrieval combines keyword matching for exact facts with semantic search for related concepts.&lt;/p&gt;

&lt;p&gt;Long term memory requires careful curation. Not every user statement deserves permanent storage. Focus on explicit preferences, confirmed facts, and repeated behaviors. Implement consent mechanisms and expiration policies. Tag entries with confidence levels and sources for later validation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Procedural memory: rules and guardrails
&lt;/h3&gt;

&lt;p&gt;Procedural memory contains the rules, policies, and guardrails that govern bot behavior. Unlike other memory types, procedural memory is not learned from user interactions but is explicitly configured and versioned. This includes safety rules, business policies, escalation triggers, and compliance requirements.&lt;/p&gt;

&lt;p&gt;Procedural memory must be reliable and auditable. Version all rule changes, test them in staging environments, and maintain clear rollback procedures. Load the current rules for each conversation and test that revisions behave as intended.&lt;/p&gt;

&lt;h2&gt;
  
  
  Design guidelines for production
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Collect less by default.&lt;/strong&gt; Persist only what moves outcomes. Avoid full transcripts without a legal need. Focus on actionable insights, confirmed preferences, and resolved decisions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gate write backs.&lt;/strong&gt; Admit data only when relevant to likely future tasks, non sensitive, consented and tagged with a time to live.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Give users control.&lt;/strong&gt; Provide a memory center to view, delete or disable. Enforce tenant and regional boundaries.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Budget tokens and time.&lt;/strong&gt; Prevent short term context from crowding out rules or citations. Track p50 and p95 latency.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Log decisions.&lt;/strong&gt; Record why an item was stored, which policy allowed it, and when it will expire or be revoked.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scorecard to watch
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Recall accuracy on planted facts across sessions&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Harmful retention rate which should approach zero&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Deflection and first contact resolution lift&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Token and latency deltas at p50 and p95 after enabling memory&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;User sentiment that it remembers me without feeling intrusive&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Further reading: &lt;a href="https://developers.openai.com/api/docs/guides/conversation-state" rel="noopener noreferrer"&gt;OpenAI conversation state&lt;/a&gt;, &lt;a href="https://developers.openai.com/api/docs/guides/retrieval" rel="noopener noreferrer"&gt;OpenAI retrieval&lt;/a&gt;, and &lt;a href="https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:32016R0679" rel="noopener noreferrer"&gt;GDPR text&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>architecture</category>
      <category>chatbots</category>
    </item>
    <item>
      <title>From APIs to Skills: The New Way to Integrate Your Product with AI Agents and Your Website</title>
      <dc:creator>Vitaly Goncharenko</dc:creator>
      <pubDate>Tue, 06 Oct 2026 03:06:45 +0000</pubDate>
      <link>https://dev.to/hoverbot/from-apis-to-skills-the-new-way-to-integrate-your-product-with-ai-agents-and-your-website-3o0g</link>
      <guid>https://dev.to/hoverbot/from-apis-to-skills-the-new-way-to-integrate-your-product-with-ai-agents-and-your-website-3o0g</guid>
      <description>&lt;p&gt;If you have ever run an integration project, you know the routine: API docs, SDK setup, auth scopes, edge cases, and more time than anyone estimated. That model is still important. But there is now a new layer on top of it: agent skills.&lt;/p&gt;

&lt;p&gt;In ecosystems like &lt;a href="https://openclaw.ai" rel="noopener noreferrer"&gt;OpenClaw&lt;/a&gt;, assistants can install skills from registries such as &lt;a href="https://clawhub.ai" rel="noopener noreferrer"&gt;ClawHub&lt;/a&gt; and use them to read data or trigger actions inside products. In plain language, integration is becoming installable for assistants, not only for developers.&lt;/p&gt;

&lt;p&gt;For product teams, that changes the question. It is no longer only "How do users navigate our UI?" It is also "How can an assistant help users finish useful tasks in our product safely?"&lt;/p&gt;

&lt;h2&gt;
  
  
  The integration model that is quietly changing
&lt;/h2&gt;

&lt;p&gt;Traditional integrations assume a human is clicking through screens. Even many chatbots are really just another front-end layer.&lt;/p&gt;

&lt;p&gt;Skills flip that assumption.&lt;/p&gt;

&lt;p&gt;A skill is basically a small contract an assistant can follow. In the OpenClaw ecosystem, ClawHub packages are usually text based, often a &lt;code&gt;SKILL.md&lt;/code&gt; plus supporting files. They can be published, versioned, and discovered more like an app marketplace than a static API directory.&lt;/p&gt;

&lt;p&gt;That creates a different pattern:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your product exposes a narrow set of capabilities, like reading records, creating updates, or running one workflow.&lt;/li&gt;
&lt;li&gt;You package those capabilities into a skill with clear inputs, outputs, and safety rules.&lt;/li&gt;
&lt;li&gt;The assistant decides when to call the skill and how to combine it with other skills.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So instead of sending users through five screens, an assistant can handle requests like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is the status of the last five invoices?&lt;/li&gt;
&lt;li&gt;Which customers are at risk?&lt;/li&gt;
&lt;li&gt;Draft a reply using our policy, then log the ticket.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why this matters for customer experience
&lt;/h2&gt;

&lt;p&gt;User expectations are shifting from navigation to outcomes.&lt;/p&gt;

&lt;p&gt;When skills are available, people do not need to remember where a report lives, which menu controls a setting, or how to manually stitch systems together. They ask in plain language, and the assistant does the routing.&lt;/p&gt;

&lt;p&gt;For SaaS teams, this opens two distribution paths:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Assistant-first discovery:&lt;/strong&gt; users install your skill when they need a capability, similar to plugin discovery.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Embedded conversational UX:&lt;/strong&gt; you deliver the same outcome directly on your website or in-product experience.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The second path needs a different runtime from the skill itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where HoverBot fits: turning agent capability into website conversation
&lt;/h2&gt;

&lt;p&gt;OpenClaw skills are excellent for connecting assistants to tools. But most businesses still need a customer-facing layer: branded chat UI, guided flows, knowledge ingestion, analytics, and operational controls.&lt;/p&gt;

&lt;p&gt;HoverBot is built for that layer, so teams can launch and manage website chatbots quickly without building custom conversation infrastructure from scratch.&lt;/p&gt;

&lt;p&gt;A practical bridge between both worlds is to expose narrow, authenticated setup tools and document their safe use in a skill. The skill can guide an assistant through configuration, while HoverBot runs the deployed customer conversation.&lt;/p&gt;

&lt;p&gt;Instead of treating installation as one opaque action, define each setup step, required permission, and approval boundary explicitly. The assistant can then guide the operator without becoming the customer-facing chatbot itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  A concrete pattern: setup skill plus chatbot runtime
&lt;/h2&gt;

&lt;p&gt;In practice, the handoff can look like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An operator asks the assistant to configure a website conversational flow.&lt;/li&gt;
&lt;li&gt;The skill supplies the setup instructions and the assistant invokes only the allowed tools.&lt;/li&gt;
&lt;li&gt;HoverBot runs the live, customer-facing chatbot after deployment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the bigger opportunity: skills are not only integrations. With the right platform behind them, they become repeatable deployment paths for product teams.&lt;/p&gt;

&lt;h2&gt;
  
  
  The hard part: trust, safety, and the skills supply chain
&lt;/h2&gt;

&lt;p&gt;Skills are powerful because they touch real systems. That is also where risk shows up.&lt;/p&gt;

&lt;p&gt;Security teams have already flagged malicious skill scenarios in open registries, which makes skill installation a new supply-chain surface.&lt;/p&gt;

&lt;p&gt;The model still works, but mature teams add guardrails:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install from trusted publishers whenever possible.&lt;/li&gt;
&lt;li&gt;Pin versions and review changelogs instead of defaulting to latest.&lt;/li&gt;
&lt;li&gt;Keep each skill narrow with explicit scopes and least privilege.&lt;/li&gt;
&lt;li&gt;Add human approval for high-impact actions like payments, deletes, or exports.&lt;/li&gt;
&lt;li&gt;Log every important step: requested action, invoked tool, and resulting change.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Treat skills the same way you treat production dependencies, not quick prompt snippets.&lt;/p&gt;

&lt;h2&gt;
  
  
  A practical playbook to ship your first skill
&lt;/h2&gt;

&lt;p&gt;If you want to enter the assistant ecosystem without overbuilding, start small and ship one useful workflow first.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Choose one weekly workflow users already repeat, like status lookup or ticket creation.&lt;/li&gt;
&lt;li&gt;Expose only what is required behind auth you already trust (token, OAuth, or service account).&lt;/li&gt;
&lt;li&gt;Return structured outputs so assistants do not need to guess fields.&lt;/li&gt;
&lt;li&gt;Document like a product: prerequisites, examples, known failure modes.&lt;/li&gt;
&lt;li&gt;Publish, version, and improve on a clear release cadence.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If customer-facing conversation is part of your goal, add the second layer: use a chatbot runtime such as HoverBot for the on-site experience while a reviewed skill documents any assistant-operated setup and configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  The takeaway
&lt;/h2&gt;

&lt;p&gt;APIs are not going anywhere. But skills are becoming one of the fastest ways to create assistant-ready product experiences because they compress integration, onboarding, and UX into one installable capability.&lt;/p&gt;

&lt;p&gt;A practical starting point is one narrow, reversible setup workflow with explicit permissions, structured outputs, logs, and human approval before any high-impact change.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.openclaw.ai/tools/skills" rel="noopener noreferrer"&gt;Skills&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.openclaw.ai/clawhub" rel="noopener noreferrer"&gt;ClawHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/openclaw/clawhub/blob/main/docs/skill-format.md" rel="noopener noreferrer"&gt;Skill format&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://genai.owasp.org/llmrisk/llm062025-excessive-agency/" rel="noopener noreferrer"&gt;LLM06:2025 Excessive Agency&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.openclaw.ai/security/THREAT-MODEL-ATLAS/persistence" rel="noopener noreferrer"&gt;Persistence (AML.TA0006)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>chatbot</category>
      <category>automation</category>
    </item>
    <item>
      <title>The Agent Layer for Chat Widgets: How to Stay Useful in an Agentic Web</title>
      <dc:creator>Vitaly Goncharenko</dc:creator>
      <pubDate>Mon, 05 Oct 2026 00:33:51 +0000</pubDate>
      <link>https://dev.to/hoverbot/the-agent-layer-for-chat-widgets-how-to-stay-useful-in-an-agentic-web-10d2</link>
      <guid>https://dev.to/hoverbot/the-agent-layer-for-chat-widgets-how-to-stay-useful-in-an-agentic-web-10d2</guid>
      <description>&lt;p&gt;Agentic browsing changes a simple assumption: your site is no longer navigated only by humans. More sessions start with an assistant already in the browser, reading the page, summarising it, and trying to finish a task on the user's behalf.&lt;/p&gt;

&lt;p&gt;That matters for chat widgets because they sit at the intersection of three things agents need: context, intent, and execution. A widget can answer questions, but it can also route to live systems, trigger workflows, and enforce policy. In an agentic web, that makes the widget less like a support bubble and more like a site's safest control surface.&lt;/p&gt;

&lt;p&gt;We already wrote about &lt;a href="https://www.hoverbot.ai/blog/agentic-web-arriving" rel="noopener noreferrer"&gt;the agentic web arriving&lt;/a&gt;. This is the practical follow up: what to change in your chatbot widget so it works with agents instead of competing with them, and so advanced tasks can be completed without fragile UI scraping.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why agents struggle with normal widgets
&lt;/h2&gt;

&lt;p&gt;Most chat widgets were built for humans who will read an answer and then click around. Agents behave differently. They arrive with a job in mind: check stock, compare plans, book a demo, start a return, open a ticket. If the site does not offer a clean path, the agent will guess by reading HTML, clicking buttons, and trying form flows like a user would.&lt;/p&gt;

&lt;p&gt;That approach is brittle. Websites change. A/B tests move buttons. Product details are split across tabs, tooltips, PDFs, and dynamic components. Even when the agent is correct, you cannot easily audit why it made a decision or what data it used.&lt;/p&gt;

&lt;p&gt;There is also a safety issue. In agentic browsing, the agent is constantly exposed to untrusted content. If your only interface is "read the page and act," you increase the odds of an agent being misled by misleading page text, stale UI, or adversarial instructions embedded in content.&lt;/p&gt;

&lt;p&gt;The fix is not to make the agent smarter. The fix is to give it a safer interface.&lt;/p&gt;

&lt;h2&gt;
  
  
  The agent layer, explained simply
&lt;/h2&gt;

&lt;p&gt;The agent layer is a small, practical upgrade to the widget. It does not require new standards, and it does not require publishing secrets. It just makes three things explicit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First&lt;/strong&gt;, the widget needs to declare what it can do and what rules it follows. Agents should not have to infer capability by trial and error. They should be able to discover, quickly, whether the widget supports tasks like creating a ticket or scheduling a demo, what languages it supports, and what actions require confirmation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Second&lt;/strong&gt;, the widget should respond with structure, not only prose. Humans want a paragraph. Agents need the facts separated from the explanation: key entities found, confidence signals, suggested next steps, and whether a sensitive action requires user confirmation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Third&lt;/strong&gt;, the widget should offer controlled actions instead of encouraging UI automation. When something must be done (a ticket created, a booking scheduled, an inventory query run) it should happen through an approved action path that enforces permissions, privacy, and auditing on the server.&lt;/p&gt;

&lt;p&gt;That is the agent layer in one sentence: discoverable capabilities, structured answers, controlled actions.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this enables for real chatbot use cases
&lt;/h2&gt;

&lt;p&gt;Once the widget becomes agent ready, you unlock workflows that are hard to do reliably through page text alone.&lt;/p&gt;

&lt;p&gt;A common example is &lt;strong&gt;product support&lt;/strong&gt;. The user asks about a warranty edge case, a compatibility rule, or a policy detail. The page rarely contains the full answer. A RAG-powered widget can answer from documentation, but the agent also needs to know what to do next. A structured response can suggest a safe next step: offer to open a ticket, ask for confirmation, and collect only the minimum details.&lt;/p&gt;

&lt;p&gt;Another example is &lt;strong&gt;inventory and pricing&lt;/strong&gt;. Agents scraping the UI can misread availability labels and miss the difference between "in stock at this site" and "ships in three days." A widget with a controlled inventory action can return live results, scoped correctly to tenant and site, with a clear explanation for the user.&lt;/p&gt;

&lt;p&gt;A third example is &lt;strong&gt;lead capture and scheduling&lt;/strong&gt;. Agents can fill forms, but it is error prone and often breaks. A controlled booking action gives you a stable flow, consistent validation, and clean attribution in analytics.&lt;/p&gt;

&lt;p&gt;In each case, the agent gets a reliable interface. The business gets fewer broken flows and more traceability.&lt;/p&gt;

&lt;h2&gt;
  
  
  How this maps to HoverBot's existing capabilities
&lt;/h2&gt;

&lt;p&gt;HoverBot already has the internal parts that make an agent layer valuable.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It can answer using RAG knowledge bases built from files, text, and URLs.&lt;/li&gt;
&lt;li&gt;It can apply guardrails via classification to block disallowed or out of scope requests.&lt;/li&gt;
&lt;li&gt;It can detect and mask PII around model calls.&lt;/li&gt;
&lt;li&gt;It can keep audit logs, session monitoring, and analytics.&lt;/li&gt;
&lt;li&gt;And it supports multi-tenant configuration with modular skills like lead generation and product support.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The agent layer does not replace these pieces. It makes them accessible in a way agents can use safely.&lt;/p&gt;

&lt;p&gt;If you strip away the terminology, the practical change is this: the widget stops being just UI and becomes a small contract that says, "here is what I'm responsible for, here is what I'm allowed to do, and here is the safe way to do it."&lt;/p&gt;

&lt;h2&gt;
  
  
  The part teams underestimate: bot to bot coordination
&lt;/h2&gt;

&lt;p&gt;On many sites, the user will soon have two assistants visible: the browser's agent panel and the site's chat widget. If both behave like primary copilots, the experience turns noisy. The user gets duplicated answers, conflicting suggestions, and aggressive popups fighting for attention.&lt;/p&gt;

&lt;p&gt;An agent-ready widget should be able to switch behaviour when an agent is present. In practice, that means it becomes less chatty in the UI and more cooperative in the interface. It can still serve the human, but it should also work as a stable endpoint for the agent to call.&lt;/p&gt;

&lt;p&gt;This is not about surrendering the relationship to the browser. It is about preventing collisions and keeping control of execution on your side.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agent-readable hints, not hidden metadata
&lt;/h2&gt;

&lt;p&gt;A lot of teams talk about hidden metadata because they want a way to pass extra context to agents. The safer framing is: publish agent-readable hints that are safe to expose, and keep everything privileged behind authentication and policy checks.&lt;/p&gt;

&lt;p&gt;The capability description should never include secrets. It can say what actions exist and what confirmation rules apply. It should not contain internal API keys, private URLs, or anything you would not want seen by a crawler.&lt;/p&gt;

&lt;p&gt;The power comes from what happens after discovery: actions are executed on the server under your controls, with short-lived tokens and tenant-level permissions. That is where privacy and security are enforced.&lt;/p&gt;

&lt;h2&gt;
  
  
  A practical rollout that stays small
&lt;/h2&gt;

&lt;p&gt;The fastest path is to start with one tenant and a narrow scope, then expand.&lt;/p&gt;

&lt;p&gt;Pick one &lt;strong&gt;read workflow&lt;/strong&gt; and one &lt;strong&gt;do workflow&lt;/strong&gt;. A read workflow is something like policy answers with citations. A do workflow is something like creating a ticket or scheduling a callback, with confirmation required. Once those two are stable, add one more action that saves users time, such as checking availability or retrieving order status, depending on your product.&lt;/p&gt;

&lt;p&gt;The key is restraint. An agent layer works best when it is small, explicit, and maintained like an API contract. If you publish 40 actions, you will maintain 40 actions. If you publish five, you will likely ship five that actually work.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bottom line
&lt;/h2&gt;

&lt;p&gt;Agentic browsers will make the web feel more task driven. That shift will reward sites that provide agents a reliable interface, and it will punish sites that force agents to guess from the DOM.&lt;/p&gt;

&lt;p&gt;For chat widgets, the answer is not a redesign. It is a thin agent layer: make capabilities discoverable, return structured outputs, and execute actions through controlled pathways with guardrails, PII protection, and auditing.&lt;/p&gt;

&lt;p&gt;In other words, treat your widget as the safest agent API your site can offer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://cheatsheetseries.owasp.org/cheatsheets/AI_Agent_Security_Cheat_Sheet.html" rel="noopener noreferrer"&gt;OWASP AI Agent Security Cheat Sheet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://cheatsheetseries.owasp.org/cheatsheets/LLM_Prompt_Injection_Prevention_Cheat_Sheet.html" rel="noopener noreferrer"&gt;OWASP Prompt Injection Prevention Cheat Sheet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://spec.openapis.org/oas/" rel="noopener noreferrer"&gt;OpenAPI Specification&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>architecture</category>
      <category>chatbot</category>
    </item>
    <item>
      <title>Data Privacy in AI Chatbots: 2026 Regulatory Update</title>
      <dc:creator>Vitaly Goncharenko</dc:creator>
      <pubDate>Sun, 04 Oct 2026 00:37:04 +0000</pubDate>
      <link>https://dev.to/hoverbot/data-privacy-in-ai-chatbots-2026-regulatory-update-2f4g</link>
      <guid>https://dev.to/hoverbot/data-privacy-in-ai-chatbots-2026-regulatory-update-2f4g</guid>
      <description>&lt;p&gt;A chat widget is not just another contact form. Every turn can leave your perimeter, reach a model vendor, and create another retained record. That is where regulators are looking in 2026. Your legal team will want to know what leaves, what stays, and what you can prove.&lt;/p&gt;

&lt;p&gt;This is an engineering and operations guide, not legal advice. Use it to prepare the architecture, controls, and evidence your counsel will review before launch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Chatbots Trigger Extra Scrutiny
&lt;/h2&gt;

&lt;p&gt;A contact form sends one message. A chatbot sends every turn to an inference pipeline. The route may cross borders, and the vendor may retain the prompt. Users paste order numbers, account details, and health information even when you never ask for them. That combination draws scrutiny, including when the bot only answers FAQs.&lt;/p&gt;

&lt;p&gt;Legal reviews keep returning to three obligations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Lawful basis and notice.&lt;/strong&gt; Tell users that the bot is automated, what data it processes, and who receives that data, including subprocessors.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Data minimisation.&lt;/strong&gt; Send only what the model needs for the answer. Mask or remove the rest before inference.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Transfer and retention.&lt;/strong&gt; The inference route and the vendor's retention settings must match your privacy policy and contractual safeguards.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  GDPR: What Enforcement Looks Like Now
&lt;/h2&gt;

&lt;p&gt;GDPR did not get a chatbot-specific rewrite in 2026. Supervisory authorities are applying the existing rules more tightly to generative AI:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Transparency.&lt;/strong&gt; Your layered notice must cover automated processing and point to retention periods for conversation logs and model vendors.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Data Protection Impact Assessments.&lt;/strong&gt; A customer-facing bot that handles personal data routinely triggers a DPIA before launch. Do not wait for an incident.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Subprocessor registers.&lt;/strong&gt; List LLM providers, embedding services, and hosting regions in your Article 30 record with the same detail you use for your CRM.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Right to erasure.&lt;/strong&gt; If you keep conversations, define how you will delete a user's thread and the analytics derived from it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The architecture has to support the policy. Our &lt;a href="https://www.hoverbot.ai/resources/white-papers/pii-masking-architecture" rel="noopener noreferrer"&gt;PII masking architecture white paper&lt;/a&gt; covers ways to keep personal data inside your perimeter. The &lt;a href="https://www.hoverbot.ai/blog/protecting-pii-ai-chatbots" rel="noopener noreferrer"&gt;PII masking patterns for customer-facing chatbots&lt;/a&gt; article provides the technical walkthrough.&lt;/p&gt;

&lt;h2&gt;
  
  
  Singapore PDPA: Transfer and Accountability
&lt;/h2&gt;

&lt;p&gt;HoverBot is headquartered in Singapore. PDPA is our home regime, and two parts matter directly to a chatbot review in 2026:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Transfer Limitation Obligation.&lt;/strong&gt; Prompts sent to an overseas LLM vendor require comparable protection. That puts standard contractual clauses and vendor due diligence in your launch work.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Accountability.&lt;/strong&gt; PDPC expects documented policies, not checked boxes. Your data inventory should show what enters the bot, what gets masked, and what you store.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;a href="https://www.hoverbot.ai/trust-center" rel="noopener noreferrer"&gt;Trust Center&lt;/a&gt; lists HoverBot's active GDPR and PDPA controls, with SOC 2 Type II certification in progress. Use it as the live control list. It is not a substitute for your own review.&lt;/p&gt;

&lt;h2&gt;
  
  
  US State Laws: A Patchwork, Not One Rule
&lt;/h2&gt;

&lt;p&gt;The United States still has no single federal AI privacy statute. State privacy laws and emerging AI transparency bills overlap instead:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Consumer privacy laws&lt;/strong&gt; in California, Colorado, Virginia, and other states require disclosure of automated decision-making. They also give consumers opt-out rights where profiling is involved.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;AI transparency bills&lt;/strong&gt; in several states require notice when a user interacts with an AI system. Some also require documentation of training data sources for high-risk uses.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Sector rules&lt;/strong&gt; still sit on top: HIPAA for covered entities, GLBA for financial services, and FERPA in education.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a US-facing ecommerce bot, the operating rule is plain. Disclose the automation. Minimise what reaches the model. Keep a vendor map your legal team can update when a state adds a requirement.&lt;/p&gt;

&lt;h2&gt;
  
  
  PII Handling Patterns That Auditors Expect
&lt;/h2&gt;

&lt;p&gt;A privacy policy cannot repair the wrong data flow. Build these patterns into the production path:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Detect before inference.&lt;/strong&gt; Run entity recognition on the user's message. Mask the tokens before the prompt leaves your infrastructure.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Scope by topic.&lt;/strong&gt; Use topic boundaries and content filters so the bot does not solicit data it does not need for catalog or policy answers.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Escalate with context.&lt;/strong&gt; When confidence drops, route the conversation to a human. Do not let the model guess on a sensitive thread.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Separate logs.&lt;/strong&gt; Keep masked transcripts for analytics. Vault or discard raw PII according to your retention policy.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Vendor zero-retention where available.&lt;/strong&gt; Negotiate zero data retention on eligible API tiers. Record every exception in the subprocessor register.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;HoverBot's guardrails layer makes masking, topic boundaries, and confidence-based escalation configurable. The &lt;a href="https://www.hoverbot.ai/resources/feature-deep-dives/guardrails-and-pii-masking" rel="noopener noreferrer"&gt;guardrails and PII masking deep dive&lt;/a&gt; shows how to tune those controls.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pre-Launch Compliance Checklist
&lt;/h2&gt;

&lt;p&gt;A customer-facing bot does not ship until this gate is complete:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Privacy notice updated&lt;/strong&gt; to cover bot processing, subprocessors, and retention.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;DPIA completed&lt;/strong&gt; for the intended use case and data categories, or the exemption is documented.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Data flow diagram&lt;/strong&gt; traces a message from the widget through masking, retrieval, inference, logging, and escalation.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Masking rules tested&lt;/strong&gt; against realistic transcripts, including a user who pastes a credit card or account number.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Erasure procedure&lt;/strong&gt; covers conversation logs and the analytics derived from them.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Human handoff path&lt;/strong&gt; covers out-of-scope and low-confidence requests.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Vendor agreements&lt;/strong&gt; cover retention, training use, and cross-border transfer terms.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the longer regulatory mapping, read the &lt;a href="https://www.hoverbot.ai/resources/white-papers/privacy-compliance-ai-chatbots" rel="noopener noreferrer"&gt;privacy compliance for AI chatbots white paper&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Audit Readiness: Evidence, Not Intentions
&lt;/h2&gt;

&lt;p&gt;Auditors and enterprise buyers ask for artifacts, not intentions. Keep this evidence current:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  A signed subprocessor list with regions and data categories&lt;/li&gt;
&lt;li&gt;  A sample masked transcript that shows what the model actually saw&lt;/li&gt;
&lt;li&gt;  A configuration export of guardrails, topic boundaries, and escalation thresholds&lt;/li&gt;
&lt;li&gt;  An incident response runbook for a suspected PII leak or vendor breach&lt;/li&gt;
&lt;li&gt;  A change log for every shift in policy, model, or retention setting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Refresh the evidence whenever you change the model vendor, hosting region, or logging policy. January's approval does not cover September's configuration. A vendor retention change can put the bot outside the terms legal reviewed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where HoverBot Fits
&lt;/h2&gt;

&lt;p&gt;HoverBot manages AI chatbots for production customer conversations. It grounds answers in a company's catalog, policies, and documentation through retrieval-augmented generation. It masks personal data before the model sees it and escalates to a human when confidence drops. One configuration can deploy the same knowledge base to a website widget and WhatsApp Business. HoverBot was founded in 2024 and is headquartered in Singapore.&lt;/p&gt;

&lt;p&gt;Put the controls in front of your legal team before launch. &lt;a href="https://www.hoverbot.ai/trust-center" rel="noopener noreferrer"&gt;Visit the Trust Center&lt;/a&gt; for current compliance status, or &lt;a href="https://www.hoverbot.ai/request-demo" rel="noopener noreferrer"&gt;request a demo&lt;/a&gt; to see masking and guardrails on your content.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.hoverbot.ai/request-demo" rel="noopener noreferrer"&gt;Request a demo&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>privacy</category>
      <category>security</category>
      <category>webdev</category>
    </item>
    <item>
      <title>A Privacy Policy Is Not a Chatbot Info Card</title>
      <dc:creator>Vitaly Goncharenko</dc:creator>
      <pubDate>Fri, 02 Oct 2026 00:41:49 +0000</pubDate>
      <link>https://dev.to/hoverbot/a-privacy-policy-is-not-a-chatbot-info-card-e4o</link>
      <guid>https://dev.to/hoverbot/a-privacy-policy-is-not-a-chatbot-info-card-e4o</guid>
      <description>&lt;p&gt;Decide what a customer needs to know before the first message, then put it beside the chat box. If the answer is buried in a privacy policy, the customer has to leave the conversation, find the right clause, and translate legal language before deciding whether to continue.&lt;/p&gt;

&lt;p&gt;That is too much work for a five-second decision. A chatbot info card gives support leaders a practical alternative: one short reference for what the bot can do, where it may be wrong, what happens to conversation data, and how to report a problem.&lt;/p&gt;

&lt;p&gt;Singapore's Infocomm Media Development Authority sets out this pattern in its &lt;a href="https://www.imda.gov.sg/-/media/imda/file/emerging-technologies-and-research/artificial-intelligence/transparency-guidelines-for-generative-ai-chatbots.pdf" rel="noopener noreferrer"&gt;Transparency Guidelines for Generative AI Chatbots&lt;/a&gt;. The guidelines are voluntary. They do not impose obligations or replace duties under other laws or sector rules. What they offer is an operator-friendly structure for telling people what matters at the moment it matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Gap a Privacy Policy Cannot Close
&lt;/h2&gt;

&lt;p&gt;A privacy policy answers only part of the customer's question. It may explain which data is collected, who receives it, and how long it is kept. It rarely says whether the bot can check current stock, whether it may give an incorrect answer, which questions need a human, or where to report a bad response.&lt;/p&gt;

&lt;p&gt;Those are operating decisions, not legal footnotes. A shopper deciding whether to trust a returns answer needs them in one scan. A support manager also needs one maintained source of truth instead of four different pages owned by legal, product, security, and customer service.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The distinction:&lt;/strong&gt; the privacy policy holds the full legal detail. The info card summarises the practical choices a user must make before and during the conversation, then links to the policy for more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Answer Four Questions, Not Every Question
&lt;/h2&gt;

&lt;p&gt;IMDA encourages at least one substantive disclosure in each of four areas. For a customer-service chatbot, that becomes a manageable editorial checklist:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;What can this chatbot do?&lt;/strong&gt; Name the tasks it handles and the boundaries that matter. “Answers questions from our published shipping and returns information” is useful. “Your intelligent shopping assistant” is not.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;How reliable and safe is it?&lt;/strong&gt; State the important limitation in plain language. If answers can be wrong or out of date, say so. If prices, stock, medical, legal, or financial decisions need verification, make the next step explicit.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;How is conversation data used and protected?&lt;/strong&gt; Summarise what is collected, who can access it, whether it is used for model training, and what controls the user has. Link to the privacy policy for retention periods and full terms.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;How can someone report a problem?&lt;/strong&gt; Give a real channel and set an expectation. Explain what kinds of issues can be raised and what acknowledgement or follow-up the user should expect.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The bar is specificity. “We take safety seriously” gives a customer nothing to act on. “This chatbot can make factual errors; verify important product, price, and policy information before relying on it” changes behaviour.&lt;/p&gt;

&lt;h2&gt;
  
  
  Place the Decision Before the Conversation
&lt;/h2&gt;

&lt;p&gt;A perfect page that nobody sees is not useful disclosure. IMDA encourages a high-level safety statement and a clearly identifiable link to the info card at first use, before the customer starts chatting. The card should remain reachable from within the interface afterward.&lt;/p&gt;

&lt;p&gt;For most teams, that does not require a new consent flow or a long modal. A short sentence near the opening prompt and a persistent information link can do the job. The linked page can use headings, bullets, and expandable sections so customers see the essentials first and supporting detail when they want it.&lt;/p&gt;

&lt;p&gt;Use the same core card across web and mobile when the bot behaves the same way. If capabilities or data practices differ by channel, name the differences instead of making the customer guess which version they are using.&lt;/p&gt;

&lt;h2&gt;
  
  
  Give the Card an Owner and a Review Trigger
&lt;/h2&gt;

&lt;p&gt;The page becomes operational only when someone owns it. Put one support or product leader on the review, record the last-updated date, and define the changes that reopen it: a new model, a new capability, a material guardrail change, a new data use, or an unexpected customer use case.&lt;/p&gt;

&lt;p&gt;Do not wait for an annual policy review when a meaningful change happens in the meantime. Equally, do not create busywork for routine infrastructure changes that do not alter behaviour or safety. The question is simple: would this change affect how a reasonable customer decides to use the chatbot?&lt;/p&gt;

&lt;h2&gt;
  
  
  A One-Hour Review for Support Leaders
&lt;/h2&gt;

&lt;p&gt;Open the chatbot as a first-time customer and run this review with support, product, and whoever owns privacy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Can a customer tell what the chatbot is for before sending a message?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can they find one concrete limitation or precaution?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can they understand the main data practice without reading the full privacy policy?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can they reach a person or reporting channel when something goes wrong?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Can the team name who updates this information after a meaningful change?&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Any “no” is a drafting task, not a reason to add another generic disclaimer. Start with the four answers, write them in the language your support team already uses with customers, and cut every sentence that does not change a decision.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where HoverBot Fits
&lt;/h2&gt;

&lt;p&gt;HoverBot helps teams ground customer conversations in their own catalogue, policies, and documentation, while keeping a clear path to human support. The same operating discipline applies to transparency: define the answerable scope, make the limits visible, and keep the customer in control of what happens next.&lt;/p&gt;

&lt;p&gt;Review the first-use experience in your current chatbot, then &lt;a href="https://www.hoverbot.ai/request-demo" rel="noopener noreferrer"&gt;request a demo&lt;/a&gt; to see how grounded answers and human handoff can fit your support workflow.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>privacy</category>
      <category>chatbot</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Your Chatbot Answered the Question the User Already Left</title>
      <dc:creator>Vitaly Goncharenko</dc:creator>
      <pubDate>Thu, 01 Oct 2026 00:38:26 +0000</pubDate>
      <link>https://dev.to/hoverbot/your-chatbot-answered-the-question-the-user-already-left-3gaj</link>
      <guid>https://dev.to/hoverbot/your-chatbot-answered-the-question-the-user-already-left-3gaj</guid>
      <description>&lt;p&gt;A stale answer is not a latency bug. It is a state ownership bug.&lt;/p&gt;

&lt;p&gt;Picture a shopper asking for blue running shoes, then quickly changing the request to black walking shoes. The first search is harder and finishes last. If the chat interface accepts both results, the blue running shoes appear beneath the newer question. Every answer may be grounded in real catalogue data, yet the conversation is still wrong.&lt;/p&gt;

&lt;p&gt;This failure is easy to miss in development because requests often finish in the order they started. Real networks, caches, retrieval paths, and model calls do not preserve that order. The older request may hit a slow search branch while the newer one finds a cached result. Correctness therefore cannot depend on arrival order.&lt;/p&gt;

&lt;h2&gt;
  
  
  Give Every Visible Turn One Owner
&lt;/h2&gt;

&lt;p&gt;The active turn needs an identity that changes whenever the user changes the work. A new message obviously starts a new turn. So can selecting a different product, changing a filter, editing the question, switching conversation, closing the widget, or navigating to a page where the old answer no longer applies.&lt;/p&gt;

&lt;p&gt;Starting new work should revoke the old turn's right to update the interface. This is the key rule. It is stronger than hiding a loading indicator and more precise than checking whether the component still exists. The application is asking one question at the commit boundary: does this result still belong to the state the user can see?&lt;/p&gt;

&lt;p&gt;React's guidance for fetching inside an effect makes the same requirement explicit. Cleanup should abort the fetch or ignore its result so an irrelevant response cannot keep affecting the application. The principle applies beyond React. Any client that launches asynchronous conversation work needs a cleanup boundary when its inputs change.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cancel the Work, Then Guard the Commit
&lt;/h2&gt;

&lt;p&gt;Use two protections because they solve different parts of the problem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First, cancel obsolete work.&lt;/strong&gt; When a turn loses ownership, signal every operation that can stop. MDN documents that aborting can stop a fetch request, response-body consumption, and streams that observe the signal. Carry that cancellation through retrieval, ranking, and answer generation where the surrounding services support it. This saves network, compute, and database work that can no longer help the user.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Second, reject obsolete results.&lt;/strong&gt; Cancellation is cooperative. A cache lookup may finish before it sees the signal. An intermediary may buffer the response. A downstream service may not support cancellation at all. Before changing the transcript, product cards, citations, or suggested actions, compare the result's owner with the active turn. If ownership changed, discard the result.&lt;/p&gt;

&lt;p&gt;The ownership check is the correctness boundary. Cancellation is the efficiency boundary. Using only the first wastes work. Using only the second leaves a gap where late data can still render.&lt;/p&gt;

&lt;h2&gt;
  
  
  Streaming Makes the Race More Visible
&lt;/h2&gt;

&lt;p&gt;A single late response produces one obvious jump. A stale stream can interleave fragments with the current answer, which is worse. It can append text to the wrong bubble, restore an old progress label, or attach product cards after the user has moved to another topic.&lt;/p&gt;

&lt;p&gt;Treat the stream, its partial text, and its final structured result as one owned operation. When ownership changes, stop reading the stream and clear only the pending state that belongs to it. Do not let old cleanup remove the newer turn's indicator. Each visible mutation needs the same ownership test as the final answer.&lt;/p&gt;

&lt;p&gt;This is the approach HoverBot uses for interruptible conversation work: cancellation follows the obsolete request, while the active turn remains the only state allowed to commit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cancellation Is Not Failure
&lt;/h2&gt;

&lt;p&gt;A shopper who changes their mind has not caused an incident. Cancellation is an expected terminal state, alongside success, timeout, failure, and a valid empty result. Keeping those states separate improves both the interface and the operational record.&lt;/p&gt;

&lt;p&gt;The interface should usually remove an obsolete pending answer without showing an error. The telemetry should record that the work was cancelled and why, without counting it as an outage or retrieval failure. A timeout still deserves different handling because the user waited for work that the system could not finish in time.&lt;/p&gt;

&lt;p&gt;Be careful with actions that have side effects. Cancelling a request does not undo a mutation that a server already committed. Product search and answer generation can often be abandoned safely. An order change, refund, or message send needs an idempotency key, a known commit boundary, and confirmation of the resulting state. Interface cancellation is not transaction rollback.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test the Order You Do Not Expect
&lt;/h2&gt;

&lt;p&gt;A happy-path test will not expose this bug. Make the first request deliberately slower than the second. Change topics several times. Close the widget while retrieval is running. Cancel during a stream. Simulate a dependency that ignores the cancellation signal. In every case, only the current owner may update the visible conversation.&lt;/p&gt;

&lt;p&gt;Also test cleanup against the newer request. The old operation must not hide the current loading state, clear its partial answer, or overwrite its error. Ownership protects removal as well as addition.&lt;/p&gt;

&lt;p&gt;The practical rule is small enough to remember: new intent revokes old ownership. Stop obsolete work where possible, and make late results prove they still belong before they touch the screen. That turns unpredictable completion order from a customer-facing contradiction into an ordinary, controlled part of asynchronous chat.&lt;/p&gt;

&lt;p&gt;Want to see a catalogue conversation handle topic changes without stale answers? &lt;a href="https://www.hoverbot.ai/request-demo" rel="noopener noreferrer"&gt;Request a demo&lt;/a&gt; and try interrupting the flow yourself.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  [Request a demo](https://www.hoverbot.ai/request-demo)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>frontend</category>
    </item>
    <item>
      <title>System One Models for Chatbot Decisions: Testing Jev for PII, Guardrails and Product Selection</title>
      <dc:creator>Vitaly Goncharenko</dc:creator>
      <pubDate>Fri, 25 Sep 2026 02:57:20 +0000</pubDate>
      <link>https://dev.to/hoverbot/system-one-models-for-chatbot-decisions-testing-jev-for-pii-guardrails-and-product-selection-2k5e</link>
      <guid>https://dev.to/hoverbot/system-one-models-for-chatbot-decisions-testing-jev-for-pii-guardrails-and-product-selection-2k5e</guid>
      <description>&lt;p&gt;A chatbot needs language generation, but much of the work around that generation is classification. Does this message contain personal information? Is a draft reply safe to send? Which retrieved product best matches the request? Should the conversation go to support?&lt;/p&gt;

&lt;p&gt;Those questions do not require another paragraph of generated text. They require a value that software can inspect and use. This is the problem TypeSafe AI positions Jev to solve. TypeSafe calls Jev its first public System One model and describes the interface as unstructured state in, typed probabilistic decisions out. Its &lt;a href="https://typesafe.ai/blog/introducing-system-one-models-and-jev" rel="noopener noreferrer"&gt;launch announcement&lt;/a&gt; says Jev gives up string generation in favor of structured outputs.&lt;/p&gt;

&lt;p&gt;HoverBot is evaluating that pattern. We made seven synthetic test calls on September 25, 2026. The messages were invented and contained no customer data. Every request returned HTTP 200 with the expected answer, taking 0.67 to 0.82 seconds end to end from Singapore, including network time. This was a smoke test of the API shape. It was not an accuracy benchmark, a latency benchmark or evidence of production performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Most chatbot decisions are classification, not writing
&lt;/h2&gt;

&lt;p&gt;The visible reply is only one part of a product aware chat pipeline. Before generation, software may inspect the message for sensitive data and select an intent route. After retrieval, it may rank a shortlist. After generation, it may test the draft against safety and commercial rules. At any point, it may decide that a human should take over.&lt;/p&gt;

&lt;p&gt;An LLM can perform these tasks, but the application usually has to request JSON, validate the schema and decide how to handle malformed or ambiguous output. TypeSafe says Jev is built around predefined answer types instead. Its public &lt;a href="https://api.typesafe.ai/docs" rel="noopener noreferrer"&gt;API reference&lt;/a&gt; documents a POST request to &lt;code&gt;https://api.typesafe.ai/v1/systemone&lt;/code&gt; with &lt;code&gt;state&lt;/code&gt; and &lt;code&gt;questions&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Jev returns
&lt;/h2&gt;

&lt;p&gt;The TypeSafe API documents three answer families: &lt;code&gt;noul&lt;/code&gt; for a probability, &lt;code&gt;choice&lt;/code&gt; for one option from named criteria, and &lt;code&gt;score&lt;/code&gt; for a position on a defined scale. The unusual word &lt;code&gt;noul&lt;/code&gt; appears in the direct TypeSafe API. Vercel uses the more familiar name &lt;code&gt;boolean&lt;/code&gt; in its gateway interface.&lt;/p&gt;

&lt;p&gt;Here is the reduced shape of our positive PII test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"jev-latest"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"state"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hi, my order hasnt arrived. I am Anna Lim, phone +65 9123 4567, card ending 4242."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"questions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"has_pii"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"noul"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"instructions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Does this message contain personal data such as a name, phone number, email, address or payment details?"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response identified model version &lt;code&gt;jev-1.13.0&lt;/code&gt; and returned:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"answers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"has_pii"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"noul"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"noul"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.99&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That value is not a policy by itself. Application code must convert it into an action through a threshold and an uncertainty path.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Check for PII before the LLM
&lt;/h2&gt;

&lt;p&gt;A PII check belongs early in the pipeline, before a message is copied into prompts, logs or downstream tools. In our synthetic positive example, Jev returned &lt;code&gt;0.99&lt;/code&gt;. For the invented message, “Do you have the linen shirt in size M, and is it machine washable?”, it returned &lt;code&gt;0.02&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A simple policy might redact or block messages at or above &lt;code&gt;0.90&lt;/code&gt;, pass messages below &lt;code&gt;0.20&lt;/code&gt;, and send the middle band to a stricter detector or human review. Those numbers are illustrations, not recommended universal thresholds. Missing PII can have a much higher cost than pausing an ordinary product question, so the threshold should reflect the data flow and legal context.&lt;/p&gt;

&lt;p&gt;Detection is only one layer. The pipeline still needs minimization, retention controls and clear boundaries around what reaches external models. Our guides to &lt;a href="https://www.hoverbot.ai/blog/protecting-pii-ai-chatbots" rel="noopener noreferrer"&gt;protecting PII&lt;/a&gt; and &lt;a href="https://www.hoverbot.ai/blog/data-privacy-ai-chatbots-2026-update" rel="noopener noreferrer"&gt;chatbot data privacy&lt;/a&gt; cover that wider system.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Apply guardrails to draft replies
&lt;/h2&gt;

&lt;p&gt;Guardrails can inspect an LLM draft before the customer sees it. Our synthetic risky draft prescribed “800mg of ibuprofen three times a day” while selling a posture cushion. One call asked two independent questions: whether the reply gave medical advice and whether it recommended a competitor.&lt;/p&gt;

&lt;p&gt;Jev returned &lt;code&gt;0.99&lt;/code&gt; for medical advice and &lt;code&gt;0.03&lt;/code&gt; for a competitor recommendation. A clean draft about shipping in two to four days and a 30 day return window returned &lt;code&gt;0.01&lt;/code&gt; for both checks.&lt;/p&gt;

&lt;p&gt;The useful pattern is specific checks rather than one vague “Is this safe?” question. Each check can have a different consequence. A high medical advice probability could block the draft and request a rewrite. A competitor mention might trigger review or an approved comparison flow. The check evaluates the provided text. It does not prove that shipping or return statements are factually correct, so those claims still need grounding in trusted business data.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Pick from a retrieved catalog shortlist
&lt;/h2&gt;

&lt;p&gt;A product decision model should not search an entire catalog from memory. Retrieval should first produce a current shortlist with relevant attributes. The decision step can then select among known identifiers.&lt;/p&gt;

&lt;p&gt;Our synthetic shopper wanted road running shoes for a half marathon, mentioned mild overpronation and had a budget near 150 dollars. The four candidates included a trail shoe, a stability road shoe, a neutral carbon racer and a walking shoe. Jev chose &lt;code&gt;sku_road_stability&lt;/code&gt;, the 140 dollar road shoe with stability support, and returned a probability map over all four identifiers.&lt;/p&gt;

&lt;p&gt;This keeps the output inside the retrieved set. It does not validate inventory, price or product specifications. Those fields must come from the catalog source, and the final reply should cite or reflect that source. See our approach to &lt;a href="https://www.hoverbot.ai/blog/knowledge-management-ai-chatbots" rel="noopener noreferrer"&gt;knowledge management for AI chatbots&lt;/a&gt; and &lt;a href="https://www.hoverbot.ai/blog/progress-streaming-catalog-chat" rel="noopener noreferrer"&gt;catalog chat progress streaming&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Route intent and estimate buying intent
&lt;/h2&gt;

&lt;p&gt;One request can answer several related questions. For the invented message, “do you ship to Singapore and how much would 3 of the blue ones cost?”, we asked for an intent choice and a buying intent probability.&lt;/p&gt;

&lt;p&gt;The intent options were product question, order status, complaint and other. Jev selected &lt;code&gt;product_question&lt;/code&gt; and returned &lt;code&gt;0.89&lt;/code&gt; for buying intent. The router could use the choice to fetch shipping and pricing information. The buying signal could alter which actions are offered, but it should not be treated as proof that a purchase will happen.&lt;/p&gt;

&lt;p&gt;The option definitions matter. Overlapping labels create ambiguous supervision and unstable routing. Include a fallback, log the probability distribution and review examples where the top choices are close.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Score human handoff urgency
&lt;/h2&gt;

&lt;p&gt;Escalation is often better represented as a scale than a yes or no flag. Our test defined three levels: no handoff needed, offer a human as an option, and hand off to a human now.&lt;/p&gt;

&lt;p&gt;The synthetic customer said this was the third request, the refund had not arrived, the bot kept repeating the same FAQ link, and a person was wanted immediately. Jev returned score &lt;code&gt;2.0&lt;/code&gt;, mapped to immediate handoff, with probabilities for every level.&lt;/p&gt;

&lt;p&gt;Real routing should combine that score with operational facts such as agent availability, account status and support hours. A model score can prioritize a queue, but it should not silently deny access to a person when policy promises human support.&lt;/p&gt;

&lt;h2&gt;
  
  
  Set thresholds around the cost of mistakes
&lt;/h2&gt;

&lt;p&gt;A probability becomes useful only when connected to a policy. Start by naming the two mistakes for each question. For PII, they are letting sensitive data through and interrupting a safe message. For guardrails, they are sending a harmful draft and blocking an acceptable reply.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Choose an automatic action threshold using labelled examples from the real traffic domain.&lt;/li&gt;
&lt;li&gt;Create a middle band for uncertainty. Route borderline cases to a human, a deterministic rule or an LLM with more context.&lt;/li&gt;
&lt;li&gt;Measure calibration. Among cases scored near 0.80, the positive rate should be examined rather than assumed.&lt;/li&gt;
&lt;li&gt;Set thresholds independently for each use case. PII, buying intent and handoff urgency carry different costs.&lt;/li&gt;
&lt;li&gt;Monitor drift when products, policies, markets or customer language change.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;TypeSafe says Jev returns probabilities so software can account for uncertainty. That is a product claim, not a substitute for measuring calibration on the population where the chatbot will operate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Limits, and where an LLM is still needed
&lt;/h2&gt;

&lt;p&gt;Jev does not write replies. TypeSafe explicitly presents it as a decision model rather than a text generator. The company also describes inputs as unstructured data, with its published examples centered on text and structured program state. Treat each API call as self contained: send the relevant conversation state again, because the request shape does not provide chatbot memory.&lt;/p&gt;

&lt;p&gt;An LLM is still useful for composing a clear response, asking a tactful follow up question, summarizing a long exchange or explaining a recommendation. Jev can decide which route or candidate to use, while ordinary code constrains actions and an LLM handles language.&lt;/p&gt;

&lt;p&gt;Availability also matters. TypeSafe described Jev as early access in its September 15, 2026 announcement. Separately, &lt;a href="https://vercel.com/changelog/ai-gateway-now-supports-typesafe-clients-and-http-api-for-jev" rel="noopener noreferrer"&gt;Vercel says&lt;/a&gt; its AI Gateway added Jev support on September 21, 2026 through a TypeSafe client, HTTP API and AI SDK. Check current access and terms before planning a rollout.&lt;/p&gt;

&lt;h2&gt;
  
  
  Evaluate on labelled data before switching
&lt;/h2&gt;

&lt;p&gt;Seven obvious synthetic cases can confirm that requests serialize, responses parse and answer types fit the pipeline. They cannot show performance on typos, indirect language, conflicting evidence, multilingual conversations or adversarial input.&lt;/p&gt;

&lt;p&gt;Build a representative dataset from properly governed, labelled examples. Freeze question instructions and candidate definitions. Split threshold selection from final evaluation. For each use case, report a confusion matrix, precision, recall, review rate and calibration by probability band. For choices, inspect both top choice accuracy and near ties. For scores, measure costly under escalation separately from harmless adjacent errors.&lt;/p&gt;

&lt;p&gt;Then run the candidate beside the existing decision path without allowing it to affect customers. Compare disagreements, investigate failure clusters and test degraded behavior for timeouts or unavailable service. Switch only when the measured tradeoff meets the policy for that specific decision.&lt;/p&gt;

&lt;h2&gt;
  
  
  A short practical rule
&lt;/h2&gt;

&lt;p&gt;Use a decision model when the acceptable outputs can be named before the call. Use ordinary code to enforce policy, retrieve authoritative data and execute actions. Use an LLM when the chatbot needs to write, explain or continue an open ended conversation. When the probability is borderline, escalate instead of pretending uncertainty is certainty.&lt;/p&gt;

&lt;p&gt;Want to see how decision checks fit into a product-aware chatbot? &lt;a href="https://www.hoverbot.ai/request-demo" rel="noopener noreferrer"&gt;Request a demo&lt;/a&gt; and we will walk through guardrails and PII handling.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.hoverbot.ai/request-demo" rel="noopener noreferrer"&gt;Request a demo&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Showing the Work: Progress Streaming for Catalog-Backed Chat</title>
      <dc:creator>Vitaly Goncharenko</dc:creator>
      <pubDate>Fri, 18 Sep 2026 02:41:30 +0000</pubDate>
      <link>https://dev.to/hoverbot/showing-the-work-progress-streaming-for-catalog-backed-chat-2lc</link>
      <guid>https://dev.to/hoverbot/showing-the-work-progress-streaming-for-catalog-backed-chat-2lc</guid>
      <description>&lt;p&gt;When a catalog-backed chatbot takes more than a second to answer, silence reads as failure. The fix is not making retrieval faster. It is streaming which stage is running so the user knows the system is working.&lt;/p&gt;

&lt;p&gt;This post describes a design we are committing to for HoverBot catalog skills: six named progress stages, a capability-gated SSE transport that degrades to a plain JSON call, an absolute wall-clock deadline, &lt;code&gt;AbortSignal&lt;/code&gt; cancellation, and five explicit stream outcomes. The design is in &lt;a href="https://github.com/HoverBotAI/hoverbot/pull/3" rel="noopener noreferrer"&gt;open PR #3&lt;/a&gt; and &lt;a href="https://github.com/HoverBotAI/hoverbot/pull/6" rel="noopener noreferrer"&gt;open PR #6&lt;/a&gt;, and is not live in production yet. Alexander Khomenko authored the implementation in commit &lt;code&gt;a6d8ac3c&lt;/code&gt; across hoverbot-api, hoverbot-config-ui, and hoverbot-widget.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Status:&lt;/strong&gt; Planned behaviour, not shipped. &lt;a href="https://github.com/HoverBotAI/hoverbot/pull/3" rel="noopener noreferrer"&gt;PR #3&lt;/a&gt; and &lt;a href="https://github.com/HoverBotAI/hoverbot/pull/6" rel="noopener noreferrer"&gt;PR #6&lt;/a&gt; in the hoverbot repo are still open. Treat everything below as the contract we intend to merge, not what you will see on hoverbot.ai today.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Silence Fails Before Search Does
&lt;/h2&gt;

&lt;p&gt;Catalog retrieval is a multi-step pipeline. The orchestrator interprets the user's message, resolves product references from prior turns, calls a search backend, validates returned SKUs, ranks candidates, and only then assembles a response. Each step can add hundreds of milliseconds to several seconds depending on catalog size, query complexity, and backend load.&lt;/p&gt;

&lt;p&gt;Users do not experience that as a pipeline. They experience a chat bubble with a typing indicator that never changes. &lt;a href="https://www.nngroup.com/articles/response-times-3-important-limits/" rel="noopener noreferrer"&gt;Nielsen Norman Group's response-time research&lt;/a&gt; identifies one second as the threshold where flow breaks and ten seconds as the point where attention is lost. A catalog query that finishes in four seconds is fast enough to be correct and slow enough to feel broken if the UI says nothing.&lt;/p&gt;

&lt;p&gt;The instinct is to optimize latency. That is worth doing, but it does not solve the perception problem. Even a well-tuned retrieval can spike when a user asks a comparison question across three product lines with constraint filters. You cannot guarantee sub-second answers for every catalog turn. You can guarantee the user sees which stage is running.&lt;/p&gt;

&lt;p&gt;This connects to the broader knowledge-retrieval picture in &lt;a href="https://www.hoverbot.ai/blog/knowledge-management-ai-chatbots" rel="noopener noreferrer"&gt;knowledge management for AI chatbots&lt;/a&gt;: retrieval quality depends on what you fetch, but retrieval UX depends on whether the user waits with context or waits in the dark.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Six Stages
&lt;/h2&gt;

&lt;p&gt;Progress updates are typed against a fixed stage list. No free-form status strings from the backend; the adapter and widget agree on six values:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CATALOG_PROGRESS_STAGES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;interpreting&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="s1"&gt;resolving_reference&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="s1"&gt;retrieving&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="s1"&gt;validating&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="s1"&gt;ranking&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="s1"&gt;building_response&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;CatalogProgressUpdate&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;stage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CatalogProgressStage&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;detail&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;elapsedMs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&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;Each stage maps to a user-facing message in the chat controller:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;interpreting:&lt;/strong&gt; Understanding your request. The orchestrator parses intent, constraints, and search mode before touching the catalog.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;resolving_reference:&lt;/strong&gt; Resolving the products you mentioned. Handles ordinals ("the second one"), pronouns, and context handoff from prior turns.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;retrieving:&lt;/strong&gt; Searching the catalog. The HTTP adapter calls the search backend. This is usually the longest stage.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;validating:&lt;/strong&gt; Checking product information. Confirms returned SKUs exist, are in scope for the tenant, and match the query constraints.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;ranking:&lt;/strong&gt; Ranking the best matches. Reorders candidates by relevance, availability, or business rules before presentation.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;building_response:&lt;/strong&gt; Preparing the results. Assembles the final message, product cards, or clarification prompt the user will see.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The optional &lt;code&gt;detail&lt;/code&gt; field carries adapter-specific context (for example, a category name) without expanding the stage vocabulary. The &lt;code&gt;elapsedMs&lt;/code&gt; field is wall-clock time since the search started, useful for logging and for deciding when to show a "still working" fallback message.&lt;/p&gt;

&lt;p&gt;Not every query runs every stage. A first-turn category browse may skip &lt;code&gt;resolving_reference&lt;/code&gt;. A cache hit might flash through &lt;code&gt;retrieving&lt;/code&gt; in under 50ms. That is fine. The stages describe what is happening when it happens, not a mandatory sequence with equal duration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Capability-Gated Transport
&lt;/h2&gt;

&lt;p&gt;Progress streaming is opt-in at three levels. Adapter config exposes &lt;code&gt;progressStreaming?: 'auto' | 'off'&lt;/code&gt;. The default in config-ui is &lt;code&gt;'off'&lt;/code&gt;. Tenants turn it on explicitly.&lt;/p&gt;

&lt;p&gt;When set to &lt;code&gt;'auto'&lt;/code&gt;, the HTTP search adapter checks four conditions before opening an SSE stream:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Config says &lt;code&gt;progressStreaming: 'auto'&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt; The caller sets &lt;code&gt;supportsProgressStreaming: true&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt; The caller provides an &lt;code&gt;onProgress&lt;/code&gt; callback.&lt;/li&gt;
&lt;li&gt; The catalog backend's &lt;code&gt;/health&lt;/code&gt; endpoint advertises &lt;code&gt;capabilities.progressStreaming&lt;/code&gt; with &lt;code&gt;version: 1&lt;/code&gt;, &lt;code&gt;transport: 'sse'&lt;/code&gt;, and a &lt;code&gt;stages&lt;/code&gt; array.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If any check fails, the adapter logs the transport selection and falls back to a standard POST that returns JSON when complete. No error, no broken widget, no second integration path for non-streaming clients.&lt;/p&gt;

&lt;p&gt;The capability probe is cached for 60 seconds per base URL so every catalog turn does not pay an extra health round-trip. The transport itself uses &lt;a href="https://html.spec.whatwg.org/multipage/server-sent-events.html" rel="noopener noreferrer"&gt;Server-Sent Events&lt;/a&gt; as defined in the WHATWG HTML specification: a long-lived HTTP response where the server pushes &lt;code&gt;event:&lt;/code&gt; and &lt;code&gt;data:&lt;/code&gt; frames. SSE fits progress updates because they are server-to-client, unidirectional, and small. The chat API already uses SSE for answer streaming on compatible clients; catalog progress rides the same pattern.&lt;/p&gt;

&lt;p&gt;Why degrade instead of requiring SSE everywhere? Embedded widgets run on third-party sites with varied network stacks, corporate proxies, and older mobile WebViews. Some cannot hold an SSE connection reliably. Forcing SSE would break those clients or require maintaining two widget builds. Capability gating lets streaming clients get stage updates and everyone else get the same final answer through JSON.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Deadline and Cancellation
&lt;/h2&gt;

&lt;p&gt;Streaming progress does not remove the need for timeouts. It makes timeouts legible.&lt;/p&gt;

&lt;p&gt;Adapter config includes &lt;code&gt;timeouts.absoluteMs&lt;/code&gt;: a wall-clock deadline for the entire catalog operation, progress stream included. Separate connect and read timeouts still apply per HTTP hop, but the absolute deadline caps total user-visible wait regardless of how many stage transitions occur.&lt;/p&gt;

&lt;p&gt;Cancellation flows through the standard &lt;a href="https://dom.spec.whatwg.org/#interface-abortcontroller" rel="noopener noreferrer"&gt;AbortController / AbortSignal&lt;/a&gt; interface. The widget creates an &lt;code&gt;AbortController&lt;/code&gt; per request, passes its signal to the chat API, and wires the typing indicator's cancel action to &lt;code&gt;abort()&lt;/code&gt;. When the signal fires, the adapter stops reading the SSE stream and throws a transport error with outcome &lt;code&gt;cancelled&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That last part matters. A stream can end five ways, and conflating them loses debuggability:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;CatalogStreamOutcome&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cancelled&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;closed_without_result&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;malformed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;timeout&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;cancelled:&lt;/strong&gt; User or client aborted via AbortSignal.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;timeout:&lt;/strong&gt; Absolute or read deadline exceeded.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;error:&lt;/strong&gt; Network failure or non-2xx response mid-stream.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;malformed:&lt;/strong&gt; SSE frame parsed but stage name not in the allowed list.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;closed_without_result:&lt;/strong&gt; Stream ended cleanly but no search result arrived.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These outcomes are not user-facing copy. They are the classification layer for logs, metrics, and deciding whether to retry. A &lt;code&gt;cancelled&lt;/code&gt; outcome after the user closes the widget should not increment the same error counter as a &lt;code&gt;malformed&lt;/code&gt; frame from a misconfigured backend. Transport failures throw &lt;code&gt;CatalogSearchTransportError&lt;/code&gt; with the outcome attached so callers cannot accidentally treat a dead stream as an empty result set.&lt;/p&gt;

&lt;p&gt;HTTP semantics for long-lived responses are governed by &lt;a href="https://datatracker.ietf.org/doc/html/rfc9110" rel="noopener noreferrer"&gt;RFC 9110&lt;/a&gt;. The practical implication for us: the client must handle connection drops, the server must not assume the client read every event, and both sides need a defined terminal state. Explicit outcomes are that terminal state for catalog progress.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the Widget Does With It
&lt;/h2&gt;

&lt;p&gt;The widget does not render a progress bar. It updates the typing indicator text:&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="nx"&gt;onProgress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;progress&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;progress&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;progress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;string&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;updateTypingIndicator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;progress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&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;The API maps each stage to a short sentence ("Searching the catalog…", "Ranking the best matches…") before the event reaches the widget. The widget only displays the string. It does not know about stage enums or elapsed milliseconds.&lt;/p&gt;

&lt;p&gt;That is deliberate. A progress bar implies measurable completion. Catalog retrieval does not have a stable denominator. Is retrieving 40% of the work? It depends on the query. A bar that jumps from 30% to 90% in one frame is worse than a label that says what is happening now. &lt;a href="https://www.nngroup.com/articles/progress-indicators/" rel="noopener noreferrer"&gt;Nielsen Norman Group's guidance on progress indicators&lt;/a&gt; distinguishes determinate bars (known duration) from indeterminate indicators (unknown duration). Catalog search is indeterminate. Stage names are the honest representation.&lt;/p&gt;

&lt;p&gt;The widget also keeps a fallback timer. If no progress event arrives within 17 seconds, the typing indicator switches to "This search is taking a little longer. I'm still working on it…" That covers backends that support streaming but emit sparse updates, and clients where capability gating fell back to JSON mid-flight.&lt;/p&gt;

&lt;p&gt;For customer-facing deployments, this sits alongside the automation patterns in &lt;a href="https://www.hoverbot.ai/blog/customer-service-automation-2026" rel="noopener noreferrer"&gt;customer service automation in 2026&lt;/a&gt;: automate the lookup, but keep the human-visible loop honest when the lookup takes time.&lt;/p&gt;

&lt;h2&gt;
  
  
  What We Gave Up
&lt;/h2&gt;

&lt;p&gt;Progress streaming adds complexity across 20 files. The adapter now maintains two transport paths (SSE and JSON), a capability cache, SSE frame parsing, and outcome classification. Every new catalog backend must advertise progress capabilities in its health endpoint or streaming silently degrades. That is the intended behaviour, but it means backend teams have a contract to implement.&lt;/p&gt;

&lt;p&gt;Fast stages look silly. When validating finishes in 12ms, the user may see "Checking product information…" flash for a single frame. We considered suppressing stages below a minimum display time and rejected it. Artificial delays lie about system speed. A flash is honest; a forced 500ms pause is theater.&lt;/p&gt;

&lt;p&gt;Default is off. Tenants must enable &lt;code&gt;progressStreaming: 'auto'&lt;/code&gt; in catalog skill config. We did not ship it as the default because not every catalog backend supports SSE progress yet, and we would rather have tenants opt in once their backend is ready than have streaming fail open on every turn.&lt;/p&gt;

&lt;p&gt;Observability gets harder before it gets easier. Five outcome types means five buckets in dashboards instead of one "search failed" counter. The payoff is that on-call can distinguish user cancels from backend timeouts without reading stack traces.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Ships Next
&lt;/h2&gt;

&lt;p&gt;When PR #3 and PR #6 merge, catalog skills with &lt;code&gt;progressStreaming: 'auto'&lt;/code&gt;, a streaming-capable widget, and a backend that advertises SSE progress will show stage updates during retrieval. Everything else continues to work as a plain JSON search with a static typing indicator.&lt;/p&gt;

&lt;p&gt;The design does not make catalog search faster. It makes the wait interpretable. For a chat interface backed by a live product catalog, that is the difference between "broken" and "working on it."&lt;/p&gt;

&lt;p&gt;Want to see catalog-backed chat with progress streaming once it ships? &lt;a href="https://www.hoverbot.ai/request-demo" rel="noopener noreferrer"&gt;Request a demo&lt;/a&gt; and we will walk through the catalog skill configuration.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.hoverbot.ai/request-demo" rel="noopener noreferrer"&gt;Request a demo&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>typescript</category>
      <category>ux</category>
    </item>
    <item>
      <title>Knowledge Management for AI Chatbots: Structure, Maintain, Improve</title>
      <dc:creator>Vitaly Goncharenko</dc:creator>
      <pubDate>Wed, 16 Sep 2026 15:13:03 +0000</pubDate>
      <link>https://dev.to/hoverbot/knowledge-management-for-ai-chatbots-structure-maintain-improve-j26</link>
      <guid>https://dev.to/hoverbot/knowledge-management-for-ai-chatbots-structure-maintain-improve-j26</guid>
      <description>&lt;p&gt;A retrieval-augmented chatbot can still give a bad answer when retrieval finds the wrong passage, an outdated passage, or nothing useful. Before changing the model, inspect the evidence it received. That separates a retrieval failure from a generation failure and points to a fix you can test.&lt;/p&gt;

&lt;p&gt;Knowledge management for AI chatbots is the discipline of organizing, maintaining, and improving the content your assistant retrieves from. This guide covers how to structure content for retrieval-augmented generation (RAG), how to keep it fresh, and how to use analytics to find and close gaps systematically.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Knowledge Is the Real Bottleneck
&lt;/h2&gt;

&lt;p&gt;In a RAG system, every answer flows through the same pipeline: the user's question is used to retrieve relevant chunks of your content, and the model composes an answer grounded in those chunks. If retrieval surfaces the wrong chunk, an outdated chunk, or no chunk at all, the answer suffers no matter how capable the model is.&lt;/p&gt;

&lt;p&gt;Knowledge structure is one part of that pipeline teams can change directly. You can restructure source content, change chunking and metadata, then test whether the intended passages appear for representative questions. For the broader architecture context, see &lt;a href="https://www.hoverbot.ai/blog/multilingual-rag-practical-architecture" rel="noopener noreferrer"&gt;multilingual RAG architecture&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Structure Content for Retrieval, Not Just Reading
&lt;/h2&gt;

&lt;p&gt;Content written for humans browsing a help center is often poorly suited for retrieval. A few principles make a large difference:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  - **One topic per section.** Self-contained sections retrieve cleanly; sprawling articles that cover five topics retrieve ambiguously.

  - **Front-load the answer.** State the answer near the top of each section so a retrieved chunk carries the substance.

  - **Use explicit headings.** Headings that mirror how customers phrase questions improve matching.

  - **Avoid pronoun chains across sections.** A chunk should make sense on its own, without the paragraph before it.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Chunking Strategy: The Quiet Lever
&lt;/h2&gt;

&lt;p&gt;Chunking decides what unit of content gets embedded and retrieved. Chunks that are too large dilute relevance and bury the answer; chunks that are too small lose the context needed to answer well. The sweet spot is usually a coherent section: large enough to stand alone, small enough to be specific.&lt;/p&gt;

&lt;p&gt;Prefer structure-aware chunking that respects headings and natural boundaries over naive fixed-length splitting. Overlapping a little context between adjacent chunks helps preserve meaning at the edges. Then score retrieval at the chunk level so you can see which chunks actually answer questions and which never get used.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  **Practical tip:** If a single article answers many different questions, test focused sections or entries against the original. The useful unit is the one that retrieves the complete answer for your evaluation questions without bringing unrelated material with it.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Metadata Tagging for Precision and Freshness
&lt;/h2&gt;

&lt;p&gt;Metadata turns a flat pile of content into something you can filter and govern. Tag chunks with attributes like product area, audience, language, region, and last-reviewed date. This enables more precise retrieval, lets you scope answers to the right context, and makes freshness auditable.&lt;/p&gt;

&lt;p&gt;A last-reviewed date in particular is the backbone of maintenance: it tells you and the system which content is aging and may need a human check before it keeps answering customers.&lt;/p&gt;
&lt;h2&gt;
  
  
  Maintain Freshness Without a Full-Time Librarian
&lt;/h2&gt;

&lt;p&gt;Knowledge decays. Policies change, products ship, and yesterday's correct answer becomes today's complaint. The fix is a lightweight recurring process rather than a heroic annual cleanup:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  - Flag content past its review date for a quick human check

  - Tie knowledge updates to product and policy release cycles

  - Retire or merge chunks that never get retrieved

  - Promote answers that resolve well into canonical, well-structured entries
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Use Analytics to Find Gaps Systematically
&lt;/h2&gt;

&lt;p&gt;An unanswered or low-confidence question is a useful diagnostic signal. Cluster those conversations, inspect the retrieved passages, and separate missing content from weak retrieval or an answer-generation problem. When the source material is missing, write a focused entry and add the original question to the retrieval test set. We covered the loop in depth in &lt;a href="https://www.hoverbot.ai/blog/close-the-loop-analytics-that-teach-your-chatbot-to-fix-itself" rel="noopener noreferrer"&gt;close the loop&lt;/a&gt;, and the analytics surface is described in the &lt;a href="https://www.hoverbot.ai/resources/feature-deep-dives/analytics-close-loop-optimization" rel="noopener noreferrer"&gt;analytics deep dive&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  A Weekly Maintenance Workflow
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Review misses.&lt;/strong&gt; Look at clustered unresolved and low-confidence conversations from the week.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Triage.&lt;/strong&gt; Decide which gaps are worth fixing now based on volume and impact.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Write or restructure.&lt;/strong&gt; Add or reshape content as self-contained, well-headed chunks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Tag.&lt;/strong&gt; Apply metadata and a fresh review date.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Verify.&lt;/strong&gt; Confirm the new content actually gets retrieved for the target questions.&lt;/p&gt;

&lt;p&gt;Keep the review small enough to repeat. The important result is not time spent or documents edited. It is whether the changed content is retrieved for the target questions and supports a correct answer in the same evaluation set.&lt;/p&gt;
&lt;h2&gt;
  
  
  Where HoverBot Fits
&lt;/h2&gt;

&lt;p&gt;HoverBot ingests and chunks source content for retrieval, attributes answers to sources, and surfaces unresolved conversations for review. That gives a team evidence to inspect when an answer fails instead of treating the model as a black box. The knowledge-base tooling is detailed in the &lt;a href="https://www.hoverbot.ai/resources/feature-deep-dives/knowledge-base-management" rel="noopener noreferrer"&gt;knowledge base management deep dive&lt;/a&gt;, with the wider system in the &lt;a href="https://www.hoverbot.ai/resources/technical-overview" rel="noopener noreferrer"&gt;technical overview&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Want to inspect how grounded retrieval behaves on your own content? &lt;a href="https://www.hoverbot.ai/request-demo" rel="noopener noreferrer"&gt;Request a demo&lt;/a&gt; and test HoverBot against questions from your knowledge base.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  [Request a demo](https://www.hoverbot.ai/request-demo)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>ai</category>
      <category>rag</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
