<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>CatylAI — Blog</title>
    <link>https://catylai.com/blog/</link>
    <description>Field notes on AI-assisted engineering and cloud architecture.</description>
    <language>en</language>
    <lastBuildDate>Thu, 24 Sep 2026 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://catylai.com/rss.xml" rel="self" type="application/rss+xml"/>
    <item>
      <title>An AI assistant needs one door into your data, not a key to every SaaS app</title>
      <link>https://catylai.com/blog/one-door-into-the-warehouse/</link>
      <guid isPermaLink="true">https://catylai.com/blog/one-door-into-the-warehouse/</guid>
      <description>Steward gives Claude a single read-only tool over the curated warehouse, with field-level authorization compiled to Cedar. Here is why I built it that way instead of wiring up one connector per product.</description>
      <pubDate>Thu, 24 Sep 2026 00:00:00 +0000</pubDate>
      <category>agents</category>
      <category>architecture</category>
      <category>patterns</category>
    </item>
    <item>
      <title>An ADR is only as good as what actually reads it</title>
      <link>https://catylai.com/blog/an-adr-is-only-as-good-as-what-reads-it/</link>
      <guid isPermaLink="true">https://catylai.com/blog/an-adr-is-only-as-good-as-what-reads-it/</guid>
      <description>A decision record that only lives as prose is something an agent has to be told to go open. The ones that survive are the ones also wired into a table, a script, or a test the agent&apos;s normal workflow already touches.</description>
      <pubDate>Tue, 22 Sep 2026 00:00:00 +0000</pubDate>
      <category>architecture</category>
      <category>patterns</category>
      <category>claude-code</category>
    </item>
    <item>
      <title>Bedrock model access is three gates, not one permission</title>
      <link>https://catylai.com/blog/bedrock-access-three-gates/</link>
      <guid isPermaLink="true">https://catylai.com/blog/bedrock-access-three-gates/</guid>
      <description>A Bedrock AccessDeniedException can mean three different things, so we built a nightly discovery job and a runbook that checks each gate in order.</description>
      <pubDate>Tue, 22 Sep 2026 00:00:00 +0000</pubDate>
      <category>aws</category>
      <category>architecture</category>
      <category>devex</category>
    </item>
    <item>
      <title>The credential nobody watched</title>
      <link>https://catylai.com/blog/credential-nobody-watched/</link>
      <guid isPermaLink="true">https://catylai.com/blog/credential-nobody-watched/</guid>
      <description>A shared service-account token expired silently and took a production integration down for 40 hours. The fix that mattered wasn&apos;t rotation. It was making four causes of the same error distinguishable.</description>
      <pubDate>Tue, 22 Sep 2026 00:00:00 +0000</pubDate>
      <category>aws</category>
      <category>patterns</category>
      <category>devex</category>
    </item>
    <item>
      <title>I deleted five AI review agents and the reviews got better</title>
      <link>https://catylai.com/blog/deleting-five-review-agents/</link>
      <guid isPermaLink="true">https://catylai.com/blog/deleting-five-review-agents/</guid>
      <description>A five-specialist review fan-out looked thorough. One session cost $5.88 and 905 seconds for zero findings, and that&apos;s what actually changed the design.</description>
      <pubDate>Tue, 22 Sep 2026 00:00:00 +0000</pubDate>
      <category>claude-code</category>
      <category>agents</category>
      <category>ci</category>
    </item>
    <item>
      <title>A green test suite is not proof a non-programmer&apos;s edit was safe</title>
      <link>https://catylai.com/blog/designing-for-the-non-programmer-maintainer/</link>
      <guid isPermaLink="true">https://catylai.com/blog/designing-for-the-non-programmer-maintainer/</guid>
      <description>A change-tier system and a verifier that fails risky edits even when every test passes, because a green suite is not evidence the change was safe.</description>
      <pubDate>Tue, 22 Sep 2026 00:00:00 +0000</pubDate>
      <category>architecture</category>
      <category>devex</category>
      <category>ai</category>
    </item>
    <item>
      <title>Don&apos;t trust a model&apos;s arithmetic, only its tool calls</title>
      <link>https://catylai.com/blog/deterministic-math-as-a-tool-call/</link>
      <guid isPermaLink="true">https://catylai.com/blog/deterministic-math-as-a-tool-call/</guid>
      <description>Why I moved every numeric answer out of model prose and into a calculator tool call, and what a data-quality investigation taught me about trusting the output.</description>
      <pubDate>Tue, 22 Sep 2026 00:00:00 +0000</pubDate>
      <category>architecture</category>
      <category>patterns</category>
      <category>agents</category>
    </item>
    <item>
      <title>Field-level authorization for AI agents, enforced in-process</title>
      <link>https://catylai.com/blog/field-level-authorization-cedar/</link>
      <guid isPermaLink="true">https://catylai.com/blog/field-level-authorization-cedar/</guid>
      <description>Row-level access control tells an agent nothing exists. Section-level tells it the entity exists with fewer fields, and that difference changes what an agent can safely ask.</description>
      <pubDate>Tue, 22 Sep 2026 00:00:00 +0000</pubDate>
      <category>claude-code</category>
      <category>agents</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Forcing the model to do arithmetic in Python</title>
      <link>https://catylai.com/blog/forcing-the-model-to-show-its-math/</link>
      <guid isPermaLink="true">https://catylai.com/blog/forcing-the-model-to-show-its-math/</guid>
      <description>An LLM cannot be trusted to self-report whether it actually did math, so a Stop hook checks mechanically whether a real calculation tool ran first.</description>
      <pubDate>Tue, 22 Sep 2026 00:00:00 +0000</pubDate>
      <category>claude-code</category>
      <category>agents</category>
      <category>patterns</category>
    </item>
    <item>
      <title>47 ADRs on one plugin in six weeks, what amend-in-place bought us</title>
      <link>https://catylai.com/blog/forty-seven-adrs-in-six-weeks/</link>
      <guid isPermaLink="true">https://catylai.com/blog/forty-seven-adrs-in-six-weeks/</guid>
      <description>A decision log is valuable because it preserves disagreement with your past self, illustrated by ADRs that reversed their own measured evidence in place.</description>
      <pubDate>Tue, 22 Sep 2026 00:00:00 +0000</pubDate>
      <category>architecture</category>
      <category>patterns</category>
      <category>devex</category>
    </item>
    <item>
      <title>A green pipeline is not evidence</title>
      <link>https://catylai.com/blog/green-pipeline-not-evidence/</link>
      <guid isPermaLink="true">https://catylai.com/blog/green-pipeline-not-evidence/</guid>
      <description>Two load-bearing CI gates ran green for months without comparing anything, because the base image had no git and nobody noticed the difference between passing and not running.</description>
      <pubDate>Tue, 22 Sep 2026 00:00:00 +0000</pubDate>
      <category>patterns</category>
      <category>devex</category>
      <category>build</category>
    </item>
    <item>
      <title>Your infrastructure has a new client, and it pushes changes</title>
      <link>https://catylai.com/blog/infrastructure-new-client/</link>
      <guid isPermaLink="true">https://catylai.com/blog/infrastructure-new-client/</guid>
      <description>The architecture diagram for our shared AWS platform names two human actors and lists an AI coding agent&apos;s own cloud egress as a third. That&apos;s a trust-model decision, not a diagram detail.</description>
      <pubDate>Tue, 22 Sep 2026 00:00:00 +0000</pubDate>
      <category>aws</category>
      <category>architecture</category>
      <category>claude-code</category>
    </item>
    <item>
      <title>The judge that never fires</title>
      <link>https://catylai.com/blog/judge-that-never-fires/</link>
      <guid isPermaLink="true">https://catylai.com/blog/judge-that-never-fires/</guid>
      <description>A quality check the model can choose to invoke isn&apos;t weak enforcement. It&apos;s no enforcement, and the corpus behind it has a measured number to prove it.</description>
      <pubDate>Tue, 22 Sep 2026 00:00:00 +0000</pubDate>
      <category>claude-code</category>
      <category>agents</category>
      <category>patterns</category>
    </item>
    <item>
      <title>A hand-rolled agent loop that works is not a reason to keep it</title>
      <link>https://catylai.com/blog/migrating-off-a-hand-rolled-agent-loop/</link>
      <guid isPermaLink="true">https://catylai.com/blog/migrating-off-a-hand-rolled-agent-loop/</guid>
      <description>When a vendor SDK actively maintains the parts of an agent loop you built by hand, the build-vs-adopt math changes even if your version already works.</description>
      <pubDate>Tue, 22 Sep 2026 00:00:00 +0000</pubDate>
      <category>architecture</category>
      <category>agents</category>
      <category>claude-code</category>
    </item>
    <item>
      <title>One gateway, eight backends, and no MCP session in sight</title>
      <link>https://catylai.com/blog/one-gateway-nine-backends/</link>
      <guid isPermaLink="true">https://catylai.com/blog/one-gateway-nine-backends/</guid>
      <description>Why an internal MCP aggregation gateway hand-rolls raw HTTP instead of the standard SDK client, and how it disambiguates tool names across eight backends.</description>
      <pubDate>Tue, 22 Sep 2026 00:00:00 +0000</pubDate>
      <category>architecture</category>
      <category>patterns</category>
      <category>build</category>
    </item>
    <item>
      <title>A shared library across two languages needs a contract, not parity</title>
      <link>https://catylai.com/blog/shared-server-utils-two-languages/</link>
      <guid isPermaLink="true">https://catylai.com/blog/shared-server-utils-two-languages/</guid>
      <description>Running the same MCP service shape in TypeScript and Rust only works if you decide, in writing, which parts are a contract and let everything else diverge.</description>
      <pubDate>Tue, 22 Sep 2026 00:00:00 +0000</pubDate>
      <category>architecture</category>
      <category>patterns</category>
      <category>agents</category>
    </item>
    <item>
      <title>The prompt-cache floor that made the cheap model expensive</title>
      <link>https://catylai.com/blog/the-prompt-cache-floor-the-cheap-tier-never-cleared/</link>
      <guid isPermaLink="true">https://catylai.com/blog/the-prompt-cache-floor-the-cheap-tier-never-cleared/</guid>
      <description>A two-tier triage pipeline assumed its cheap model&apos;s shared prompt was cached. Real token telemetry showed it never once was.</description>
      <pubDate>Tue, 22 Sep 2026 00:00:00 +0000</pubDate>
      <category>architecture</category>
      <category>ai</category>
      <category>patterns</category>
    </item>
    <item>
      <title>What a bot vote is allowed to decide</title>
      <link>https://catylai.com/blog/what-a-bot-vote-is-allowed-to-decide/</link>
      <guid isPermaLink="true">https://catylai.com/blog/what-a-bot-vote-is-allowed-to-decide/</guid>
      <description>The architecture decision trail behind letting an AI code-review job cast a real merge approval, and the explicit line we drew around what that vote can never do alone.</description>
      <pubDate>Tue, 22 Sep 2026 00:00:00 +0000</pubDate>
      <category>architecture</category>
      <category>ai</category>
      <category>build</category>
    </item>
    <item>
      <title>Delegating to agents without losing the thread</title>
      <link>https://catylai.com/blog/delegating-to-agents-without-losing-the-thread/</link>
      <guid isPermaLink="true">https://catylai.com/blog/delegating-to-agents-without-losing-the-thread/</guid>
      <description>Fanning work out to parallel agents is easy. Staying responsible for the result is the part that needs a method.</description>
      <pubDate>Mon, 21 Sep 2026 00:00:00 +0000</pubDate>
      <category>claude-code</category>
      <category>agents</category>
    </item>
    <item>
      <title>Hosting a Claude Code marketplace on your own domain</title>
      <link>https://catylai.com/blog/hosting-a-claude-code-marketplace/</link>
      <guid isPermaLink="true">https://catylai.com/blog/hosting-a-claude-code-marketplace/</guid>
      <description>It works, but three undocumented-feeling constraints will bite you. Here they are before they do.</description>
      <pubDate>Mon, 21 Sep 2026 00:00:00 +0000</pubDate>
      <category>claude-code</category>
      <category>plugins</category>
    </item>
    <item>
      <title>Static exports do not forgive</title>
      <link>https://catylai.com/blog/static-exports-do-not-forgive/</link>
      <guid isPermaLink="true">https://catylai.com/blog/static-exports-do-not-forgive/</guid>
      <description>Four ways a Next.js static export broke during a rebuild, and what each one was actually telling me.</description>
      <pubDate>Mon, 21 Sep 2026 00:00:00 +0000</pubDate>
      <category>nextjs</category>
      <category>build</category>
    </item>
    <item>
      <title>What outlives the Terraform</title>
      <link>https://catylai.com/blog/what-outlives-the-terraform/</link>
      <guid isPermaLink="true">https://catylai.com/blog/what-outlives-the-terraform/</guid>
      <description>Moving off AWS is mostly deletion. The risk is entirely in the handful of things deletion does not cover.</description>
      <pubDate>Mon, 21 Sep 2026 00:00:00 +0000</pubDate>
      <category>infrastructure</category>
      <category>dns</category>
    </item>
  </channel>
</rss>
