{"id":47169,"date":"2026-10-04T20:40:01","date_gmt":"2026-10-04T18:40:01","guid":{"rendered":"https:\/\/www.dbi-services.com\/blog\/?p=47169"},"modified":"2026-10-04T20:40:04","modified_gmt":"2026-10-04T18:40:04","slug":"ai-problems-are-database-problems","status":"publish","type":"post","link":"https:\/\/www.dbi-services.com\/blog\/ai-problems-are-database-problems\/","title":{"rendered":"AI problems are database problems"},"content":{"rendered":"\n<h2 id=\"h-introduction\" class=\"wp-block-heading\">Introduction<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">When discussing agentic AI, we spend a lot of time on the model. Which one should we use? How much context does it support? Can it choose the right tool? These are useful questions. But from a my perspective, there are a few others I would ask quite early. Where does the agent store its state? Who can access the information it retrieves? What happens when two agents update the same record? Can we recover after a bad change? And can we explain which data was used to produce an answer? What governance do we need to apply ?  <br>In an upcoming essay, <em>Deciding in the Storm<\/em>, I am exploring how organizations can make useful decisions while AI keeps changing. Here, I focus on the application underneath: where its knowledge and workflow state live, who may change them, and what happens when several users or agents depend on them at once. These are questions database teams already know how to investigate.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That is good news. We already have useful tools and operational experience, but we need to apply them properly.<\/p>\n\n\n\n<h2 id=\"h-what-a-knowledge-format-gives-us\" class=\"wp-block-heading\">What a knowledge format gives us<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">On 12 June 2026, Google Cloud introduced the <a href=\"https:\/\/cloud.google.com\/blog\/products\/data-analytics\/how-the-open-knowledge-format-can-improve-data-sharing\" target=\"_blank\" rel=\"noopener\">Open Knowledge Format<\/a>, or OKF. The initial specification represents knowledge as Markdown files with YAML frontmatter and conventions for linking and organizing them. Table descriptions, metric definitions, runbooks and business rules can be exchanged in a format that both people and agents can read. You can review the files, version them in Git and move them between tools.<br>I like that approach. We do not need another proprietary API just to explain what a business metric means. The <a href=\"https:\/\/github.com\/GoogleCloudPlatform\/knowledge-catalog\/blob\/main\/okf\/SPEC.md\" target=\"_blank\" rel=\"noopener\">v0.2 specification<\/a> includes provenance, verification records, lifecycle status and a <code>stale_after<\/code> timestamp. It also defines attested computations: a concept that carries both the meaning of a value and the approved method to calculate it, so a consumer can check that a figure came from the validated calculation rather than from an agent that improvised it. And it explicitly leaves storage, serving and query infrastructure to the implementation. A field can describe when knowledge becomes stale. Something still has to detect source changes, refresh that knowledge and decide how consumers handle it. Likewise, a verification record describes a check; it does not enforce access permissions.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">OKF can be part of a governed platform, including one backed by a database. The format and the operational platform have different responsibilities.<\/p>\n\n\n\n<h2 id=\"h-a-personal-second-brain-is-a-valid-architecture\" class=\"wp-block-heading\">A personal second brain is a valid architecture<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The famous LLM wiki pattern described by <a href=\"https:\/\/gist.github.com\/karpathy\/442a6bf555914893e9891c11519de94f\" target=\"_blank\" rel=\"noopener\">Andrej Karpathy<\/a> is a useful example, and it is the pattern Google says OKF formalizes: keep source material, then let an LLM build and maintain linked Markdown pages around it.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I personally use Obsidian for my own notes, and I understand the appeal. Files are easy to inspect, easy to edit and easy to move. When I work alone, I can decide how to organize the corpus and review what the agent changes. With suitable backups and control over what reaches the model, this can be a perfectly reasonable architecture.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">As the corpus grows, I can improve how I find information. Start with filenames, links, metadata and text search. I would recommend adding an index when repeated scans become inconvenient (Karpathy&#8217;s own note puts the useful limit of a plain index file at roughly a hundred sources and a few hundred pages, before a local search engine becomes worthwhile). SQLite FTS5 provides full-text search, while ordinary tables can hold document paths, tags, source revisions and indexing status. Markdown remains the authoritative content and SQLite holds a derived index that can be rebuilt from the files, as long as the indexing process detects modifications and deletions. With SQLite we have then included a database, even though there is no database server to operate. Note that the database capabilities can start inside a local application.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">SQLite is also capable of serving multiple users through an application. Its <a href=\"https:\/\/www.sqlite.org\/whentouse.html\" target=\"_blank\" rel=\"noopener\">deployment guidance<\/a> highlights workload and concurrency as deciding factors: it permits one writer at a time per database file. The number of colleagues alone does not determine when PostgreSQL becomes necessary.<\/p>\n\n\n\n<h2 id=\"h-shared-memory-becomes-an-application-data-problem\" class=\"wp-block-heading\">Shared memory becomes an application data problem<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Strictly speaking, the LLM is a model inside an application (agents are programmatic). The surrounding application supplies tools, identity, retrieval and any state it needs to retain. An application can persist information without a database: files, object storage and durable logs are all possible storage choices. The precise requirement is that state needed after a restart or a new session must be stored somewhere outside the transient computation and loaded again when required.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">What changes at team and organizational level is the set of guarantees we need around that state. A team could share reviewed documentation through Git and serve a mostly read-only corpus successfully. But consider a system where several agents update shared tasks, record approvals, remember customer-specific facts and act on behalf of users with different permissions. We now need conflict handling, authoritative versions, controlled visibility and recoverable history. Personal conventions are no longer enough to establish who may change what.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The comment thread under Karpathy&#8217;s gist is a good illustration of that evolution. By September, the people building their own versions of the pattern were reporting the same needs: write gates and proposal queues so that several clients can write without overwriting each other; provenance and verification stamps so that an unsupported answer filed into the wiki is not later treated as a source; staleness checks so that someone learns when a page stopped being true; and an MCP server in front of one canonical corpus so that different tools read and write the same memory. One contributor argued that a wiki needs to record both when a fact was true and when the system came to &#8220;believe&#8221; it, and that Markdown makes this hard. Those are database requirements, and the SQL standard has described that last one, bitemporal data, since 2011.<\/p>\n\n\n\n<h3 id=\"h-four-kinds-of-data-not-one-memory\" class=\"wp-block-heading\">Four kinds of data, not one &#8220;memory&#8221;<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">&#8220;Memory&#8221; hides several responsibilities that do not need the same home:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Kind of data<\/th><th>Examples<\/th><th>Where it can live<\/th><th>What it needs<\/th><\/tr><\/thead><tbody><tr><td>Knowledge documents<\/td><td>Runbooks, metric definitions, an OKF bundle<\/td><td>Reviewed Markdown in Git, or ingested into a database<\/td><td>Review, versioning, freshness metadata<\/td><\/tr><tr><td>Authoritative state<\/td><td>Tasks, approvals, operation revisions, customer facts<\/td><td>A transactional database<\/td><td>Concurrency control, a tight recovery objective, access rules<\/td><\/tr><tr><td>Derived retrieval data<\/td><td>Embeddings, search indexes<\/td><td>Next to the source, for example with pgvector<\/td><td>A link to the source revision, a rebuild path, the source&#8217;s access rules<\/td><\/tr><tr><td>Traces and evaluations<\/td><td>Requests, retrieved context, answers, scores<\/td><td>A tracing store<\/td><td>Its own access control, filtering and retention<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Only the second kind cannot be rebuilt from something else. That is where I would normally put the database first, keeping knowledge documents where they are most useful. The database might already sit behind an existing service; it does not have to be a new PostgreSQL instance dedicated to the agent.<br><strong>This is the argument I am making: when an organizational second brain starts coordinating work, it inherits the data-management requirements of a shared application. A database is often the most direct way to meet them.<\/strong> PostgreSQL being then my first choice for its maturity in both RDBMS and AI world as long as sovereignty advantages. This part of what we all call the vertical defensibility other and me included, talk about. <\/p>\n\n\n\n<h2 id=\"h-a-larger-context-window-does-not-replace-data-management\" class=\"wp-block-heading\">A larger context window does not replace data management<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Could we skip all of this and simply give the model everything, in a larger context window?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Sometimes more context helps. If the task requires reasoning across an entire document, retrieving a few fragments may omit something essential. I would not claim that research has established a consensus against long context.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The <a href=\"https:\/\/proceedings.mlr.press\/v267\/li25dv.html\" target=\"_blank\" rel=\"noopener\">LaRA benchmark<\/a>, published at ICML 2025, found that the choice between retrieval and long-context processing depends on the model, task, context length and retrieval characteristics. An <a href=\"https:\/\/aclanthology.org\/2024.emnlp-industry.66\/\" target=\"_blank\" rel=\"noopener\">earlier EMNLP study<\/a> found stronger average results for sufficiently resourced long-context processing on its benchmarks, with lower cost as an advantage of RAG. Neither establishes a universal winner. At the same time, <a href=\"https:\/\/www.trychroma.com\/research\/context-rot\" target=\"_blank\" rel=\"noopener\">Chroma&#8217;s context-rot report<\/a> measured 18 models degrading as input length grows, often well before the window is full, so the window size is not a reliable guide to how much of it a model uses well.<br>What recent work does support is the need to manage context deliberately. Anthropic&#8217;s <a href=\"https:\/\/www.anthropic.com\/engineering\/effective-context-engineering-for-ai-agents\" target=\"_blank\" rel=\"noopener\">context-engineering guidance<\/a> discusses selective retrieval, compaction and notes stored outside the active context. The <a href=\"https:\/\/arxiv.org\/abs\/2512.24601\" target=\"_blank\" rel=\"noopener\">Recursive Language Models paper<\/a>, first published in December 2025, explores letting a model inspect and decompose external input programmatically. My understanding is that a larger context window is another capability to evaluate but it does not remove the need to select relevant information, track its origin or keep it current.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">And even if a model could reliably process every document in the company, we would still have to decide which documents a particular user may access. More tokens do not define ownership, resolve conflicting updates or provide a recovery plan. <a href=\"TODO-ADRIEN-URL\">Deeper thoughts on the matter here<\/a>.<\/p>\n\n\n\n<h2 id=\"h-one-operation-followed-end-to-end\" class=\"wp-block-heading\">One operation, followed end to end<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The shared state is where agents differ most from a retrieval demo, so let us follow one piece of it. An agent proposes a maintenance operation: rebuild an index on a busy table during tonight&#8217;s window. A person approves it. Another agent changes the plan. Execution times out. At each step, something must be recorded and something must be checked.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>The proposal.<\/strong> The agent writes an operation record: the plan, a revision number starting at 1, and a state, awaiting approval. The plan can come from a runbook in Markdown; the operation itself is authoritative state, so it goes in the database.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>The approval.<\/strong> A person approves revision 1. The approval row names the operation, the revision and the approver, and it is written by a trusted component that authenticated that person, never by the agent. An approved flag that the agent can set is not an approval.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>The change.<\/strong> A second agent decides the window is too short and edits the plan. It read revision 1, so it updates on that condition:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; title: ; notranslate\" title=\"\">\nUPDATE operation\n   SET plan = $2,\n       revision = revision + 1,\n       state = &#039;awaiting_approval&#039;\n WHERE id = $1\n   AND revision = $3;  -- the revision this agent read\n\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">If someone changed the record in the meantime, the update touches zero rows and the agent has to read again instead of overwriting work it never saw. The edit also creates revision 2 and sends the operation back to awaiting approval: the person approved revision 1, not whatever the plan became afterwards. Depending on the operation, the same protection can come from a row lock or from serializable transactions with retry handling; PostgreSQL&#8217;s <a href=\"https:\/\/www.postgresql.org\/docs\/current\/transaction-iso.html\" target=\"_blank\" rel=\"noopener\">transaction isolation documentation<\/a> explains why the isolation level matters.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>The execution.<\/strong> Once revision 2 is approved, the execution service claims the operation in one statement, so two executors cannot both start it:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: sql; title: ; notranslate\" title=\"\">\nUPDATE operation o\n   SET state = &#039;executing&#039;,\n       attempt_id = $2\n WHERE o.id = $1\n   AND o.state = &#039;approved&#039;\n   AND EXISTS (SELECT 1\n                 FROM approval a\n                WHERE a.operation_id = o.id\n                  AND a.revision = o.revision)\nRETURNING o.revision;\n\n<\/pre><\/div>\n\n\n<p class=\"wp-block-paragraph\">Zero rows means another executor got there first, or the approved revision is no longer the current one. The service then verifies its own authority to act and only then touches the target system. The attempt identifier is recorded before the action, so the action can be recognized later.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>The timeout.<\/strong> The call to the target system times out. Maybe the rebuild never started, maybe it finished a second before the connection dropped. A database transaction cannot roll back an action performed outside it, and saving the workflow state does not make the external action atomic with the update that records its completion. So the state becomes requiring recovery, not failed and not completed. Reconciliation then asks the target: does the new index exist, and is it valid? Only then is the operation marked completed, or retried with the same attempt identifier so that a retry cannot apply the action twice. A blind retry is how an agent does the same thing twice.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>The record.<\/strong> At the end, the database holds every revision, who approved which one, every attempt and its outcome. That history cannot be rebuilt from anything else, which is why it deserves a stricter recovery objective than the embeddings.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/github.com\/statelyai\/xstate\" target=\"_blank\" rel=\"noopener\">XState<\/a> is one example of a library for expressing this logic: states, allowed transitions and guards that decide whether a transition may happen. It also saves and restores actor state, while the application supplies the persistent storage and the recovery design. A state machine helps express the process; its presence alone does not establish a security boundary. That said, I am quite fond of this project, and I think it is a significant piece of the puzzle. The responsibilities stay explicit:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Component<\/th><th>Responsibility in this example<\/th><\/tr><\/thead><tbody><tr><td>Procedure or knowledge document<\/td><td>Describe the operation, prerequisites and constraints<\/td><\/tr><tr><td>Workflow state machine<\/td><td>Define the current stage and allowed transitions<\/td><\/tr><tr><td>Database<\/td><td>Persist operation records, approvals, revisions, attempts and outcomes<\/td><\/tr><tr><td>Execution service<\/td><td>Verify authority and execute the permitted operation<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">The retrieval lab I describe below does not cover any of this. Safe autonomous writes and workflow recovery are a separate test, and the one I would want to see before an agent acts on production.<\/p>\n\n\n\n<h2 id=\"h-the-other-familiar-questions\" class=\"wp-block-heading\">The other familiar questions<\/h2>\n\n\n\n<h3 id=\"h-can-we-recover-it\" class=\"wp-block-heading\">Can we recover it<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">For a DBA, storing data is only the beginning. We also need to know how much we could lose and how long recovery would take: our RPO and RTO. PostgreSQL provides WAL and the mechanisms needed for replication and recovery. Point-in-time recovery still requires a usable base backup and the required WAL. High availability requires a configured deployment and a tested failover process. Installing PostgreSQL does not give us all of this automatically. A replica is also not a substitute for a backup: it can faithfully reproduce an unwanted change, including one an agent made. An embedding index may be reproducible, but rebuilding it takes time and can incur embedding costs.<\/p>\n\n\n\n<h3 id=\"h-how-do-we-know-the-knowledge-is-current\" class=\"wp-block-heading\">How do we know the knowledge is current<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A source document changes. Its embedding still represents the previous version. Retrieval continues to work, but it works against outdated information. CDC can tell a pipeline that source data changed. It does not regenerate the embedding by itself, and it does not make an external embedding service part of the source transaction. My approach would be to track the source revision and the embedding revision explicitly, generate the replacement, verify that it still corresponds to the intended source revision, then publish the new content and embedding together. Deletion needs the same attention: removing a source row does not remove copies from caches, downstream stores or conversation history. In <a href=\"https:\/\/www.dbi-services.com\/blog\/rag-series-embedding-versioning-with-pgvector-why-event-driven-architecture-is-a-precondition-to-ai-data-workflows\/\" target=\"_blank\" rel=\"noopener\">Embedding Versioning with pgvector<\/a>, I argued that batch re-embedding is technical debt and event-driven refresh a precondition. For data that changes and drives decisions, I still think so. The more precise rule is that the freshness the use case requires decides whether batch is enough. A documentation corpus refreshed every night may meet its target; operational data behind a time-sensitive decision will not. Declare the target, then measure the delay, including failed refreshes and deletion propagation.<\/p>\n\n\n\n<h3 id=\"h-who-is-allowed-to-retrieve-it\" class=\"wp-block-heading\">Who is allowed to retrieve it<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">PostgreSQL <a href=\"https:\/\/www.postgresql.org\/docs\/current\/ddl-rowsecurity.html\" target=\"_blank\" rel=\"noopener\">row-level security<\/a> enforces row visibility in the engine, for every application and retrieval path that reads the same tables, as long as the application does not connect with a role that bypasses it. I built and measured this in <a href=\"https:\/\/www.dbi-services.com\/blog\/ai-agents-on-sensitive-data-what-postgresql-can-enforce-and-what-it-cant\/\" target=\"_blank\" rel=\"noopener\">AI agents on sensitive data: what PostgreSQL can enforce and what it can&#8217;t<\/a>: synthetic banks, an agent answering questions over client documents, pgvector next to the data. Policies apply to the embedding tables as they do to the documents. The tenant is set inside every transaction, so it ends at commit and a pooled connection does not hand it to the next request, as long as nothing sets it at session level. But row visibility was one layer of six: column privileges, a register of what is sensitive, deterministic tokens, a gate on what leaves for the model provider, a separate vault server and the audit trail each carry part of the guarantee, and the guarantee ends where the labelling ends.<br>The database enforces the rule once the identity is set; it cannot tell whether the identity is the right one. The trusted service chooses the tenant from the authenticated user, and the agent must not be able to overwrite it, for example by running its own SQL on the same connection. On relevance, the measurements went against the usual fear: blunt redaction collapsed retrieval, while labelled tokens with entity-aware search matched raw text under the same search, the answers cited the expected documents as often, and zero detected sensitive values were sent to the model.<\/p>\n\n\n\n<h3 id=\"h-can-we-reconstruct-what-happened\" class=\"wp-block-heading\">Can we reconstruct what happened<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/github.com\/pgaudit\/pgaudit\" target=\"_blank\" rel=\"noopener\">pgAudit<\/a> records which statements ran and which objects they accessed; its optional row logging records a count, not the rows. It sees the database side of one step, not which question triggered it, what the model did with the rows, or whether the answer was right. For a RAG request I would also want a request identifier, the authenticated identity, the database role and whether it bypasses row-level security, the retrieved document identifiers and revisions, the policy version, the context actually sent, and the answer with its evaluation.<br>In the lab, I added Langfuse, self-hosted, to follow that path. Two lessons. The tracing layer is a database workload in its own right, PostgreSQL plus ClickHouse, to size, back up, secure and retain. And with evaluation scores next to the trace spans (a span is one recorded step, such as the search or the model call), a weak answer becomes a join: did the search miss the documents, or did the model ignore them?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It also stores every retrieved document once more. In the lab, a tool&#8217;s result was recorded when the tool returned, before the provider gate checked the next request, so a value the gate blocked could still reach the trace store. Tracing needs its own filtering boundary, applied before trace data leaves the application, rather than the assumption that the provider gate covers it. That variant is the next one I want to run.<\/p>\n\n\n\n<h2 id=\"h-measure-retrieval-quality-and-security-separately\" class=\"wp-block-heading\">Measure retrieval quality and security separately<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Production RAG evaluation splits the retrieval step from the generation step. For retrieval, the classic measures, recall@k, precision@k and nDCG@k, still do the job (<a href=\"https:\/\/www.dbi-services.com\/blog\/rag-series-adaptive-rag-understanding-confidence-precision-ndcg\/\" target=\"_blank\" rel=\"noopener\">Understanding Confidence, Precision and nDCG<\/a> defines them), and public benchmarks such as BEIR and MTEB still rank on nDCG@10. Their cost is a set of questions with the documents that should come back, written by someone who knows the data. Most tooling (Ragas, TruLens, DeepEval, the evaluators in Langfuse) adds measures scored by a second model acting as a judge: context precision and recall for the retrieval, faithfulness and answer relevance for the answer. Judges scale where human labels do not, but they make errors too, so I would calibrate them on a small labelled set. And each measure claims less than it seems: an answer that cites the expected documents has the right coverage, which is not proof that it is factually correct.<br>Two points matter for sensitive data. First, define the evaluation set per identity: the relevant documents that identity is permitted to retrieve. That avoids treating the exclusion of another customer&#8217;s data as a retrieval failure. Second, a judge model reads the question, the retrieved context and the answer, so it is one more place the data goes, like an external embedding service. Both belong in the same data-flow review as the model that answers. Measures computed from document identifiers need no judge at all.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Security testing needs its own checks. Does a request from tenant A ever return tenant B&#8217;s documents? Can a user change the retrieval identity? Do revoked permissions still allow access through a cache? Can retrieved content persuade an agent to use another tool with broader access? A high relevance score does not answer those questions. Unauthorized data can be extremely relevant to a query and still be forbidden. A mandatory access restriction is a requirement to satisfy; we can then work on preserving quality within it.<\/p>\n\n\n\n<h2 id=\"h-the-operational-work-still-needs-an-owner\" class=\"wp-block-heading\">The operational work still needs an owner<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A production agent depends on more than retrieval. It needs credentials, tool permissions, monitoring, deployment procedures and recovery paths, and approval before a consequential action, as in the example above. This is shared work between application teams, database teams, infrastructure and security. I would not call every one of these problems a database problem. Model reliability, prompt injection and the safety of external actions need their own controls; I discussed where the trust boundary sits for tools in <a href=\"https:\/\/www.dbi-services.com\/blog\/rag-mcp-skills-three-paradigms-for-llms-talking-to-your-database-and-why-governance-changes-everything\/\" target=\"_blank\" rel=\"noopener\">RAG, MCP, Skills, and why governance changes everything<\/a>. Database experience nevertheless covers a substantial part of the foundation.<br>Anthropic&#8217;s <a href=\"https:\/\/claude.com\/blog\/the-ai-native-sdlc-playbook\" target=\"_blank\" rel=\"noopener\">AI-native SDLC playbook<\/a> gives a concrete example of this broader work. It describes versioned artifacts such as <code>intent.md<\/code>, <code>spec.md<\/code> and <code>plan.md<\/code>, alongside review, approval gates and operational feedback, and it distinguishes advisory instructions in skills from controls enforced through executable mechanisms such as hooks. Markdown stays valuable inside the workflow; the process around it establishes who may approve a change, what can execute and where the authoritative record lives. It is a vendor&#8217;s implementation guidance, so I would evaluate its controls against the actual environment rather than treat every example as a production guarantee.<\/p>\n\n\n\n<h2 id=\"h-readiness-needs-evidence\" class=\"wp-block-heading\">Readiness needs evidence<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Readiness can be described through evidence: a restore that met the recovery objective, a failover test that included the CDC consumer, a tenant-isolation test, a measured refresh delay, a retrieval evaluation based on the intended users and data, and, for an agent that acts, a test of the timeout above. We also need to know where the data goes. Keeping PostgreSQL in Switzerland does not keep the context sent to an external model there: embedding providers, inference endpoints, judges, traces, backups and support access all belong in the assessment, and the EU AI Act and the revised Swiss data-protection law both expect us to know it. How to judge that evidence against targets an organization declared for itself, rather than against someone else&#8217;s checklist, is the subject of <em>Deciding in the Storm<\/em>.<\/p>\n\n\n\n<h2 id=\"h-conclusion\" class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">I see a useful opportunity here for database teams. We already know how to ask about consistency, permissions, recovery and operational ownership. Agentic applications give us another reason to ask those questions early.<br>A personal second brain can work well with files, search and an embedded database as needed. As it becomes a shared application, separate what it holds, define the guarantees its users depend on and choose the storage and workflow mechanisms that provide them. Keep formats such as OKF where portability and reviewable knowledge help.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Larger context windows give the model more room to work. The application still needs a reliable way to retain, update and govern the information it uses.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<p class=\"wp-block-paragraph\"><em>Related articles: <a href=\"https:\/\/www.dbi-services.com\/blog\/ai-agents-on-sensitive-data-what-postgresql-can-enforce-and-what-it-cant\/\" target=\"_blank\" rel=\"noopener\">AI agents on sensitive data: what PostgreSQL can enforce and what it can&#8217;t<\/a>; <a href=\"https:\/\/www.dbi-services.com\/blog\/rag-mcp-skills-three-paradigms-for-llms-talking-to-your-database-and-why-governance-changes-everything\/\" target=\"_blank\" rel=\"noopener\">RAG, MCP, Skills, and why governance changes everything<\/a>; <a href=\"https:\/\/www.dbi-services.com\/blog\/rag-series-embedding-versioning-with-pgvector-why-event-driven-architecture-is-a-precondition-to-ai-data-workflows\/\" target=\"_blank\" rel=\"noopener\">Embedding Versioning with pgvector<\/a>; <a href=\"https:\/\/www.dbi-services.com\/blog\/rag-series-adaptive-rag-understanding-confidence-precision-ndcg\/\" target=\"_blank\" rel=\"noopener\">Understanding Confidence, Precision and nDCG<\/a>; the Swiss PGDay 2026 talk <a href=\"https:\/\/2026.pgday.ch\/session\/388-the-cost-of-security-debt-in-postgresql-when-implementing-ai-workflows\/\" target=\"_blank\" rel=\"noopener\">&#8220;The cost of security debt in PostgreSQL when implementing AI workflows&#8221;<\/a>.<\/em><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction When discussing agentic AI, we spend a lot of time on the model. Which one should we use? How much context does it support? Can it choose the right tool? These are useful questions. But from a my perspective, there are a few others I would ask quite early. Where does the agent store [&hellip;]<\/p>\n","protected":false},"author":153,"featured_media":47530,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":"","_members_access_role":[],"_members_access_error":""},"categories":[83],"tags":[2810,77],"type_dbi":[3654,2749],"class_list":["post-47169","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-postgresql","tag-ai","tag-postgresql","type-ai","type-postgresql"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v28.5 (Yoast SEO v28.6) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>AI problems are database problems - dbi Blog<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.dbi-services.com\/blog\/ai-problems-are-database-problems\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"AI problems are database problems\" \/>\n<meta property=\"og:description\" content=\"Introduction When discussing agentic AI, we spend a lot of time on the model. Which one should we use? How much context does it support? Can it choose the right tool? These are useful questions. But from a my perspective, there are a few others I would ask quite early. Where does the agent store [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.dbi-services.com\/blog\/ai-problems-are-database-problems\/\" \/>\n<meta property=\"og:site_name\" content=\"dbi Blog\" \/>\n<meta property=\"article:published_time\" content=\"2026-10-04T18:40:01+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-10-04T18:40:04+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/10\/9abbb277-c866-40fe-9d3e-bab9724d1845.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1774\" \/>\n\t<meta property=\"og:image:height\" content=\"887\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Adrien Obernesser\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Adrien Obernesser\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"17 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/ai-problems-are-database-problems\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/ai-problems-are-database-problems\\\/\"},\"author\":{\"name\":\"Adrien Obernesser\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/#\\\/schema\\\/person\\\/fd2ab917212ce0200c7618afaa7fdbcd\"},\"headline\":\"AI problems are database problems\",\"datePublished\":\"2026-10-04T18:40:01+00:00\",\"dateModified\":\"2026-10-04T18:40:04+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/ai-problems-are-database-problems\\\/\"},\"wordCount\":3781,\"commentCount\":0,\"image\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/ai-problems-are-database-problems\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/2\\\/2026\\\/10\\\/9abbb277-c866-40fe-9d3e-bab9724d1845.png\",\"keywords\":[\"ai\",\"PostgreSQL\"],\"articleSection\":[\"PostgreSQL\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/ai-problems-are-database-problems\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/ai-problems-are-database-problems\\\/\",\"url\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/ai-problems-are-database-problems\\\/\",\"name\":\"AI problems are database problems - dbi Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/ai-problems-are-database-problems\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/ai-problems-are-database-problems\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/2\\\/2026\\\/10\\\/9abbb277-c866-40fe-9d3e-bab9724d1845.png\",\"datePublished\":\"2026-10-04T18:40:01+00:00\",\"dateModified\":\"2026-10-04T18:40:04+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/#\\\/schema\\\/person\\\/fd2ab917212ce0200c7618afaa7fdbcd\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/ai-problems-are-database-problems\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/ai-problems-are-database-problems\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/ai-problems-are-database-problems\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/2\\\/2026\\\/10\\\/9abbb277-c866-40fe-9d3e-bab9724d1845.png\",\"contentUrl\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/wp-content\\\/uploads\\\/sites\\\/2\\\/2026\\\/10\\\/9abbb277-c866-40fe-9d3e-bab9724d1845.png\",\"width\":1774,\"height\":887},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/ai-problems-are-database-problems\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Accueil\",\"item\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"AI problems are database problems\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/\",\"name\":\"dbi Blog\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/#\\\/schema\\\/person\\\/fd2ab917212ce0200c7618afaa7fdbcd\",\"name\":\"Adrien Obernesser\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/dc9316c729e50107159e0a1e631b9c1742ce8898576887d0103c83b1ca3bc9e6?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/dc9316c729e50107159e0a1e631b9c1742ce8898576887d0103c83b1ca3bc9e6?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/dc9316c729e50107159e0a1e631b9c1742ce8898576887d0103c83b1ca3bc9e6?s=96&d=mm&r=g\",\"caption\":\"Adrien Obernesser\"},\"url\":\"https:\\\/\\\/www.dbi-services.com\\\/blog\\\/author\\\/adrienobernesser\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"AI problems are database problems - dbi Blog","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.dbi-services.com\/blog\/ai-problems-are-database-problems\/","og_locale":"en_US","og_type":"article","og_title":"AI problems are database problems","og_description":"Introduction When discussing agentic AI, we spend a lot of time on the model. Which one should we use? How much context does it support? Can it choose the right tool? These are useful questions. But from a my perspective, there are a few others I would ask quite early. Where does the agent store [&hellip;]","og_url":"https:\/\/www.dbi-services.com\/blog\/ai-problems-are-database-problems\/","og_site_name":"dbi Blog","article_published_time":"2026-10-04T18:40:01+00:00","article_modified_time":"2026-10-04T18:40:04+00:00","og_image":[{"width":1774,"height":887,"url":"http:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/10\/9abbb277-c866-40fe-9d3e-bab9724d1845.png","type":"image\/png"}],"author":"Adrien Obernesser","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Adrien Obernesser","Est. reading time":"17 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.dbi-services.com\/blog\/ai-problems-are-database-problems\/#article","isPartOf":{"@id":"https:\/\/www.dbi-services.com\/blog\/ai-problems-are-database-problems\/"},"author":{"name":"Adrien Obernesser","@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/fd2ab917212ce0200c7618afaa7fdbcd"},"headline":"AI problems are database problems","datePublished":"2026-10-04T18:40:01+00:00","dateModified":"2026-10-04T18:40:04+00:00","mainEntityOfPage":{"@id":"https:\/\/www.dbi-services.com\/blog\/ai-problems-are-database-problems\/"},"wordCount":3781,"commentCount":0,"image":{"@id":"https:\/\/www.dbi-services.com\/blog\/ai-problems-are-database-problems\/#primaryimage"},"thumbnailUrl":"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/10\/9abbb277-c866-40fe-9d3e-bab9724d1845.png","keywords":["ai","PostgreSQL"],"articleSection":["PostgreSQL"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.dbi-services.com\/blog\/ai-problems-are-database-problems\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.dbi-services.com\/blog\/ai-problems-are-database-problems\/","url":"https:\/\/www.dbi-services.com\/blog\/ai-problems-are-database-problems\/","name":"AI problems are database problems - dbi Blog","isPartOf":{"@id":"https:\/\/www.dbi-services.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.dbi-services.com\/blog\/ai-problems-are-database-problems\/#primaryimage"},"image":{"@id":"https:\/\/www.dbi-services.com\/blog\/ai-problems-are-database-problems\/#primaryimage"},"thumbnailUrl":"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/10\/9abbb277-c866-40fe-9d3e-bab9724d1845.png","datePublished":"2026-10-04T18:40:01+00:00","dateModified":"2026-10-04T18:40:04+00:00","author":{"@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/fd2ab917212ce0200c7618afaa7fdbcd"},"breadcrumb":{"@id":"https:\/\/www.dbi-services.com\/blog\/ai-problems-are-database-problems\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.dbi-services.com\/blog\/ai-problems-are-database-problems\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.dbi-services.com\/blog\/ai-problems-are-database-problems\/#primaryimage","url":"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/10\/9abbb277-c866-40fe-9d3e-bab9724d1845.png","contentUrl":"https:\/\/www.dbi-services.com\/blog\/wp-content\/uploads\/sites\/2\/2026\/10\/9abbb277-c866-40fe-9d3e-bab9724d1845.png","width":1774,"height":887},{"@type":"BreadcrumbList","@id":"https:\/\/www.dbi-services.com\/blog\/ai-problems-are-database-problems\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Accueil","item":"https:\/\/www.dbi-services.com\/blog\/"},{"@type":"ListItem","position":2,"name":"AI problems are database problems"}]},{"@type":"WebSite","@id":"https:\/\/www.dbi-services.com\/blog\/#website","url":"https:\/\/www.dbi-services.com\/blog\/","name":"dbi Blog","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.dbi-services.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.dbi-services.com\/blog\/#\/schema\/person\/fd2ab917212ce0200c7618afaa7fdbcd","name":"Adrien Obernesser","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/dc9316c729e50107159e0a1e631b9c1742ce8898576887d0103c83b1ca3bc9e6?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/dc9316c729e50107159e0a1e631b9c1742ce8898576887d0103c83b1ca3bc9e6?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/dc9316c729e50107159e0a1e631b9c1742ce8898576887d0103c83b1ca3bc9e6?s=96&d=mm&r=g","caption":"Adrien Obernesser"},"url":"https:\/\/www.dbi-services.com\/blog\/author\/adrienobernesser\/"}]}},"_links":{"self":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/47169","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/users\/153"}],"replies":[{"embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/comments?post=47169"}],"version-history":[{"count":46,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/47169\/revisions"}],"predecessor-version":[{"id":47670,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/posts\/47169\/revisions\/47670"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/media\/47530"}],"wp:attachment":[{"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/media?parent=47169"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/categories?post=47169"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/tags?post=47169"},{"taxonomy":"type","embeddable":true,"href":"https:\/\/www.dbi-services.com\/blog\/wp-json\/wp\/v2\/type_dbi?post=47169"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}