<?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>Forem: Bunny Sleuth</title>
    <description>The latest articles on Forem by Bunny Sleuth (@rawr).</description>
    <link>https://forem.com/rawr</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3738446%2F7b6e7ef7-fb7b-49ac-af43-429efeb3f25e.png</url>
      <title>Forem: Bunny Sleuth</title>
      <link>https://forem.com/rawr</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/rawr"/>
    <language>en</language>
    <item>
      <title>elsewhere, a text-to-3D studio</title>
      <dc:creator>Bunny Sleuth</dc:creator>
      <pubDate>Wed, 04 Mar 2026 04:30:17 +0000</pubDate>
      <link>https://forem.com/rawr/elsewhere-a-text-to-3d-studio-3bif</link>
      <guid>https://forem.com/rawr/elsewhere-a-text-to-3d-studio-3bif</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/mlh-built-with-google-gemini-02-25-26"&gt;Built with Google Gemini: Writing Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built with Google Gemini
&lt;/h2&gt;

&lt;p&gt;I built a high performance text-to-3D model studio that works straight from the browser!  A user describes what they want in natural language from “cute cat” to “floating pizza with laser eyes” and Gemini generates an interactive 3D model (in THREE.js). &lt;br&gt;
Asset generation is a two-phase pipeline with:&lt;br&gt;
  ## Planning phase — Gemini receives the user prompt + PLANNING_SYSTEM_PROMPT_V4 as systemInstruction. Temperature 0.5, thinkingLevel: 'low', max 8192 output tokens. It returns a v3 schema JSON: an array of 3-6 materials (color, roughness, metalness) and 4-12 parts, each specifying geometry type (Box|Sphere|Cylinder|Cone|Torus|Lathe|Tube|Dome), parent reference, priority (1-3), material index, geometry parameters, and instance transforms (position/rotation/scale arrays). The LLM never writes executable code and rather it describes geometry in a constrained JSON vocabulary.&lt;br&gt;
 ## Compilation phase — SchemaCompiler.compile() runs five deterministic steps with no LLM involvement:&lt;br&gt;
    - Parse: normalize JSON, expand defaults, resolve material references&lt;br&gt;
    - Validate: check required fields, parent references, topological sort&lt;br&gt;
    - Budget: prune parts by priority (3 → 2 → 1.5) if mesh count exceeds 24 or the material count exceeds 5&lt;br&gt;
    - Auto-snap: detect disconnected parts and snap to parent bounding box (threshold: 2.0 units)&lt;br&gt;
    - Emit: generate Three.js code — MeshStandardMaterial array, geometry constructors, parent-child hierarchy via group.add()&lt;/p&gt;

&lt;p&gt;We can even handle full scene generation from a single prompt or theme! This same spatial reasoning when combining asset parts is used to place them on the map. After each round, a screenshot of the studio is taken from multiple angles and these images are passed back to Gemini where it tweaks the coordinates and relations, so assets fit together more tidily.&lt;/p&gt;
&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Here is my Cloud run link (the password is "buildwithelsewhere") :&lt;/strong&gt;&lt;br&gt;


&lt;/p&gt;
&lt;div class="ltag__cloud-run"&gt;
  &lt;iframe height="600px" src="https://elsewhere-431781682131.us-central1.run.app"&gt;
  &lt;/iframe&gt;
&lt;/div&gt;


&lt;br&gt;
&lt;strong&gt;Here is my quick little YouTube demo/trailer:&lt;/strong&gt;&lt;br&gt;


  &lt;iframe src="https://www.youtube.com/embed/LhwH2ZuDw7s"&gt;
  &lt;/iframe&gt;


