<?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: Daniel Ferraz</title>
    <description>The latest articles on DEV Community by Daniel Ferraz (@dcoferraz).</description>
    <link>https://dev.to/dcoferraz</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%2F1675636%2F82f120f6-99af-4c96-a196-42b7660b3584.png</url>
      <title>DEV Community: Daniel Ferraz</title>
      <link>https://dev.to/dcoferraz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dcoferraz"/>
    <language>en</language>
    <item>
      <title>Giving AI Coding Agents a Memory That Argues Back</title>
      <dc:creator>Daniel Ferraz</dc:creator>
      <pubDate>Fri, 30 Oct 2026 21:09:36 +0000</pubDate>
      <link>https://dev.to/dcoferraz/giving-ai-coding-agents-a-memory-that-argues-back-26g3</link>
      <guid>https://dev.to/dcoferraz/giving-ai-coding-agents-a-memory-that-argues-back-26g3</guid>
      <description>&lt;p&gt;I'm writing a series called "Becoming a Super Engineer": a software engineer since 2013, learning to hold software, data and AI under the same belt, and writing it down as it happens.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/dcoferraz/what-ai-agents-taught-me-about-building-databricks-apps-7ni"&gt;Chapter 1&lt;/a&gt; ended with agents that only stopped repeating mistakes once a check failed on them.&lt;/p&gt;

&lt;p&gt;This chapter is about the other half of that problem: what agents remember. It's about an open-source project of mine, a knowledge base the agents read before touching anything and write back to when they're done. It taught me a lot about working with agents :)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh93ftf23kk95579md9wh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh93ftf23kk95579md9wh.png" alt="One bug given to three agents: two without memory return different correct fixes, the one with the knowledge base returns the fix the team already recorded" width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Two agents without memory, two different correct APIs. The one with memory gave back the fix we had recorded&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem: every session starts from zero
&lt;/h2&gt;

&lt;p&gt;Without persistent memory, an AI coding agent forgets everything between sessions.&lt;/p&gt;

&lt;p&gt;Monday it spends 20 minutes figuring out how the auth middleware works. Tuesday, same question, same 20 minutes. Wednesday it debugs a bug you already fixed last week, from scratch.&lt;/p&gt;

&lt;p&gt;My first pitch for a knowledge base was the obvious one: stop paying tokens to rediscover the same things.&lt;/p&gt;

&lt;p&gt;A small experiment changed my mind. More on that later.&lt;/p&gt;

&lt;p&gt;The real problem showed up in an experiment I had an AI agent run: three agents got the same money-rounding bug, in the same codebase.&lt;/p&gt;

&lt;p&gt;All three fixed it correctly.&lt;/p&gt;

&lt;p&gt;The two without the knowledge base came back with two &lt;em&gt;different&lt;/em&gt; correct fixes. One added &lt;code&gt;round_money(amount)&lt;/code&gt;. The other added &lt;code&gt;to_decimal&lt;/code&gt;, &lt;code&gt;round_money(value)&lt;/code&gt; and &lt;code&gt;percent_of(amount, pct)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The agent with the knowledge base rebuilt the fix we had already recorded: same API, same four call sites, same line numbers.&lt;/p&gt;

&lt;p&gt;All three were right. Only one matched what the team already had.&lt;/p&gt;

&lt;p&gt;That's the actual problem: drift. Each of these agents was smart enough to solve the problem, and each one solved it a little differently. Over months, that's how a codebase ends up with three ways to round money.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F72jqzhuom1wdie724m8u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F72jqzhuom1wdie724m8u.png" alt="A one-way ratchet with four steps: convention, prompt, mandatory, mechanical" width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Each step moved a rule from "please do this" to "this fails if you don't"&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The walkthrough: from asking nicely to failing loudly
&lt;/h2&gt;

