[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fBSOCFlB6urqjEk0gr7IkCMdFX4iGgtomA1szsT7MXsQ":3},{"item":4},{"id":5,"idKnowledge":6,"idDomain":7,"idCluster":7,"kindOverride":8,"slug":9,"title":10,"description":11,"bodyMarkdown":12,"bodyHtml":13,"author":14,"date":15,"createdAt":16,"topics":17,"image":25,"hasDownload":26,"fileName":7,"youtubeId":27},"499","EFFDB3CC-D8FB-F149-826F-ACB6B2F6F2AA","","article","how-do-you-make-a-15-year-old-filemaker-database-answer-questions-in-plain-english","How do you make a 15-year-old FileMaker database answer questions in plain English?","A case study in building FindIt AI: why our first approach (RAG) broke on live business data, why we rebuilt it as a direct FileMaker Data API connection instead and using MCP server, and what a working natural-language layer on top of FileMaker actually looks like in production.","A staff member needs to know how many hours a colleague booked today. In most FileMaker shops, that means opening the right layout, finding the right filter, and reading the right field — assuming you know which of the twelve layouts holds that number. Multiply that by every question someone might have about contacts, contracts, tasks, or bookings, and you get the real, unglamorous cost of running a business on a database only a few people know how to navigate.\n\nWe set out to fix that: let someone type \"what are today's booked hours for Shubham?\" and get a real answer, pulled from the live database, with nothing memorized and nothing manually looked up. What we learned building it — including one full architecture rebuild — is a better story than the finished product, so here's both.\n\n## Situation\n\nThe client's FileMaker system was mature: years of contacts, contracts, projects, and time-tracking data, actively used and changing daily. Non-technical staff needed answers from it constantly, but only a handful of people could navigate the schema well enough to find them. The ask was simple to state and hard to deliver: a natural-language interface that could sit on top of the existing database without replacing it, disrupting daily operations, or requiring FileMaker expertise to use.\n\n## Challenge\n\nOur first instinct was the standard approach for \"chat with your data\": **retrieval-augmented generation (RAG)**. Build a service that reads documents out of FileMaker, chunks them, embeds them into a vector database, and lets an LLM search that index semantically. It's the right tool for a lot of problems — searching PDFs, reports, and static documents by meaning instead of keyword.\n\nIt's the wrong tool for this one, and it took building most of it to see exactly why.\n\nRAG assumes the data is relatively static — you embed it once, and search it many times. But contacts and contracts in an active FileMaker system change constantly. Every sync creates a window where the vector index is stale. A time-booking question needs *today's* number, not a number from whenever the last embedding job ran. We were building an increasingly complex freshness problem — re-sync schedules, cache invalidation, delete-and-re-embed logic — to work around a mismatch between the tool and the task. RAG is built for documents. This was transactional, fast-changing, row-level data. Different problem, different architecture.\n\n## Approach\n\nThe fix was to stop embedding the data at all. Instead of pre-indexing a copy of the database and hoping it stayed fresh, we rebuilt the system to query FileMaker directly, live, through the **FileMaker Data API**, every time a question is asked. The natural-language layer's job became routing and translation — figuring out which layout and which filter a question maps to — not memorizing a snapshot of the data.\n\nConcretely, this meant building an **MCP (Model Context Protocol) server** — a set of Python-defined tools (`search_contacts`, `count_contacts`, and similar) that an LLM can call directly against the FileMaker Data API at question time. The AI doesn't hold its own copy of your data; it holds a set of live tools and decides which one to call based on the question. No sync job, no staleness window, no re-indexing when a record changes. The trade-off is that every question costs a live query instead of a cheap vector lookup — a reasonable price for always-correct answers.\n\n## Solution: FindIt AI\n\nWhat came out of that rebuild is **FindIt AI**, an assistant that sits on top of a FileMaker system and answers natural-language questions using live Data API calls, deployed and managed through a purpose-built console.\n\nA few things about how it actually works in production:\n\n**Real-time answers, not cached ones.** Ask \"what are today's booked hours of Shubham?\" and the assistant resolves it to the `Task_Time_Booking` layout, filters live, and returns a plain-English answer (\"Shubham booked 1.2 hrs today.\") straight from the current data — not from an index that might be hours old.\n\n**A deployment console for managing real client servers.** Each client gets an entry in a \"Client servers\" panel, connected over SSH with FileMaker Data API credentials (server URL, database, service account) configured per deployment. A \"Schema mode\" setting lets a new client run in a generic dynamic Q&A mode against any set of layouts, without custom development up front.\n\n**A training layer instead of prompt engineering.** This is the part we think matters most. Rather than tuning prompts and hoping the model generalizes, the console has a dedicated \"Train AI\" tab where an admin can teach the assistant, with no code:\n- **Layout routing rules** — a regex pattern maps certain kinds of questions to a specific layout.\n- **Owner rules** — teach the assistant that \"Shubham\" refers to a specific FileMaker user ID, so \"tasks of Shubham\" filters correctly instead of guessing.\n- **Q&A overrides** — when the assistant gives a wrong answer, an admin can define the exact question pattern and the exact correct answer, and it's applied immediately.\n\nThese rules are stored per client as a `rules.json` file and applied automatically on restart — meaning accuracy improves over time through configuration, not code changes.\n\n**Controlled writes, not just reads.** The system also supports the assistant creating records — extracting fields from a request like \"create a task,\" asking for anything missing, and writing it to the database. This is deliberately a separate, explicit capability from read-only Q&A, not an automatic side effect of a query.\n\n**Self-service customization.** A \"Files & AI\" tab lets an admin view the Python service files running on a specific client's server, describe a required change in plain English (e.g., \"rename the CONTACTS table to CUSTOMERS and update all field names\"), and have an AI assistant rewrite the file for that client before it's deployed and the service restarted — with a live log streaming the deployment as it happens.\n\nThe system runs in production connected to a live FileMaker BetterForms client portal, answering real staff questions against real, currently-changing data — not a demo environment.\n\n## Result\n\nThe practical outcome is a database that non-technical staff can query directly, without learning the schema, and without the freshness problems that would have made the original RAG design fragile in exactly the scenarios that matter most (today's numbers, this week's bookings, the current status of a record).\n\n## Lessons learned\n\n**The obvious architecture isn't always the right one.** RAG is the default answer to \"let people ask questions about our data,\" and it's the wrong default for anything that changes as often as a live business database does. The fix wasn't a smarter RAG pipeline — it was recognizing the category of problem had changed.\n\n**\"Teach the AI\" needs to be a UI, not a prompt file.** Accuracy on messy, real-world questions (\"tasks of Shubham,\" not \"tasks where UserID = 4471\") came less from the model and more from giving a non-developer a way to correct it directly — layout rules, owner mappings, and answer overrides that don't require touching code.\n\n**Read and write need to stay visibly separate.** Letting the assistant answer questions and letting it create records are both useful, but conflating them invites exactly the kind of silent, unreviewed write we'd warn any client against. Keeping record creation as its own deliberate step, with confirmation of extracted fields, matters more than raw capability.\n\n**\"Production-ready\" means it survives a live client, not a demo.** The real test wasn't a clean sample database — it was staying accurate against a system that's been in daily use for years, with the inconsistent naming and edge cases that come with that.\n\n## Checklist: before you put a natural-language layer on your own database\n\n- [ ] Is the underlying data mostly static (documents, reports) or constantly changing (transactional records)? This decides whether RAG or a live-query approach fits.\n- [ ] Can you tolerate a staleness window, or does the answer need to reflect right-now data?\n- [ ] Do the people who'll use it need to correct wrong answers themselves, without a developer in the loop?\n- [ ] Is there a clear, separate confirmation step before the assistant writes anything back to the database?\n- [ ] Can you point to which layout or table produced a given answer, for anyone who wants to verify it?\n\n## FAQ\n\n**Why not just use RAG and re-sync more often?**\nFaster syncing narrows the staleness window but never closes it, and it adds real infrastructure cost (embedding pipelines, vector storage, delete\u002Fre-ingest logic) to work around a mismatch that a live query sidesteps entirely. For data that changes hourly or daily, querying live is usually simpler than syncing constantly.\n\n**Does this replace the FileMaker interface?**\nNo — it sits alongside it. FileMaker stays the system of record and the interface for anything more complex than a lookup; the natural-language layer handles the \"just tell me the number\" questions that otherwise interrupt someone's day.\n\n**How is this different from asking a general chatbot to read a database export?**\nA general chatbot working from a static export has the same staleness problem RAG does, plus no way to safely write back. Querying live through the FileMaker Data API, with an explicit training layer for accuracy, is what makes this usable for a database that's actually in daily use rather than a one-off analysis.\n\n**What stops the assistant from writing bad data?**\nRecord creation is a distinct, visible action — the assistant extracts values, asks for anything missing, and the change is deployed and logged like any other configuration change, not silently triggered by a question that merely looked like a request.\n\n## The actual point\n\nThe lesson here generalizes past FileMaker: the popular architecture for \"AI on top of your data\" isn't automatically the right one for *your* data. If it changes constantly, that's a strong signal to query it live rather than index a copy of it — and to spend your effort on a way for real users to correct the AI, not on tuning a prompt nobody but a developer can touch.","\u003Cp>A staff member needs to know how many hours a colleague booked today. In most FileMaker shops, that means opening the right layout, finding the right filter, and reading the right field — assuming you know which of the twelve layouts holds that number. Multiply that by every question someone might have about contacts, contracts, tasks, or bookings, and you get the real, unglamorous cost of running a business on a database only a few people know how to navigate.\u003C\u002Fp>\n\u003Cp>We set out to fix that: let someone type &quot;what are today&#39;s booked hours for Shubham?&quot; and get a real answer, pulled from the live database, with nothing memorized and nothing manually looked up. What we learned building it — including one full architecture rebuild — is a better story than the finished product, so here&#39;s both.\u003C\u002Fp>\n\u003Ch2>Situation\u003C\u002Fh2>\n\u003Cp>The client&#39;s FileMaker system was mature: years of contacts, contracts, projects, and time-tracking data, actively used and changing daily. Non-technical staff needed answers from it constantly, but only a handful of people could navigate the schema well enough to find them. The ask was simple to state and hard to deliver: a natural-language interface that could sit on top of the existing database without replacing it, disrupting daily operations, or requiring FileMaker expertise to use.\u003C\u002Fp>\n\u003Ch2>Challenge\u003C\u002Fh2>\n\u003Cp>Our first instinct was the standard approach for &quot;chat with your data&quot;: \u003Cstrong>retrieval-augmented generation (RAG)\u003C\u002Fstrong>. Build a service that reads documents out of FileMaker, chunks them, embeds them into a vector database, and lets an LLM search that index semantically. It&#39;s the right tool for a lot of problems — searching PDFs, reports, and static documents by meaning instead of keyword.\u003C\u002Fp>\n\u003Cp>It&#39;s the wrong tool for this one, and it took building most of it to see exactly why.\u003C\u002Fp>\n\u003Cp>RAG assumes the data is relatively static — you embed it once, and search it many times. But contacts and contracts in an active FileMaker system change constantly. Every sync creates a window where the vector index is stale. A time-booking question needs \u003Cem>today&#39;s\u003C\u002Fem> number, not a number from whenever the last embedding job ran. We were building an increasingly complex freshness problem — re-sync schedules, cache invalidation, delete-and-re-embed logic — to work around a mismatch between the tool and the task. RAG is built for documents. This was transactional, fast-changing, row-level data. Different problem, different architecture.\u003C\u002Fp>\n\u003Ch2>Approach\u003C\u002Fh2>\n\u003Cp>The fix was to stop embedding the data at all. Instead of pre-indexing a copy of the database and hoping it stayed fresh, we rebuilt the system to query FileMaker directly, live, through the \u003Cstrong>FileMaker Data API\u003C\u002Fstrong>, every time a question is asked. The natural-language layer&#39;s job became routing and translation — figuring out which layout and which filter a question maps to — not memorizing a snapshot of the data.\u003C\u002Fp>\n\u003Cp>Concretely, this meant building an \u003Cstrong>MCP (Model Context Protocol) server\u003C\u002Fstrong> — a set of Python-defined tools (\u003Ccode>search_contacts\u003C\u002Fcode>, \u003Ccode>count_contacts\u003C\u002Fcode>, and similar) that an LLM can call directly against the FileMaker Data API at question time. The AI doesn&#39;t hold its own copy of your data; it holds a set of live tools and decides which one to call based on the question. No sync job, no staleness window, no re-indexing when a record changes. The trade-off is that every question costs a live query instead of a cheap vector lookup — a reasonable price for always-correct answers.\u003C\u002Fp>\n\u003Ch2>Solution: FindIt AI\u003C\u002Fh2>\n\u003Cp>What came out of that rebuild is \u003Cstrong>FindIt AI\u003C\u002Fstrong>, an assistant that sits on top of a FileMaker system and answers natural-language questions using live Data API calls, deployed and managed through a purpose-built console.\u003C\u002Fp>\n\u003Cp>A few things about how it actually works in production:\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Real-time answers, not cached ones.\u003C\u002Fstrong> Ask &quot;what are today&#39;s booked hours of Shubham?&quot; and the assistant resolves it to the \u003Ccode>Task_Time_Booking\u003C\u002Fcode> layout, filters live, and returns a plain-English answer (&quot;Shubham booked 1.2 hrs today.&quot;) straight from the current data — not from an index that might be hours old.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>A deployment console for managing real client servers.\u003C\u002Fstrong> Each client gets an entry in a &quot;Client servers&quot; panel, connected over SSH with FileMaker Data API credentials (server URL, database, service account) configured per deployment. A &quot;Schema mode&quot; setting lets a new client run in a generic dynamic Q&amp;A mode against any set of layouts, without custom development up front.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>A training layer instead of prompt engineering.\u003C\u002Fstrong> This is the part we think matters most. Rather than tuning prompts and hoping the model generalizes, the console has a dedicated &quot;Train AI&quot; tab where an admin can teach the assistant, with no code:\u003C\u002Fp>\n\u003Cul>\n\u003Cli>\u003Cstrong>Layout routing rules\u003C\u002Fstrong> — a regex pattern maps certain kinds of questions to a specific layout.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Owner rules\u003C\u002Fstrong> — teach the assistant that &quot;Shubham&quot; refers to a specific FileMaker user ID, so &quot;tasks of Shubham&quot; filters correctly instead of guessing.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Q&amp;A overrides\u003C\u002Fstrong> — when the assistant gives a wrong answer, an admin can define the exact question pattern and the exact correct answer, and it&#39;s applied immediately.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Cp>These rules are stored per client as a \u003Ccode>rules.json\u003C\u002Fcode> file and applied automatically on restart — meaning accuracy improves over time through configuration, not code changes.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Controlled writes, not just reads.\u003C\u002Fstrong> The system also supports the assistant creating records — extracting fields from a request like &quot;create a task,&quot; asking for anything missing, and writing it to the database. This is deliberately a separate, explicit capability from read-only Q&amp;A, not an automatic side effect of a query.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Self-service customization.\u003C\u002Fstrong> A &quot;Files &amp; AI&quot; tab lets an admin view the Python service files running on a specific client&#39;s server, describe a required change in plain English (e.g., &quot;rename the CONTACTS table to CUSTOMERS and update all field names&quot;), and have an AI assistant rewrite the file for that client before it&#39;s deployed and the service restarted — with a live log streaming the deployment as it happens.\u003C\u002Fp>\n\u003Cp>The system runs in production connected to a live FileMaker BetterForms client portal, answering real staff questions against real, currently-changing data — not a demo environment.\u003C\u002Fp>\n\u003Ch2>Result\u003C\u002Fh2>\n\u003Cp>The practical outcome is a database that non-technical staff can query directly, without learning the schema, and without the freshness problems that would have made the original RAG design fragile in exactly the scenarios that matter most (today&#39;s numbers, this week&#39;s bookings, the current status of a record).\u003C\u002Fp>\n\u003Ch2>Lessons learned\u003C\u002Fh2>\n\u003Cp>\u003Cstrong>The obvious architecture isn&#39;t always the right one.\u003C\u002Fstrong> RAG is the default answer to &quot;let people ask questions about our data,&quot; and it&#39;s the wrong default for anything that changes as often as a live business database does. The fix wasn&#39;t a smarter RAG pipeline — it was recognizing the category of problem had changed.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>&quot;Teach the AI&quot; needs to be a UI, not a prompt file.\u003C\u002Fstrong> Accuracy on messy, real-world questions (&quot;tasks of Shubham,&quot; not &quot;tasks where UserID = 4471&quot;) came less from the model and more from giving a non-developer a way to correct it directly — layout rules, owner mappings, and answer overrides that don&#39;t require touching code.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Read and write need to stay visibly separate.\u003C\u002Fstrong> Letting the assistant answer questions and letting it create records are both useful, but conflating them invites exactly the kind of silent, unreviewed write we&#39;d warn any client against. Keeping record creation as its own deliberate step, with confirmation of extracted fields, matters more than raw capability.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>&quot;Production-ready&quot; means it survives a live client, not a demo.\u003C\u002Fstrong> The real test wasn&#39;t a clean sample database — it was staying accurate against a system that&#39;s been in daily use for years, with the inconsistent naming and edge cases that come with that.\u003C\u002Fp>\n\u003Ch2>Checklist: before you put a natural-language layer on your own database\u003C\u002Fh2>\n\u003Cul>\n\u003Cli>\u003Cinput disabled=\"\" type=\"checkbox\"> Is the underlying data mostly static (documents, reports) or constantly changing (transactional records)? This decides whether RAG or a live-query approach fits.\u003C\u002Fli>\n\u003Cli>\u003Cinput disabled=\"\" type=\"checkbox\"> Can you tolerate a staleness window, or does the answer need to reflect right-now data?\u003C\u002Fli>\n\u003Cli>\u003Cinput disabled=\"\" type=\"checkbox\"> Do the people who&#39;ll use it need to correct wrong answers themselves, without a developer in the loop?\u003C\u002Fli>\n\u003Cli>\u003Cinput disabled=\"\" type=\"checkbox\"> Is there a clear, separate confirmation step before the assistant writes anything back to the database?\u003C\u002Fli>\n\u003Cli>\u003Cinput disabled=\"\" type=\"checkbox\"> Can you point to which layout or table produced a given answer, for anyone who wants to verify it?\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2>FAQ\u003C\u002Fh2>\n\u003Cp>\u003Cstrong>Why not just use RAG and re-sync more often?\u003C\u002Fstrong>\nFaster syncing narrows the staleness window but never closes it, and it adds real infrastructure cost (embedding pipelines, vector storage, delete\u002Fre-ingest logic) to work around a mismatch that a live query sidesteps entirely. For data that changes hourly or daily, querying live is usually simpler than syncing constantly.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>Does this replace the FileMaker interface?\u003C\u002Fstrong>\nNo — it sits alongside it. FileMaker stays the system of record and the interface for anything more complex than a lookup; the natural-language layer handles the &quot;just tell me the number&quot; questions that otherwise interrupt someone&#39;s day.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>How is this different from asking a general chatbot to read a database export?\u003C\u002Fstrong>\nA general chatbot working from a static export has the same staleness problem RAG does, plus no way to safely write back. Querying live through the FileMaker Data API, with an explicit training layer for accuracy, is what makes this usable for a database that&#39;s actually in daily use rather than a one-off analysis.\u003C\u002Fp>\n\u003Cp>\u003Cstrong>What stops the assistant from writing bad data?\u003C\u002Fstrong>\nRecord creation is a distinct, visible action — the assistant extracts values, asks for anything missing, and the change is deployed and logged like any other configuration change, not silently triggered by a question that merely looked like a request.\u003C\u002Fp>\n\u003Ch2>The actual point\u003C\u002Fh2>\n\u003Cp>The lesson here generalizes past FileMaker: the popular architecture for &quot;AI on top of your data&quot; isn&#39;t automatically the right one for \u003Cem>your\u003C\u002Fem> data. If it changes constantly, that&#39;s a strong signal to query it live rather than index a copy of it — and to spend your effort on a way for real users to correct the AI, not on tuning a prompt nobody but a developer can touch.\u003C\u002Fp>\n","Shubham","2026-09-23",1790154024000,[18,19,20,21,22,23,24],"filemaker-ai","natural-language-query","filemaker-data-api","mcp","rag","ai-agents","klai studio","\u002Fapi\u002Fknowledge\u002Fimage\u002F499\u002F?v=55ec129be828",false,null]