&lt;br&gt;
&lt;strong&gt;And here is the GitHub repo:&lt;/strong&gt;&lt;br&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/bug39" rel="noopener noreferrer"&gt;
        bug39
      &lt;/a&gt; / &lt;a href="https://github.com/bug39/elsewhere" rel="noopener noreferrer"&gt;
        elsewhere
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      3D world-building studio powered by Gemini. Generate assets from text, build worlds, create animations.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;elsewhere&lt;/h1&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;AI-Powered 3D World Studio&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Describe what you want and AI builds it — 3D assets, entire scenes, living worlds you can explore in third person. Built for Google's Gemini 3 Hackathon&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;What You Can Do&lt;/h2&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Generate assets&lt;/strong&gt; from text prompts — "a cozy cabin with smoke from the chimney"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generate entire scenes&lt;/strong&gt; — "a medieval village marketplace" plans, creates, and places everything&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Arrange worlds&lt;/strong&gt; on a 400m terrain with biomes, heightmaps, and textures&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Script NPCs&lt;/strong&gt; with behaviors and branching dialogue trees&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Play&lt;/strong&gt; your world in third person — walk, run, jump, talk to NPCs&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Quick Start&lt;/h2&gt;

&lt;/div&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm install
npm run dev        &lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; http://localhost:3000&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;If the hackathon results still aren't out, this might not be working yet!
Requires a &lt;a href="https://aistudio.google.com/apikey" rel="nofollow noopener noreferrer"&gt;Gemini API key&lt;/a&gt; (free tier works).&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Tech Stack&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;Preact, Three.js, Gemini 3 Flash, React Flow, IndexedDB&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;License&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;MIT&lt;/p&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/bug39/elsewhere" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;





&lt;p&gt;:D&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;p&gt;Technical skills, soft skills, unexpected lessons — what stuck with you? →&lt;br&gt;
I had LOTS of trouble with prompt engineering the generation model to output consistent results across a very wide diversity of prompts. It took maybe 30 iterations to get right. At one point, I had a CLI agent set-up a mock studio where the base prompt had 15+ other tiny tweaks, and I judged the quality of each output, slowly picking out weakness of each prompt I got to a place where I was very happy with how consistently the model could output differing geometries. I wanted to know how to very finely tweak these 3D models and I couldn’t really rely on communicating that through text with myagent, so I had to get pretty familiar with THREE.js!&lt;/p&gt;

&lt;h2&gt;
  
  
  Google Gemini Feedback
&lt;/h2&gt;