&lt;p&gt;The project is called &lt;a href="https://github.com/dcoferraz/knowledge-database" rel="noopener noreferrer"&gt;knowledge-database&lt;/a&gt;. The shape is simple.&lt;/p&gt;

&lt;p&gt;A folder of dated markdown entries, in four buckets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;explorations/&lt;/code&gt;: what is true about this system&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;solutions/&lt;/code&gt;: what we did, and how&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;errors/&lt;/code&gt;: what broke, and the trap that catches it next time&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;decisions/&lt;/code&gt;: what we chose, what we rejected, and who decided&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every entry cites its evidence as &lt;code&gt;path:Lstart-Lend&lt;/code&gt;, so a claim points at real lines of code.&lt;/p&gt;

&lt;p&gt;And one loop, on every non-trivial task: read first, do the work, write back.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb8iu6t0ygjivubx2lnub.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fb8iu6t0ygjivubx2lnub.png" alt="The knowledge base: four buckets around a read, work, write-back loop, with a check gate in front" width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Read first, do the work, write back. The check makes sure nobody skips step three&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I'd been using this idea heavily in another setup before it went public. The public version, and making agents actually follow it, came together in twenty days.&lt;/p&gt;

&lt;h3&gt;
  
  
  Phase 1: conventions
&lt;/h3&gt;

&lt;p&gt;The first versions were rules written in the agent instructions. Please read the KB first. Please record what you learned.&lt;/p&gt;

&lt;p&gt;Recording started as a prompt at the end of every task ("want me to record this?"), and turned mandatory pretty quickly. I wanted to review what went into an entry, without approving every single one.&lt;/p&gt;

&lt;p&gt;Everything in this phase depended on the agent choosing to behave.&lt;/p&gt;

&lt;h3&gt;
  
  
  Phase 2: enforce or delete
&lt;/h3&gt;

&lt;p&gt;Then someone reviewed it from the outside and showed me the conventions were drifting. Index tags didn't match the entries. Entries marked &lt;code&gt;verified&lt;/code&gt; had prose instead of proof. One decision used a hypothetical code comment as its evidence.&lt;/p&gt;

&lt;p&gt;That review changed the project. The new rule was simple: enforce or delete.&lt;/p&gt;

&lt;p&gt;Every hard rule got a stable ID (KB001 to KB015 today) and a test fixture that passes or fails. A rule without an ID isn't a rule anymore. It moves to a "guidance, not checked" section.&lt;/p&gt;

&lt;p&gt;A few of my favorites:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;verified&lt;/code&gt; requires a verification block with captured output. Comments like &lt;code&gt;# should work&lt;/code&gt; get rejected&lt;/li&gt;
&lt;li&gt;citations must point at files that exist, so a deleted or renamed file fails the check&lt;/li&gt;
&lt;li&gt;a diff that touches code but not the knowledge base fails the check, and names the bucket you probably forgot&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The checks run from a zero-dependency Python CLI, a pre-commit hook, CI, and a hook at the end of every agent session.&lt;/p&gt;

&lt;h3&gt;
  
  
  Phase 3: rules that never reach the agent don't count
&lt;/h3&gt;

&lt;p&gt;A field failure showed the rules only loaded for one agent runtime, and only at the start of a session.&lt;/p&gt;

&lt;p&gt;So now a short rules block (about 240 tokens) gets injected on every single prompt, and the same rules get planted in six agent instruction files, one per runtime. Install it mid-session and it works on the very next prompt.&lt;/p&gt;

&lt;h3&gt;
  
  
  Phase 4: the audit
&lt;/h3&gt;

&lt;p&gt;Someone installed it fresh, on a workspace that wasn't a git repo, and read the docs like a new user. Thirteen findings.&lt;/p&gt;

&lt;p&gt;The verdict hurt a little: everything mechanically enforced worked. Everything at the edges didn't.&lt;/p&gt;

