<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Jose Soares</title>
    <description>The latest articles on Forem by Jose Soares (@jose_soares).</description>
    <link>https://forem.com/jose_soares</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3842988%2Fdda451c9-7880-4c9c-a399-a77dccebe28a.JPG</url>
      <title>Forem: Jose Soares</title>
      <link>https://forem.com/jose_soares</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/jose_soares"/>
    <language>en</language>
    <item>
      <title>We built an AI agent for DevOps engineers. They didn't want it.</title>
      <dc:creator>Jose Soares</dc:creator>
      <pubDate>Thu, 26 Mar 2026 12:46:21 +0000</pubDate>
      <link>https://forem.com/jose_soares/we-built-an-tool-for-devops-that-wasnt-useful-heres-what-we-are-building-instead-20gi</link>
      <guid>https://forem.com/jose_soares/we-built-an-tool-for-devops-that-wasnt-useful-heres-what-we-are-building-instead-20gi</guid>
      <description>&lt;p&gt;&lt;strong&gt;We spent months building an AI agent for Terraform. When we did user interviews with SREs and DevOps engineers, their reaction was pretty unanimous: "This looks great but not very useful to me."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This completely changed the trajectory of our startup.&lt;/p&gt;

&lt;p&gt;Here is the story of how we accidentally built the wrong product for the wrong people, and how it led us to build Grafos v2: a tool designed to help founders and SWEs survive the transition from MVP to production-grade.&lt;/p&gt;




&lt;h2&gt;
  
  
  It started as a visualisation tool
&lt;/h2&gt;

&lt;p&gt;During a hackathon a few months ago, we built the foundational blocks of Grafos.ai. Initially, it was just an infrastructure visualisation tool.&lt;/p&gt;

&lt;p&gt;As a frontend engineer, I knew nothing about Terraform. I had to go through a hardcore introduction to IaC in just one week. By week two, we had built this:&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.amazonaws.com%2Fuploads%2Farticles%2Fqkl14m5k2urq3tyaw0gi.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.amazonaws.com%2Fuploads%2Farticles%2Fqkl14m5k2urq3tyaw0gi.png" alt="First version of our terraform visualisation" width="800" height="479"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It was, let's say, "rough" but this had potential. As far as we knew, there were only a couple of decent infra visualisation tools around — Brainboard and Pluralith. The latter wasn't even maintained anymore, and users in their community were practically begging for updates.&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.amazonaws.com%2Fuploads%2Farticles%2F50vgb4f9xoydus3je8vl.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.amazonaws.com%2Fuploads%2Farticles%2F50vgb4f9xoydus3je8vl.png" alt="Updated version of the visualiser" width="800" height="522"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But we knew a read-only diagram wasn't the end goal. Now that we understood how to visualise the infrastructure, how hard could it be to build a "Lovable for infra." LLMs know how to code so plugging one in that lets you edit the graph, and translate those edits into Terraform shouldn't be too complicated.&lt;/p&gt;

&lt;p&gt;During a second hackathon, we built it. Then we productionised it and shipped Grafos v1. (You can read about the &lt;a href="https://dev.to/jose_soares/im-a-frontend-engineer-let-me-spin-up-a-scalable-gcp-backend-real-quick-4n6o"&gt;second hackathon here&lt;/a&gt;).&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.amazonaws.com%2Fuploads%2Farticles%2Fofnmsxqe2fkhm43au6dg.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.amazonaws.com%2Fuploads%2Farticles%2Fofnmsxqe2fkhm43au6dg.png" alt="The Lovable For Infra" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We thought we had built a superpower for DevOps but when we talked to actual SREs, their natural skepticism kicked in. There will never be an AI that can claim to be a better SRE than an actual senior engineer. To them our tool was just another abstraction layer to babysit. This forced us to ask who actually needs this.&lt;/p&gt;

&lt;p&gt;The answer was staring me in the face. Our ideal user wasn't an SRE. Our ideal user was a founding engineer like me.&lt;/p&gt;

&lt;p&gt;Think about the typical founding engineer today. You build a product, you host it on Vercel or Heroku, and you get some traction.&lt;/p&gt;