&lt;p&gt;When Gemini 3 Flash Preview was in the pipeline, I was really missing that final "push" to get more detail out of the THREE.js compiler I made. The recently released &lt;code&gt;Gemini-3.1-flash-preview&lt;/code&gt; brought with it a HUGE improvement in spatial reasoning, and this was exactly what elsewhere needed (though in the Cloud run link, &lt;code&gt;gemini-3-flash-preview&lt;/code&gt; is still running as I can't afford to pay for that on a public link!). Very smooth and easy experience using Gemini. I had originally started this for a Gemini hackathon, so I was locked into that, but in early testing, I found that Flash performed better, faster, and cheaper for my specific task of generating 3D models. &lt;/p&gt;

&lt;h1&gt;
  
  
  ai #computer #gemini
&lt;/h1&gt;

</description>
      <category>gemini</category>
      <category>devchallenge</category>
      <category>geminireflections</category>
      <category>ai</category>
    </item>
    <item>
      <title>Verdict — When Policies Collide</title>
      <dc:creator>Bunny Sleuth</dc:creator>
      <pubDate>Mon, 09 Feb 2026 00:18:54 +0000</pubDate>
      <link>https://forem.com/rawr/verdict-when-policies-collide-3j70</link>
      <guid>https://forem.com/rawr/verdict-when-policies-collide-3j70</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/algolia"&gt;Algolia Agent Studio Challenge&lt;/a&gt;: Consumer-Facing Non-Conversational Experiences&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Verdict — When Policies Collide
&lt;/h2&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;Most support tools search for a policy and hand it to an agent. But real support tickets don't map to a single policy — they sit at the intersection of multiple, often contradictory ones. A customer's treadmill motor dies at 6 weeks. The 30-day return window says no. The 2-year motor warranty says yes. Which one wins?&lt;/p&gt;

&lt;p&gt;Verdict is a decision engine that resolves these conflicts. A support agent clicks a ticket, and Verdict retrieves the relevant policy clauses from Algolia, detects where they contradict each other, and applies a resolution hierarchy — product-specific overrides general, situational overrides everything — to produce a structured verdict with full citations. No chatbot, no back-and-forth. Click a ticket, get a ruling.&lt;/p&gt;

&lt;p&gt;The interesting case is a denial. Try the earbuds scenario: a customer wants to return opened wireless earbuds within the 30-day window. Sounds like a standard approval. But Verdict pulls a hygiene exception for in-ear audio products and denies the return. The UI renders the two policies side-by-side with a "VS" comparison — General Return Policy (overridden) vs. Hygiene Exception (prevails) — so the agent immediately sees &lt;em&gt;why&lt;/em&gt; the return was blocked and can explain it to the customer.&lt;/p&gt;

&lt;p&gt;I built this for the non-conversational track because the whole point is that there's no conversation needed. The agent's workflow is: see ticket, click, read verdict, act. The decision is proactive and fully structured — verdict cards, policy comparison panels, conflict traces — not a chat bubble.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Live URL:&lt;/strong&gt; &lt;a href="https://algoliahack.vercel.app/" rel="noopener noreferrer"&gt;https://algoliahack.vercel.app/&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Video:&lt;/strong&gt; &lt;a href="https://youtu.be/waHa-nvvmbA" rel="noopener noreferrer"&gt;https://youtu.be/waHa-nvvmbA&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Here's what to look at:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Treadmill X500&lt;/strong&gt; (Warranty vs. Return) — Green APPROVED. The motor warranty overrides the expired return window. This sets the pattern: Verdict finds conflicts and resolves them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SoundPro Earbuds&lt;/strong&gt; (Hygiene Override) — Red DENIED. This is the one to watch. The earbuds are within the return window, but the hygiene exception blocks it. The VS comparison makes the conflict immediately visible.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alpine Hiking Boots&lt;/strong&gt; (Damage Override) — Green APPROVED. Return window expired at 39 days, but shipping damage was reported within 48 hours. The situational override wins.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TrailBlazer Daypack&lt;/strong&gt; (Standard Return) — Green APPROVED, no conflict. Shows the system doesn't over-complicate simple cases.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom ticket&lt;/strong&gt; — Paste any text and watch it analyze live. This proves the verdicts aren't pre-computed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Policy Index&lt;/strong&gt; — Browse all 26 Algolia records grouped by policy layer, including 3 red herring decoy policies that the agent correctly ignores.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  How I Used Algolia Agent Studio
&lt;/h2&gt;
&lt;h3&gt;
  
  
  The index: 26 clause-level records
&lt;/h3&gt;

&lt;p&gt;I indexed 26 policy clause records for a fictional retailer (Apex Gear) in a single index, &lt;code&gt;apex_gear_policies&lt;/code&gt;. Each record is one clause — not a whole policy document — with structured metadata: a &lt;code&gt;policy_layer&lt;/code&gt; (1-4), &lt;code&gt;priority&lt;/code&gt; score, &lt;code&gt;policy_type&lt;/code&gt;, &lt;code&gt;product_tags&lt;/code&gt;, &lt;code&gt;conditions&lt;/code&gt;, and &lt;code&gt;effect&lt;/code&gt;. I split them this way because conflict resolution requires comparing individual clauses, not whole documents, and it keeps records under Algolia's 10KB free-tier limit.&lt;/p&gt;

&lt;p&gt;Three of the 26 records are deliberate red herrings — an expired holiday return extension, a loyalty member perk, and a bulk discount policy. They share product categories with the demo scenarios but shouldn't be cited. The agent consistently ignores them.&lt;/p&gt;
&lt;h3&gt;
  
  
  Retrieval-time intelligence: ranking, Rules, and Synonyms
&lt;/h3&gt;

&lt;p&gt;This is where Algolia does more than store data. The index is configured with custom ranking: &lt;code&gt;desc(policy_layer)&lt;/code&gt;, &lt;code&gt;desc(priority)&lt;/code&gt;, &lt;code&gt;desc(specificity_score)&lt;/code&gt;. Every search result arrives pre-sorted by authority — the most specific, highest-priority clause first. The LLM receives policies in the right order before it starts reasoning, which naturally guides correct conflict resolution.&lt;/p&gt;

&lt;p&gt;On top of custom ranking, I added 3 index-level Rules and 6 Synonym groups. The Rules promote critical override policies when the query contains trigger words — a query mentioning "hygiene" promotes &lt;code&gt;HYG-4.1&lt;/code&gt; (the in-ear audio hygiene exception) to position 1, ensuring the agent can't miss it even in a noisy result set. Without that Rule, a broad search for "earbuds return" surfaces general return policies first, and the agent might approve a return it should deny. The Synonyms expand the search vocabulary — "defective" matches "broken", "malfunction", "stopped working"; "earbuds" expands to "in-ear audio" and "personal audio" — so the agent retrieves relevant clauses even when the customer's language doesn't match the index terminology.&lt;/p&gt;

&lt;p&gt;These are all retrieval-time features. They shape what the LLM sees &lt;em&gt;before&lt;/em&gt; it starts reasoning — Algolia handles authority ranking and vocabulary normalization at query time, the LLM handles condition matching and explanation at reasoning time. They're complementary layers of intelligence.&lt;/p&gt;
&lt;h3&gt;
  
  
  Agent Studio as orchestrator
&lt;/h3&gt;

&lt;p&gt;Agent Studio runs the agentic loop. The system prompt defines a multi-step protocol: extract key information from the ticket, then perform 3 targeted Algolia searches (general return policies, product-specific warranties, situational overrides), then analyze all retrieved policies, detect conflicts, resolve them using the layer hierarchy, and output a structured XML verdict.&lt;/p&gt;

&lt;p&gt;The agent decides &lt;em&gt;which&lt;/em&gt; searches to run based on the ticket content. For the earbuds ticket, it searches for "hygiene earbuds in-ear audio return" because the ticket mentions opened in-ear products. For the treadmill ticket, it searches "Pro-Treadmill X500 warranty" because the issue is a mechanical failure. For the hiking boots, it searches "shipping damage carrier report override" because the package arrived crushed. The system prompt guides this decision-making, but Agent Studio executes the tool calls autonomously — I don't hardcode which searches run for which ticket.&lt;/p&gt;

&lt;p&gt;The system prompt also enforces anti-hallucination: every &lt;code&gt;clause_id&lt;/code&gt; in the verdict must come verbatim from search results. The agent can't invent a policy, and it can't ask the customer for more information — it either decides or escalates.&lt;/p&gt;
&lt;h3&gt;
  
  
  Capturing the pipeline: SSE stream parsing
&lt;/h3&gt;

&lt;p&gt;Agent Studio's &lt;code&gt;/completions&lt;/code&gt; endpoint returns a Server-Sent Events stream. I built a custom SSE parser in the API route that captures every event in the agent's reasoning chain — not just the final text output. The parser correlates &lt;code&gt;tool-input-start&lt;/code&gt; events (which carry the search query and a &lt;code&gt;toolCallId&lt;/code&gt;) with &lt;code&gt;tool-output-available&lt;/code&gt; events (which carry the actual Algolia hits for that &lt;code&gt;toolCallId&lt;/code&gt;). This gives me the full pipeline: what the agent searched for, what Algolia returned, and which records the LLM ultimately cited.&lt;/p&gt;

&lt;p&gt;The frontend renders this as a visible pipeline trace — each Algolia search step shows the query text, hit count, and the individual policy records returned. Records that ended up cited in the final verdict get a "Cited in verdict" badge, so you can see exactly which retrieved clauses influenced the decision. This makes Algolia's contribution transparent instead of hiding it behind the LLM's output.&lt;/p&gt;
&lt;h3&gt;
  
  
  Structured output: XML over free-form text
&lt;/h3&gt;

&lt;p&gt;The system prompt instructs the agent to produce XML-tagged output rather than free-form text:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;analysis&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;verdict&amp;gt;&lt;/span&gt;APPROVED&lt;span class="nt"&gt;&amp;lt;/verdict&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;verdict_type&amp;gt;&lt;/span&gt;warranty_claim&lt;span class="nt"&gt;&amp;lt;/verdict_type&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;summary&amp;gt;&lt;/span&gt;Motor warranty overrides expired return window...&lt;span class="nt"&gt;&amp;lt;/summary&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;policies&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;policy&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;clause_id&amp;gt;&lt;/span&gt;WAR-3.1&lt;span class="nt"&gt;&amp;lt;/clause_id&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;policy_name&amp;gt;&lt;/span&gt;Pro-Treadmill Motor Warranty&lt;span class="nt"&gt;&amp;lt;/policy_name&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;applies&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/applies&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;effect&amp;gt;&lt;/span&gt;warranty_approved&lt;span class="nt"&gt;&amp;lt;/effect&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;reason&amp;gt;&lt;/span&gt;Motor failed within 2-year warranty period&lt;span class="nt"&gt;&amp;lt;/reason&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/policy&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/policies&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;conflict&amp;gt;&amp;lt;exists&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/exists&amp;gt;&lt;/span&gt;...&lt;span class="nt"&gt;&amp;lt;/conflict&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;resolution&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;winning_policy&amp;gt;&lt;/span&gt;WAR-3.1&lt;span class="nt"&gt;&amp;lt;/winning_policy&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;rule_applied&amp;gt;&lt;/span&gt;Product-specific warranty overrides general return&lt;span class="nt"&gt;&amp;lt;/rule_applied&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/resolution&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/analysis&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The frontend parses this into typed components with a regex-based tag extractor. If the LLM deviates from format, the UI falls back to displaying the raw response with a warning banner rather than crashing. Across 20+ test runs per scenario at temperature=0, the XML has been well-formed every time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Fast Retrieval Matters
&lt;/h2&gt;

&lt;p&gt;Custom ranking means every search result arrives pre-sorted by policy authority. Index-level Rules promote critical override clauses to the top of the result set when trigger conditions are met. Synonyms normalize vocabulary so "motor stopped working" matches "mechanical defect" without the LLM needing to guess. These features shape the LLM's reasoning context before it processes a single token — and they're all configured in the Algolia dashboard, working transparently through Agent Studio without extra API code.&lt;/p&gt;

&lt;p&gt;A vector database would retrieve "semantically similar" policies, which isn't what I need. When a customer reports a treadmill motor failure, we get the exact motor warranty clause for that product model (&lt;code&gt;policy_layer:3&lt;/code&gt;, &lt;code&gt;applies_to:Pro-Treadmill X500&lt;/code&gt;), not five vaguely related fitness equipment policies ranked by embedding distance. Structured metadata with precise filtering is the right retrieval model for compliance data.&lt;/p&gt;

&lt;p&gt;The total analysis time (shown in the UI after each verdict) is typically 5-10 seconds — almost entirely LLM reasoning. Algolia's retrieval completes in under 50ms across all 3 searches. In a support workflow where agents triage dozens of tickets, that retrieval speed keeps the bottleneck on reasoning, not on waiting for data.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>programming</category>
      <category>algoliachallenge</category>
    </item>
  </channel>
</rss>