&lt;p&gt;The installer died halfway on a non-git folder. The rules told agents to run two scripts no install had ever copied. A staleness rule would start blocking every commit, 90 days after the entries were written, all on the same day.&lt;/p&gt;

&lt;p&gt;All thirteen got fixed in one release, plus a setup wizard and a real upgrade path.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part where my own benchmark humbled me
&lt;/h2&gt;

&lt;p&gt;Then, in a second experiment, I had an agent measure the pitch itself. The control was the same task run three times without the knowledge base, recording each answer, the tokens and the time. Then the same task with the knowledge base in place.&lt;/p&gt;

&lt;p&gt;The agent with the knowledge base cost more than the control.&lt;/p&gt;

&lt;p&gt;Both causes were my fault. Nothing told the agent what "done" looks like when the answer already exists, so it wrote a new entry anyway. And the documented way to look things up was "read the index", which cost thousands of tokens before reaching the answer.&lt;/p&gt;

&lt;p&gt;The fixes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;kb find "&amp;lt;keywords&amp;gt;"&lt;/code&gt; prints only the hits: 134 to 360 tokens instead of 2,360 to read the index&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kb show &amp;lt;entry&amp;gt;&lt;/code&gt; prints just the useful part of one entry: 279 tokens instead of 709&lt;/li&gt;
&lt;li&gt;a new rule, "reuse ends it": if an entry already answered the task, you refresh that entry and stop&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Together, reusing an answer went from about 3,000 tokens to about 400 to 650.&lt;/p&gt;

&lt;p&gt;And I rewrote the README. The old headline promised token savings that the measurements didn't support at small scale. Token savings still happen, but only when an answer gets read many times, or when the investigation behind it was expensive. The new headline is: your agents give the same answer twice, and can show their work.&lt;/p&gt;

&lt;p&gt;Profiling found one more surprise: about 55ms of a 58ms lookup was just Python starting up. So now one command returns the hits and the top fix together, and the search reads a single index file instead of every entry.&lt;/p&gt;

&lt;p&gt;My favorite bug came last. &lt;code&gt;kb find&lt;/code&gt; returned the right entries, then added a note at the bottom: "(deep scan: no title/tag/summary match)".&lt;/p&gt;

&lt;p&gt;An agent read "no match" as the verdict, ignored the verified entries listed right above it, and went off to re-derive the answer, which is exactly what the tool exists to prevent.&lt;/p&gt;

&lt;p&gt;The fix was one line of text. The note now only says where the match came from.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to give your agents a memory that holds
&lt;/h2&gt;

&lt;p&gt;If you want to try this, with my tool or your own, this is what I'd keep:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Four buckets, dated entries, evidence as &lt;code&gt;path:line&lt;/code&gt;. Explorations, solutions, errors, decisions. Every error entry records what broke and the trap that catches it next time.&lt;/li&gt;
&lt;li&gt;Read first, write back, every time. And make "reuse ends it" explicit, or agents will write duplicates.&lt;/li&gt;
&lt;li&gt;Make lookups cheap. A search that returns hits, and a "show me the fix" command. If finding the answer costs more than re-deriving it, agents will re-derive it.&lt;/li&gt;
&lt;li&gt;Enforce or delete. Every rule you care about needs a check that fails. Rules agents only &lt;em&gt;read&lt;/em&gt; will drift.&lt;/li&gt;
&lt;li&gt;Deliver the rules every prompt. Start-of-session instructions get lost.&lt;/li&gt;
&lt;li&gt;Give humans a window. The KB generates one offline HTML page where anyone can search entries and expand every citation into the actual source lines. No install.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And be honest about where it doesn't pay off: when the fact is one grep away, when the project is solo and short-lived, or when the code changes faster than you can re-verify entries. Stale memory is worse than none.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd1x1x1kwgzp9wlh7s2av.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd1x1x1kwgzp9wlh7s2av.png" alt="Three overlapping circles for software, data and AI engineering, with the AI circle highlighted and an SE shield where they meet" width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Chapter 2 lived mostly in the AI circle. Still heading for the middle :)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Soooo, what did this one teach me?
&lt;/h2&gt;