&lt;p&gt;You have a couple of hundred users, and they start complaining about downtime or speed dips. You know you need to migrate to a real GCP or AWS setup. You know of these clouds, but you have no idea what you actually need, let alone how to provision it safely. And you definitely cannot afford to hire a $150k/year infrastructure person yet. Your infra isn't good enough to scale, but you are stuck.&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.amazonaws.com%2Fuploads%2Farticles%2Fd956dx21bhg01mwerwcw.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.amazonaws.com%2Fuploads%2Farticles%2Fd956dx21bhg01mwerwcw.png" alt="Grafos v2 onboarding screen" width="800" height="522"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Grafos v2
&lt;/h2&gt;

&lt;p&gt;This is why we threw out our original assumptions and started working on Grafos v2.&lt;/p&gt;

&lt;p&gt;From the learnings of our first iteration, we are building a product explicitly to help productionise applications for founders who don't have an SRE. Grafos v1 already knows how to analyze and decide what your application needs. Grafos v2 actually sets up that infrastructure for you based on those requirements.&lt;/p&gt;

&lt;p&gt;Because we know the dangers of AI hallucinating cloud infrastructure, we are building v2 with a very strict, opinionated philosophy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Highly Deterministic: The system relies on hard logic for as much of the process as possible.&lt;/li&gt;
&lt;li&gt;LLMs in their lane: We only use LLMs to do what they are actually good at. Stuff like reading massive amounts of documentation and interpreting the user's plain-English intent.&lt;/li&gt;
&lt;li&gt;Fail fast to a human: Every step is transparent. If the agent isn't sure, it stops and asks the user, rather than guessing and breaking things.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We aren't trying to replace infrastructure engineers. We are empowering founders to continue their journey, scale their apps, and survive until they reach the point where they can hand it over to a DevOps team.&lt;/p&gt;




&lt;p&gt;We're a team of 4 engineers currently deep in the trenches building this. If you are a founder or engineer dreading your infrastructure migration, we are opening up an early alpha for v2 soon to help us test it. Drop your email &lt;a href="https://grafos.ai/early-access/?utm_source=dev_to" rel="noopener noreferrer"&gt;here to get on the waitlist&lt;/a&gt;, or leave a comment below.&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>devops</category>
      <category>startup</category>
      <category>terraform</category>
    </item>
    <item>
      <title>I’m a Frontend Engineer. Let me spin up a scalable GCP backend real quick.</title>
      <dc:creator>Jose Soares</dc:creator>
      <pubDate>Wed, 25 Mar 2026 11:24:12 +0000</pubDate>
      <link>https://forem.com/jose_soares/im-a-frontend-engineer-let-me-spin-up-a-scalable-gcp-backend-real-quick-4n6o</link>
      <guid>https://forem.com/jose_soares/im-a-frontend-engineer-let-me-spin-up-a-scalable-gcp-backend-real-quick-4n6o</guid>
      <description>&lt;p&gt;&lt;strong&gt;I'm a frontend engineer who had to build an AI backend, and later debug a collapsed GCP environment. Here is what those two weekends taught me about the context gap between code and infrastructure.&lt;/strong&gt;&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.amazonaws.com%2Fuploads%2Farticles%2Fkq9zrd5tb46f04n1th0r.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.amazonaws.com%2Fuploads%2Farticles%2Fkq9zrd5tb46f04n1th0r.png" alt="Peran summiting mount Toubkal" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;During a hackathon, our data engineer was near the summit of Mount Toubkal in Morocco (image above), and I was left alone to build an end-to-end AI backend. A few months later, when our CTO was away for the weekend, our staging environment collapsed.&lt;/p&gt;

&lt;p&gt;So naturally, I decided to spin up a scalable GCP backend and fix our infrastructure real quick.&lt;/p&gt;

&lt;p&gt;Okay, I didn’t build a distributed backend from scratch. But over those two weekends, I did build a working LLM agent from scratch, debug a cascade of GCP failures I’d never encountered before, untangle IAM permissions, and learn how to run production database migrations. A year ago, any one of those things would have taken me weeks, but look at me now.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Hackathon Project
&lt;/h2&gt;

