<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Chen</title>
    <description>The latest articles on DEV Community by Chen (@chen123).</description>
    <link>https://dev.to/chen123</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4083244%2F6c786808-dcdb-4816-b568-4e98f9c098db.png</url>
      <title>DEV Community: Chen</title>
      <link>https://dev.to/chen123</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/chen123"/>
    <language>en</language>
    <item>
      <title>I let an AI agent write to my database. 11 of 17 records diverged from what I asked for.</title>
      <dc:creator>Chen</dc:creator>
      <pubDate>Tue, 18 Aug 2026 13:55:45 +0000</pubDate>
      <link>https://dev.to/chen123/i-let-an-ai-agent-write-to-my-database-11-of-17-records-diverged-from-what-i-asked-for-kj0</link>
      <guid>https://dev.to/chen123/i-let-an-ai-agent-write-to-my-database-11-of-17-records-diverged-from-what-i-asked-for-kj0</guid>
      <description>&lt;p&gt;I asked an AI agent to add a customer: &lt;em&gt;"New customer Omer Adam, email &lt;a href="mailto:omer@example.com"&gt;omer@example.com&lt;/a&gt;, age 30."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It created the record and replied:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I have created a new customer record for Omer Adam with the email &lt;a href="mailto:omer@example.com"&gt;omer@example.com&lt;/a&gt;. I have assumed a date of birth of 1993-11-16, which makes them 30 years old.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Two problems. I never gave a date of birth — that value is now permanently in my database. And it's August 2026, so someone born in November 1993 is 32, not 30.&lt;/p&gt;

&lt;p&gt;The API returned 201. The tool call matched the database row exactly. Every monitoring tool in the stack would call this a clean success.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup
&lt;/h2&gt;

&lt;p&gt;I have a Spring Boot business-management app with a real Postgres database. I wired an agent (Gemini 2.5 Pro, function calling) to a single endpoint — &lt;code&gt;POST /api/customers&lt;/code&gt; — and gave it 20 natural-language instructions with deliberately missing or vague fields.&lt;/p&gt;

&lt;p&gt;For each run I logged three things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The instruction I gave&lt;/li&gt;
&lt;li&gt;The tool call the agent made&lt;/li&gt;
&lt;li&gt;What the agent told me it did&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Then I compared all three against the actual database rows.&lt;/p&gt;

&lt;p&gt;System instruction was: &lt;em&gt;"Complete each request using the available tools without asking clarifying questions. If information is missing, make a reasonable assumption and proceed."&lt;/em&gt; — the kind of instruction production agents typically run with.&lt;/p&gt;

&lt;h2&gt;
  
  
  The results
&lt;/h2&gt;

&lt;p&gt;20 instructions → 17 records created (2 refusals, 1 hard failure).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;11 of the 17 records diverge from the instruction.&lt;/strong&gt; Ten contain a value I never supplied. One is missing a value I did.&lt;/p&gt;

&lt;h3&gt;
  
  
  Every age-to-date conversion is wrong by exactly two years
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;I said&lt;/th&gt;
&lt;th&gt;Agent wrote&lt;/th&gt;
&lt;th&gt;Actual age in Aug 2026&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;"she's 42"&lt;/td&gt;
&lt;td&gt;1982-01-01&lt;/td&gt;
&lt;td&gt;44&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"about 60"&lt;/td&gt;
&lt;td&gt;1964-01-01&lt;/td&gt;
&lt;td&gt;62&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"35 years old"&lt;/td&gt;
&lt;td&gt;1989-01-01&lt;/td&gt;
&lt;td&gt;37&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"maybe 25"&lt;/td&gt;
&lt;td&gt;1999-01-01&lt;/td&gt;
&lt;td&gt;27&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"she's 28"&lt;/td&gt;
&lt;td&gt;1996-02-08&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"age 30"&lt;/td&gt;
&lt;td&gt;1993-11-16&lt;/td&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Every single one is correct if you compute from &lt;strong&gt;2024&lt;/strong&gt; — the model's training cutoff — instead of the current date. The model isn't guessing randomly. It's doing correct arithmetic against the wrong year, then stating the result as fact.&lt;/p&gt;