&lt;p&gt;Looking back, almost every release came from outside feedback. A reviewer, a field report, a fresh install, an experiment, a profiler, an agent misreading my own tool.&lt;/p&gt;

&lt;p&gt;So thank you to everyone who reviewed it, installed it fresh and broke it. It didn't always feel great in the moment, and it made the tool a lot better :)&lt;/p&gt;

&lt;p&gt;And the direction never changed: take something that depends on an agent choosing correctly, and turn it into something that fails loudly instead.&lt;/p&gt;

&lt;p&gt;That's the same lesson from Chapter 1, just one level up. There it was deploy traps. Here it's knowledge itself: a claim with a test attached holds up much longer than one nobody checks.&lt;/p&gt;

&lt;p&gt;For the Super Engineer path, this was the AI side getting real for me. I think a big part of the work there is designing what the agent can't skip.&lt;/p&gt;

&lt;p&gt;If you're feeling the AI fear right now, I believe this is a good place to start: you already know where your team's traps are. Write them down in a way an agent has to respect.&lt;/p&gt;

&lt;p&gt;The project is open source: &lt;a href="https://github.com/dcoferraz/knowledge-database" rel="noopener noreferrer"&gt;github.com/dcoferraz/knowledge-database&lt;/a&gt;. Issues and stories very welcome.&lt;/p&gt;

&lt;p&gt;Let me know in the comments: how do your agents remember things today? Or do they?&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>productivity</category>
      <category>programming</category>
    </item>
    <item>
      <title>What AI Agents Taught Me About Building Databricks Apps</title>
      <dc:creator>Daniel Ferraz</dc:creator>
      <pubDate>Wed, 21 Oct 2026 21:19:53 +0000</pubDate>
      <link>https://dev.to/dcoferraz/what-ai-agents-taught-me-about-building-databricks-apps-7ni</link>
      <guid>https://dev.to/dcoferraz/what-ai-agents-taught-me-about-building-databricks-apps-7ni</guid>
      <description>&lt;h1&gt;
  
  
  What AI Agents Taught Me About Building Databricks Apps
&lt;/h1&gt;

&lt;h3&gt;
  
  
  The agents wrote most of the code. Everything around it was still on me, and I think that's good news
&lt;/h3&gt;

&lt;p&gt;I've been building software since 2013.&lt;/p&gt;

&lt;p&gt;Most of that time on the frontend: React, components, the part of the product people actually touch.&lt;/p&gt;

&lt;p&gt;Then AI agents started writing code. A lot of it, and faster than me.&lt;/p&gt;

&lt;p&gt;And I had the same question I think a lot of us have right now: if the code writes itself, what am I here for?&lt;/p&gt;

&lt;p&gt;My answer so far is to make the job bigger. I'm working toward what I call a "Super Engineer": software engineering, data engineering and AI engineering under the same belt.&lt;/p&gt;

&lt;p&gt;I'm sharing it while it happens, wrong turns included :)&lt;/p&gt;

&lt;p&gt;This is one of those turns. We built a production Databricks App with AI coding agents doing a big part of the work. The code showed up fast. Getting it to run correctly took way longer.&lt;/p&gt;

&lt;p&gt;And every one of those extra hours went into knowledge the agents didn't have.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz5l24gw91q8tq5jsu8i5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz5l24gw91q8tq5jsu8i5.png" alt=" " width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The agent types faster than I ever will. So what do I bring to the table now?&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The problem: the agent writes the code, the platform decides if it runs
&lt;/h2&gt;

&lt;p&gt;Databricks Apps let you host a web app right next to your data.&lt;/p&gt;

&lt;p&gt;Users sign in with the identity they already have, every query can run as that user, and Unity Catalog decides what each person can see. For an internal tool on top of governed tables, that's pretty close to ideal.&lt;/p&gt;