&lt;p&gt;We’d just shipped the MVP of Grafos.ai as an infrastructure visualiser - a clean, interactive graph of your Terraform. Looking at it, I had a thought that felt obvious: we had a beautiful way to see infrastructure. How hard could it be to add a chat interface that allowed users to change it?&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.amazonaws.com%2Fuploads%2Farticles%2Fominzos9jmfym1w55s7h.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.amazonaws.com%2Fuploads%2Farticles%2Fominzos9jmfym1w55s7h.png" alt="Infrastructure visualiser" width="800" height="522"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The barrier to building something like this isn’t the code. It’s the time it takes to acquire the context. I’d never touched the Gemini API or written an LLM agent. I barely knew how our own FastAPI backend was wired up. Which endpoints existed, how authentication worked or how the Terraform data was stored and accessed. Under normal circumstances, that’s a week of reading documentation before writing a single line that does anything useful.&lt;/p&gt;

&lt;p&gt;So before I opened my editor, I opened Gemini and asked for a crash course. Not a general “explain LLMs to me”, I needed a specific, dense, 60-minute conversation on the Gemini API, context management, intent classification, and retry logic. The kind of briefing you’d get from a senior engineer who had 45 minutes before a flight. By the time I opened Cursor, I had enough of a mental model to know what to build.&lt;/p&gt;

&lt;p&gt;Then Cursor did something I still find uncanny. I pointed it at our FastAPI backend and started describing what I needed: an endpoint that takes a user message, loads the right Terraform context, classifies the intent, and returns a response. Cursor already knew how our authentication middleware worked, where our Terraform data lived, and how our existing endpoints were structured. I’d describe the logic, the conventions to follow, the existing code to draw from, and it’d write the implementation. I spent my two days on the design decisions, not fighting the boilerplate.&lt;/p&gt;

&lt;p&gt;I gave the UI to Lovable. Ten minutes for a chat interface I’d have spent an hour on myself. With two days on the clock, an hour was too expensive to spend on something I already knew how to build. Not worth the pride.&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.amazonaws.com%2Fuploads%2Farticles%2F4jcmdin10sy1igdohbm0.gif" 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.amazonaws.com%2Fuploads%2Farticles%2F4jcmdin10sy1igdohbm0.gif" alt="Grafos AI interface" width="600" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By the end of the second day, a user could ask a question about their Terraform, get a sensible answer, and request a PR. The agent had no memory between messages, the JSON parsing was so brittle that a malformed response could break the whole flow. When Peran came back from the mountain and looked at the code, he was not delighted. His post on &lt;a href="https://grafosai.substack.com/p/productionising-our-ai-agent-why" rel="noopener noreferrer"&gt;making it production ready&lt;/a&gt; is well worth reading if you want to know how he improved this.&lt;/p&gt;

&lt;p&gt;But it worked, and it took two days instead of two weeks. That gap comes down to how fast I was able to filter through research and documentation for the specific problem in front of me, without having to wade through everything that wasn’t relevant.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Infrastructure Outage
&lt;/h2&gt;

&lt;p&gt;A few months later, our CTO was away for the weekend and our staging environment collapsed. Fresh off the hackathon, I felt I could do it. Cursor had made me feel like I could squash any bug. So I pulled up GCP and started debugging.&lt;/p&gt;

&lt;p&gt;It was painful in a way the hackathon hadn’t been. Not because the problems were harder in isolation, but because I had no map. Every LLM was happy to help but none of them knew what our infrastructure actually looked like. Cursor had our codebase indexed. It didn’t have our GCP project, our IAM roles, our Terraform state, or any concept of what would break if I changed an Ingress setting.&lt;/p&gt;

&lt;p&gt;What followed was about six hours of whack-a-mole, where fixing one problem would immediately surface the next one hiding behind it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The first problem was that I couldn’t see any problems.&lt;/strong&gt; Our FastAPI service was returning 500 errors, but GCP Logs showed nothing. Just a clean HTTP request log with a status code and silence. It took a conversation with Gemini to understand why: a try/except block in our middleware was catching every unexpected exception and converting it into a tidy HTTPException. FastAPI received a neat error response, decided the developer had handled it, and logged nothing. GCP’s Error Reporting was completely blind. The fix was one line, but finding that it was even needed took an hour.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Once I could see errors, I hit the second problem: one of our services wasn’t responding.&lt;/strong&gt; The traceback pointed to a &lt;code&gt;ConnectionRefusedError&lt;/code&gt; trying to reach &lt;code&gt;localhost:80&lt;/code&gt;. After working through the networking layer with Gemini, I eventually found it: the GitHub Action that built and deployed that service was running docker build from the root of the monorepo instead of inside the service folder. It had been deploying the wrong Docker image to the wrong service, probably for longer than I’d realised.&lt;/p&gt;