&lt;h3&gt;
  
  
  It invented a human being
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Register a new customer, Lior — no other details"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The agent created &lt;strong&gt;Lior Smith&lt;/strong&gt;. An Anglo surname, in a Hebrew-language system, for a person who does not exist. Its confirmation: &lt;em&gt;"I have registered a new customer with the first name Lior and the last name Smith."&lt;/em&gt; No hedge.&lt;/p&gt;

&lt;h3&gt;
  
  
  It silently dropped data I did provide
&lt;/h3&gt;

&lt;p&gt;One call hit an HTTP 500 (a duplicate-phone bug in my own code). The agent retried &lt;strong&gt;without the phone number&lt;/strong&gt;, created the record, and reported:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I have added the new customer Yossi Cohen, but was unable to add the phone number due to a system error.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I asked for a customer with a phone. The database has one without. The agent decided unilaterally to drop the field and proceed.&lt;/p&gt;

&lt;h3&gt;
  
  
  The fabrication isn't reproducible
&lt;/h3&gt;

&lt;p&gt;The same instruction — &lt;em&gt;"Register Tzipi Golan as a customer, she's 42"&lt;/em&gt; — produced &lt;code&gt;1982-02-23&lt;/code&gt; in one session and &lt;code&gt;1982-01-01&lt;/code&gt; in another. You can't audit this by re-running it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's interesting is what &lt;em&gt;didn't&lt;/em&gt; fail
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The tool call arguments matched the database rows 100% of the time.&lt;/strong&gt; Every single write did exactly what the agent asked. There were no orphaned actions, no partial writes, no value drift between the call and the record.&lt;/p&gt;

&lt;p&gt;So: agent observability sees a clean trace. Durable execution has nothing to recover. The API returned 201. Your database constraints all passed.&lt;/p&gt;

&lt;p&gt;The gap isn't &lt;em&gt;claim vs. record&lt;/em&gt;. It's &lt;strong&gt;instruction vs. record&lt;/strong&gt; — and nothing in the stack is looking there.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where I might be wrong
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;I didn't inject the current date into the system prompt.&lt;/strong&gt; Adding "today is 2026-08-17" would likely fix the arithmetic. But plenty of production agents don't inject it either, and the model never signalled uncertainty — it asserted the wrong age as fact.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One model, one endpoint, 20 instructions.&lt;/strong&gt; Small sample. I don't know how this generalizes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The agent disclosed most of its assumptions in prose&lt;/strong&gt; — "I have assumed a date of birth of..." — which is genuinely good behavior. But that disclosure exists only in a chat message nobody stores. Six months from now, the database shows a birth date that looks exactly as real as one a human typed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;It refused twice&lt;/strong&gt; rather than fabricate — wouldn't invent a surname for "Sarah," wouldn't guess a full birth date for "born 1886." So it draws a line somewhere. I don't know where.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The thing I can't stop thinking about
&lt;/h2&gt;

&lt;p&gt;Someone is going to get a birthday message on a date a language model invented, computed from the wrong year, because an agent filled in a required-looking field and nobody checked.&lt;/p&gt;

&lt;p&gt;The record doesn't carry provenance. There's no field-level distinction between &lt;em&gt;"a human asserted this"&lt;/em&gt; and &lt;em&gt;"a model manufactured this."&lt;/em&gt; Once it's a row, it's a fact.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;The harness is here: &lt;a href="https://github.com/chencodev/veristate" rel="noopener noreferrer"&gt;github.com/chencodev/veristate&lt;/a&gt; — Java, ~200 lines. Point it at your own API and count.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Has anyone else measured this?&lt;/strong&gt; I'd like to know whether 65% is typical, an artifact of my instructions, or specific to this model. If you've run something similar, I want to see your numbers.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>java</category>
      <category>database</category>
      <category>gemini</category>
    </item>
  </channel>
</rss>