&lt;p&gt;Ask an agent for "a React app with an Express API that edits these tables" and you'll have working code in an afternoon.&lt;/p&gt;

&lt;p&gt;Whether it runs is a different story. That part depends on configuration: a bundle file, user API scopes, a warehouse binding and three separate permission systems.&lt;/p&gt;

&lt;p&gt;Most mistakes there are one line long. Many fail silently, or with an error that points somewhere else -&amp;gt; and an agent that reads the error and searches the code will confidently fix the wrong thing.&lt;/p&gt;

&lt;p&gt;Our app: React plus Node/Express in one container, reading and writing Unity Catalog tables through a SQL warehouse, deployed with a Databricks Asset Bundle and promoted from dev to sqa to prd through CI.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fs3jjp4i2c7m35479p8xm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fs3jjp4i2c7m35479p8xm.png" alt="The request path of a Databricks App, from the signed-in user through the Apps proxy, the React and API container and the SQL warehouse to Unity Catalog, with the traps we hit at each step" width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;One request, five hops, and a trap waiting at almost every one of them&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The walkthrough: where it broke
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Wiring user identity
&lt;/h3&gt;

&lt;p&gt;The design is on-behalf-of-user (OBO) authentication.&lt;/p&gt;

&lt;p&gt;The Databricks proxy forwards the signed-in user's token in &lt;code&gt;X-Forwarded-Access-Token&lt;/code&gt;. The API opens a SQL session with it on every request. The app's own service principal gets &lt;code&gt;CAN_USE&lt;/code&gt; on the warehouse and nothing else.&lt;/p&gt;

&lt;p&gt;First deploy: blank user names, empty tables.&lt;/p&gt;

&lt;p&gt;hm.&lt;/p&gt;

&lt;p&gt;The code was fine. The &lt;code&gt;sql&lt;/code&gt; scope was sitting under &lt;code&gt;config:&lt;/code&gt; in the bundle, where it's silently ignored. It belongs at the app level:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;apps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;my_app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${var.deploy_app_name}&lt;/span&gt;
      &lt;span class="na"&gt;source_code_path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./&lt;/span&gt;
      &lt;span class="na"&gt;user_api_scopes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;sql&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;   &lt;span class="c1"&gt;# app level, not under config:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Declaring the scope only requests it. The workspace has to allow it and have user-token passthrough enabled, and the only real proof is the deployed app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;databricks apps get &amp;lt;app&amp;gt;   &lt;span class="c"&gt;# effective_user_api_scopes must include "sql"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Configuring environments
&lt;/h3&gt;

&lt;p&gt;We promoted to sqa and saw dev data.&lt;/p&gt;

&lt;p&gt;A committed &lt;code&gt;app.yaml&lt;/code&gt; was overriding the bundle's per-target settings, so every environment was running against the dev catalog. We deleted it and kept every environment value in the bundle targets.&lt;/p&gt;

&lt;p&gt;Then a bare warehouse id made every query return 404 (the driver needs &lt;code&gt;/sql/1.0/warehouses/&amp;lt;id&amp;gt;&lt;/code&gt;). And a catalog typo (&lt;code&gt;_qa&lt;/code&gt; instead of &lt;code&gt;_sqa&lt;/code&gt;) gave us empty screens and no error at all.&lt;/p&gt;

&lt;p&gt;These days the app logs its effective catalog, schema and warehouse at boot. That one line catches this kind of bug in seconds.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deploying
&lt;/h3&gt;

&lt;p&gt;Our first deployment pulled the code from a git branch and never started: "App process did not start within 10 minutes."&lt;/p&gt;

&lt;p&gt;A git snapshot only has tracked files, and our build output was gitignored. So we switched to the bundle and built at start:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sh"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-c"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;npm&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;ci&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;npm&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;run&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;build&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;node&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;server/dist/index.js"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next one: the pipeline went green and the app didn't change.&lt;/p&gt;