&lt;p&gt;Fixing the Docker context fixed the build. &lt;strong&gt;But now our main app was getting a 404 back from the service, but the GCP logs were empty.&lt;/strong&gt; Not a single entry. Google’s load balancer was silently swallowing them before they ever touched the container, because the service’s Cloud Run Ingress was set to Internal. From the outside it looked like a dead service but from the inside, nothing had happened. No logs, no errors, no trace of any request ever arriving. I only figured it out by noticing a column in the Cloud Run dashboard that said “Internal” next to the service name, compared it to our production service set to “All”, and changed it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Now I was getting a 403 instead of a 404.&lt;/strong&gt; This was actually progress: the request was reaching the service, but being rejected because our main app had no authentication token. I had to write Python logic to fetch a Google Identity Token and grant the Cloud Run Invoker role to our service account. That got the services talking.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Then the app crashed because a database column didn’t exist.&lt;/strong&gt; Running the migrations job appeared to succeed, green checkmark and all, but the logs showed it had connected to &lt;code&gt;localhost:5432&lt;/code&gt; the entire time. The job’s environment variables had never been configured to point at the actual SQL instance. I ran migrations against the right database, and after a full day of debugging, the staging environment was back up.&lt;/p&gt;

&lt;p&gt;What struck me was how differently the two weekends had felt. The hackathon was hard but navigable. Every time I hit a wall, I could show Cursor the exact file it needed to understand the problem. The infrastructure outage was disorienting in a different way. I wouldn’t have been able to do it without LLMs but every conversation started from scratch. I had to describe our setup, copy-paste logs, explain what IAM roles existed and what they were supposed to do. None of them could see the blast radius of changing that Ingress rule. None of them knew which Docker image was deployed where, or that our migrations job had never been pointed at the right database. I was the only source of context, and also the one who didn’t understand the system.&lt;/p&gt;

&lt;p&gt;Six months earlier, a frontend engineer attempting to debug a Cloud Run IAM lockout would have just waited for the CTO to come back from his weekend. The reason I could do it at all was Gemini explaining GCPs logging architecture step by step and Cursor helping me write Python I’d never written. The context gap made it painful and slow in a way that the hackathon wasn’t.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this means for Grafos
&lt;/h2&gt;

&lt;p&gt;The two weekends are basically the same story told twice. In the first one, the tools worked because the context existed. Cursor had the codebase, Gemini could give me a crash course on a well-documented API. In the second one, the same tools were harder to use because the context was split. Gemini knew GCP inside out but it didn’t know our specific setup. It couldn’t see our IAM configuration, our Terraform state, or which services depended on which. Every time I hit a new failure, I had to reconstruct a new picture from scratch before Gemini could help me reason about it. The general knowledge was there but the specific context wasn’t.&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.amazonaws.com%2Fuploads%2Farticles%2Fvcj1cypymn3u2dh46ao3.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.amazonaws.com%2Fuploads%2Farticles%2Fvcj1cypymn3u2dh46ao3.png" alt="Grafos AI" width="800" height="522"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is what Grafos is built around. The whole product is a bet that infrastructure has a context problem, and that if you can make that context legible, you can give any developer the same footing with their cloud environment that Cursor gives them with their codebase. Turning thousands of lines of Terraform into an interactive graph, with an AI assistant that actually understands your state, is just solving the same problem that made the hackathon work and made the outage so much harder than it needed to be.&lt;/p&gt;

&lt;p&gt;I didn’t come out of that weekend a cloud architect but I did come out of it more certain that the era of “I can’t touch that, I’m a frontend dev” is ending.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;We originally published this on our &lt;a href="https://grafosai.substack.com/" rel="noopener noreferrer"&gt;Substack&lt;/a&gt;. I'm part of a team of 4 engineers building &lt;a href="https://grafos.ai/?utm_source=dev_to" rel="noopener noreferrer"&gt;Grafos AI&lt;/a&gt; - check it out if you're tired of debugging Terraform infrastructure in the dark without context.&lt;/em&gt;&lt;/p&gt;




</description>
      <category>ai</category>
      <category>infrastructure</category>
      <category>infrastructureascode</category>
      <category>gcp</category>
    </item>
  </channel>
</rss>