&lt;p&gt;With Asset Bundles, &lt;code&gt;bundle deploy&lt;/code&gt; uploads the code and &lt;code&gt;bundle run&lt;/code&gt; starts the new version. BUT our CI template only ran the second step for resource keys that matched its naming convention. Ours didn't.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;databricks bundle deploy &lt;span class="nt"&gt;-t&lt;/span&gt; dev
databricks bundle run &amp;lt;app-resource-key&amp;gt; &lt;span class="nt"&gt;-t&lt;/span&gt; dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The npm install had its own surprises: a corporate registry pinned in &lt;code&gt;.npmrc&lt;/code&gt; that Databricks can't reach, an &lt;code&gt;omit=optional&lt;/code&gt; setting that dropped native binaries, and a missing &lt;code&gt;package-lock.json&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Opening it to users
&lt;/h3&gt;

&lt;p&gt;Some users still saw nothing.&lt;/p&gt;

&lt;p&gt;Three permissions have to line up: app &lt;code&gt;CAN_USE&lt;/code&gt; (who can open the app), warehouse &lt;code&gt;CAN_USE&lt;/code&gt; (who can run queries), and Unity Catalog grants on each table, including &lt;code&gt;USE CATALOG&lt;/code&gt; and &lt;code&gt;USE SCHEMA&lt;/code&gt;. Each one fails on its own, and different teams usually own them.&lt;/p&gt;

&lt;p&gt;Our group check was also rejecting the right people. The workspace SCIM &lt;code&gt;/Me&lt;/code&gt; endpoint leaves out account-level groups synced from the identity provider. Running &lt;code&gt;SELECT is_account_group_member(:group)&lt;/code&gt; with the user's own token fixed it.&lt;/p&gt;

&lt;p&gt;And the first request after a quiet period sometimes failed with "Failed to open new session" while the warehouse woke up (30 seconds to five minutes on a classic one). Nothing had run yet, so retrying with backoff was safe. We added retries and a small "warehouse is starting" banner, and moving to a serverless warehouse removed most of those errors.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq9vvi3h98y7y19msasjo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq9vvi3h98y7y19msasjo.png" alt="A team wiki page the agent skipped, and a terminal where npm run preflight passes every check" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What the agents couldn't learn from a wiki
&lt;/h2&gt;

&lt;p&gt;Each of these failures was easy to fix and took hours to find.&lt;/p&gt;

&lt;p&gt;The agents hit every single one. And they kept hitting them after we wrote the fixes down. They only stopped when a check failed on the mistake.&lt;/p&gt;

&lt;p&gt;That changed how I see my own role. I think the most valuable work in this project was knowing where the traps were, and turning that into something the agent has to pass.&lt;/p&gt;

&lt;h2&gt;
  
  
  The solution: how you can skip the hard path
&lt;/h2&gt;

&lt;p&gt;Set up four things before your agent writes its first line.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Ten rules in AGENTS.md
&lt;/h3&gt;

&lt;p&gt;Put short rules in an &lt;code&gt;AGENTS.md&lt;/code&gt; (or &lt;code&gt;CLAUDE.md&lt;/code&gt;) at the repo root, where the agent reads them first:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run every query as the user. Unity Catalog is the security boundary.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;user_api_scopes: [sql]&lt;/code&gt; goes at the app level. Check &lt;code&gt;effective_user_api_scopes&lt;/code&gt; after each deploy.&lt;/li&gt;
&lt;li&gt;Three permissions must line up: app &lt;code&gt;CAN_USE&lt;/code&gt;, warehouse &lt;code&gt;CAN_USE&lt;/code&gt;, table grants.&lt;/li&gt;
&lt;li&gt;Deploy through the bundle, never a git snapshot.&lt;/li&gt;
&lt;li&gt;An app deploy is &lt;code&gt;bundle deploy&lt;/code&gt; plus &lt;code&gt;bundle run&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;No &lt;code&gt;app.yaml&lt;/code&gt;. Environment values live in bundle targets.&lt;/li&gt;
&lt;li&gt;Normalize the warehouse path to &lt;code&gt;/sql/1.0/warehouses/&amp;lt;id&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Retry session-open errors with backoff, and tell users the warehouse is waking up.&lt;/li&gt;
&lt;li&gt;Fake databases are for tests only.&lt;/li&gt;
&lt;li&gt;Every deploy failure becomes a check.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. A preflight check before the first pipeline
&lt;/h3&gt;

&lt;p&gt;Turn each trap into a lint rule in a script that exits non-zero on errors: &lt;code&gt;user_api_scopes&lt;/code&gt; under &lt;code&gt;config:&lt;/code&gt;, &lt;code&gt;git_source&lt;/code&gt;, an &lt;code&gt;app.yaml&lt;/code&gt; with environment values, a missing lockfile, a pinned registry, &lt;code&gt;omit=optional&lt;/code&gt;, a personal &lt;code&gt;/Workspace/Users/...&lt;/code&gt; root path, secrets in plain env values, two targets sharing one workspace.&lt;/p&gt;

&lt;p&gt;The script should also list what it can't check (secret bindings, scope passthrough, the three grants), so the agent tells you who owns each one.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. A template that already follows the rules
&lt;/h3&gt;

&lt;p&gt;Generating the app from a reviewed spec is way more reliable than asking an agent to remember forty rules.&lt;/p&gt;

&lt;p&gt;Ours asks for the app name, the catalog, warehouse and groups per environment, and the entities and fields. Then it generates an app with OBO sessions, group checks, cold-start retries, auditable writes, a bundle with dev, sqa and prd targets, grant scripts for the data owner, and tests that pass on day one.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. A fixed order for "I see no data"
&lt;/h3&gt;

&lt;p&gt;Check app access, then the OBO scope, the warehouse, the Unity Catalog grants, the data, and only then the UI.&lt;/p&gt;

&lt;p&gt;Most fixes in the first four are admin actions, so the agent should pass them to the owner and leave grants alone.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F63og81g8zlnla7ad9ybb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F63og81g8zlnla7ad9ybb.png" alt="Three overlapping circles for software, data and AI engineering, with an SE shield for Super Engineer where they meet" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Soooo, where does this leave me?
&lt;/h2&gt;

&lt;p&gt;After this setup, our deploys passed on the first run, and every "no data" report went through the same steps. The agents stopped asking "why won't it start?" and started asking "which admin owns this grant?"&lt;/p&gt;

&lt;p&gt;This project touched all three parts of the path I'm on: a software app, on governed data, built with AI agents.&lt;/p&gt;

&lt;p&gt;The agents did write most of the code. What made it work was understanding the platform underneath and writing that down in a way the agents had to follow.&lt;/p&gt;

&lt;p&gt;I find that really encouraging. It's work I can learn, and I believe you can too.&lt;/p&gt;

&lt;p&gt;If you're feeling that same fear about AI right now, I get it. I think there's still a lot of room for us. The job just looks a bit different.&lt;/p&gt;

&lt;p&gt;Huge thanks to the team I built this with - you know who you are :)&lt;/p&gt;

&lt;p&gt;Let me know in the comments: what are you learning next? Or which Databricks trap got you the worst?&lt;/p&gt;

&lt;p&gt;PS: everything from this article lives in bricksmith, the skill I built so my agents stop re-learning these traps. If it saves you a deploy or two, a ⭐ helps a lot :) &lt;br&gt;
&lt;a href="https://dev.tobricksmith"&gt;github.com/dcoferraz/bricksmith&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>databricks</category>
      <category>dataengineering</category>
      <category>softwareengineering</category>
    </item>
  </channel>
</rss>
