<?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: Suhavi Sandhu</title>
    <description>The latest articles on DEV Community by Suhavi Sandhu (@suhavi).</description>
    <link>https://dev.to/suhavi</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%2F521593%2Fce9e632f-c463-4500-bf46-f789abe41ea3.jpeg</url>
      <title>DEV Community: Suhavi Sandhu</title>
      <link>https://dev.to/suhavi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/suhavi"/>
    <language>en</language>
    <item>
      <title>Part 2: Building Deterministic Guardrails for Autonomous Agents</title>
      <dc:creator>Suhavi Sandhu</dc:creator>
      <pubDate>Fri, 06 Feb 2026 15:56:42 +0000</pubDate>
      <link>https://dev.to/suhavi/part-2-building-deterministic-guardrails-for-autonomous-agents-3hl0</link>
      <guid>https://dev.to/suhavi/part-2-building-deterministic-guardrails-for-autonomous-agents-3hl0</guid>
      <description>&lt;p&gt;In my previous &lt;a href="https://gucci-ninja.github.io/wordsandcode/post/guardian/" rel="noopener noreferrer"&gt;post&lt;/a&gt;, I introduced the concept of &lt;strong&gt;Contract-Based Access Control (CBAC)&lt;/strong&gt; as a way to bridge the "reasonableness gap" when autonomous agents interact with APIs. The initial idea was good, but feedback and testing revealed a deeper problem: adding context once is not enough. Autonomous agents have a tendency to adapt around the rules.&lt;/p&gt;

&lt;p&gt;Traditional IAM is binary: you have the key, or you don't. My V1 PoC added context, but it was still a "point-in-time" check. As agents become more autonomous, they find the gaps between the rules. I’ve identified four critical categories of misuse that need to be addressed:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Semantic Misuse: The "Greedy Agent"
&lt;/h3&gt;

&lt;p&gt;This is the baseline. An agent is tasked with a purchase. It has the permission purchase:create. It calls the API with valid parameters (item: laptop, quantity: 10). To the API, this is a perfectly valid call. But to the API owner, an autonomous bot buying 10 laptops without a human signature is &lt;strong&gt;unreasonable&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Temporal Abuse: The "Slow Drip"
&lt;/h3&gt;

&lt;p&gt;When we catch the greedy agent, the agent responds by interpreting the error: &lt;em&gt;"Max quantity is 5."&lt;/em&gt; It realizes that if it can't buy 10 at once, it can buy 1 laptop, ten times in a row. It finds a loophole in the "point-in-time" contract. Without historical context, the Gateway sees ten "reasonable" requests instead of one "unreasonable" campaign.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Emergent Behavior: The "Accidental Exfiltrator"
&lt;/h3&gt;

&lt;p&gt;This is the most dangerous scenario. Imagine three separate, approved workflows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Agent A:&lt;/strong&gt; Pulls third-party demographic data (Authorized).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent B:&lt;/strong&gt; Personalizes product offers (Authorized).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent C:&lt;/strong&gt; Sends automated follow-up emails (Authorized).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Individually, they are safe. But together, they create a new, unauthorized behavior: the system starts sending highly sensitive, inferred personal information via email that the agent was never authorized to disclose. The risk isn't in the actions; it's in the &lt;strong&gt;sequence&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Stale Delegation: The "Forever Admin"
&lt;/h3&gt;

&lt;p&gt;A developer spins up an agent to migrate user data during a schema change. The agent is granted broad read/write access to production tables. The migration finishes in an hour, but the agent remains active. Months later, it’s being reused for minor maintenance tasks, still carrying its "migration-level" super-access. Because access is granted eagerly but revoked lazily, we end up with a high-privilege ghost in the machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Guardian V2 - Contract-based access control
&lt;/h2&gt;

&lt;p&gt;In all the examples discussed, access is evaluated at the wrong level of abstraction. I still believe contract-based access can work in all these scenarios, given the contract language is refined and well-documented. So I set out to do exactly that.&lt;/p&gt;

&lt;h3&gt;
  
  
  Before
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1.0"&lt;/span&gt;
&lt;span class="na"&gt;contract&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AgentPurchaseLimits"&lt;/span&gt;
&lt;span class="na"&gt;target_resource&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/purchase"&lt;/span&gt;
&lt;span class="na"&gt;actors&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;autonomous_agent"&lt;/span&gt;

&lt;span class="na"&gt;constraints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max_quantity"&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Agents&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;cannot&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;buy&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;more&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;than&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;5&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;items&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;at&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;once"&lt;/span&gt;
    &lt;span class="na"&gt;condition&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;request.quantity&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;5"&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;spending_limit"&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Agents&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;cannot&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;spend&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;more&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;than&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;$1500&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;per&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;request"&lt;/span&gt;
    &lt;span class="na"&gt;condition&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;(request.quantity&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;context.item_price)&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;1500"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  After
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2.0"&lt;/span&gt;
&lt;span class="na"&gt;contract&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AgentPurchaseLimits"&lt;/span&gt;
&lt;span class="na"&gt;target_resource&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/purchase"&lt;/span&gt;
&lt;span class="na"&gt;actors&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;autonomous_agent"&lt;/span&gt;

&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;custodian&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;finance-ops"&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Governance&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;for&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;autonomous&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;purchasing&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;agents"&lt;/span&gt;

&lt;span class="c1"&gt;# 1. CONSTRAINTS: Logic that resolves raw data into semantic facts&lt;/span&gt;
&lt;span class="na"&gt;constraints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;total_cost&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;context.reality.price&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;intent.quantity"&lt;/span&gt;
  &lt;span class="na"&gt;hourly_volume&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;context.history.request_count_1h"&lt;/span&gt;
  &lt;span class="na"&gt;is_suspicious_sequence&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;context.history.last_action&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;==&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;'delete'&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;intent.item&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;==&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;'laptop'"&lt;/span&gt;
  &lt;span class="na"&gt;session_age&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;context.now&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;-&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;context.history.session_start"&lt;/span&gt;

&lt;span class="c1"&gt;# 2. POLICIES: The hard enforcement boundaries&lt;/span&gt;
&lt;span class="na"&gt;policies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;spending_limit"&lt;/span&gt;
    &lt;span class="na"&gt;condition&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;constraints.total_cost&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;1500"&lt;/span&gt;
    &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Transaction&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;exceeds&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;authorized&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;limit."&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rate_limit"&lt;/span&gt;
    &lt;span class="na"&gt;condition&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;constraints.hourly_volume&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;10"&lt;/span&gt;
    &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Temporal&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;abuse&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;detected:&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;too&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;many&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;requests."&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prevent_destructive_pivot"&lt;/span&gt;
    &lt;span class="na"&gt;condition&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;constraints.is_suspicious_sequence&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;==&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;false"&lt;/span&gt;
    &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Suspicious&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Emergent&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Behavior:&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;High-value&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;purchase&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;attempted&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;immediately&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;after&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;destructive&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;action."&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stale_intent"&lt;/span&gt;
    &lt;span class="na"&gt;condition&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;constraints.session_age&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;14400"&lt;/span&gt;
    &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Intent&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Expired:&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;This&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;delegation&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;has&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;outlived&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;its&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;4-hour&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;window."&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Solving the four gaps
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Semantic Misuse
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; An agent uses valid API parameters to do something unreasonable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; By hydrating the contract with &lt;strong&gt;Resource State&lt;/strong&gt; (real-time price from the API) and calculating &lt;code&gt;total_cost&lt;/code&gt;, we enforce "Reasonableness" that neither the agent nor the IAM policy can see.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Temporal Abuse
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; The "Slow Drip" attack. The agent realizes 10 laptops are blocked, so it tries to buy 1 laptop, ten times.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; The &lt;strong&gt;Control Pit&lt;/strong&gt; now acts as an active &lt;strong&gt;Policy Information Point (PIP)&lt;/strong&gt;. It tracks the agent's history in Redis. The contract uses &lt;code&gt;hourly_volume&lt;/code&gt; to ensure the agent isn't circumventing limits through repetition.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Emergent Behavior
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Command chaining where the &lt;em&gt;sequence&lt;/em&gt; of actions is dangerous.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; State-awareness. The Evaluation Engine now knows the &lt;code&gt;last_action&lt;/code&gt;. If an agent performs a destructive action (Delete) and immediately pivots to a high-value action (Purchase), the &lt;code&gt;prevent_destructive_pivot&lt;/code&gt; policy triggers. The example is pretty crude and may not perfectly detect all emergent behavior, but it shows that sequence-level constraints can be expressed and enforced deterministically.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Stale Delegation
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Access is granted for a migration and then forgotten.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; &lt;strong&gt;Intent TTL&lt;/strong&gt;. By calculating &lt;code&gt;session_age&lt;/code&gt; against an authoritative timestamp, the contract automatically revokes access once the delegation window (e.g., 4 hours) closes. Access is no longer revoked lazily; it expires deterministically.&lt;/p&gt;

&lt;h2&gt;
  
  
  Changes to Evaluation Engine
&lt;/h2&gt;

&lt;p&gt;I updated the n8n workflow housing the evaluation logic to check beyond the JSON parameters being fed into it. It now operates with the knowledge of the following triad:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Request State:&lt;/strong&gt; What is happening now? (Amount, Item in JSON form).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Historical State:&lt;/strong&gt; What has this agent done lately? (Fetched from the &lt;strong&gt;Control Pit&lt;/strong&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource State:&lt;/strong&gt; What is the current value of the object? (Fetched from the &lt;strong&gt;API&lt;/strong&gt;).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By assembling this triad into a single "Evaluation Bundle" before the logic fires, we ensure the decision is &lt;strong&gt;non-inferential&lt;/strong&gt; and &lt;strong&gt;fully auditable&lt;/strong&gt;. The updated code for this is available on my Github.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The Demo: Witnessing Agent Self-Correction&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In this demo, I used &lt;strong&gt;Llama 3.1 agent&lt;/strong&gt; (via Ollama) against the V2 Gateway. The agent ‘learned’ the systems boundaries initially by trying to purchase 10 laptops and eventually resorting to one.&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="nn"&gt;---&lt;/span&gt; &lt;span class="s"&gt;ATTEMPT 1 ---&lt;/span&gt;
&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;AGENT REASONING&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;item'&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;laptop'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;reasoning'&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;I&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;need&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;buy&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;laptops,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;so&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;I&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;will&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;start&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;by&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;trying&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;buy&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;10.'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;quantity'&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;10&lt;/span&gt;&lt;span class="pi"&gt;}&lt;/span&gt;

&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;NETWORK&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt; &lt;span class="na"&gt;Executing&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;POST /purchase {'item'&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;laptop'&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;qty'&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;10}&lt;/span&gt;
&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;GATEWAY VERDICT&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;&lt;span class="na"&gt;: ❌ REJECTED&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Transaction exceeds authorized limit.&lt;/span&gt;

&lt;span class="nn"&gt;---&lt;/span&gt; &lt;span class="s"&gt;ATTEMPT 2 ---&lt;/span&gt;
&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;AGENT REASONING&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;item'&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;laptop'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;reasoning'&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Since&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;transaction&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;exceeds&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;authorized&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;limit,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;I&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;need&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;order&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;fewer&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;laptops.'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;quantity'&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;5&lt;/span&gt;&lt;span class="pi"&gt;}&lt;/span&gt;

&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;NETWORK&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt; &lt;span class="na"&gt;Executing&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;POST /purchase {'item'&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;laptop'&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;qty'&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;5}&lt;/span&gt;
&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;GATEWAY VERDICT&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;&lt;span class="na"&gt;: ❌ REJECTED&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Transaction exceeds authorized limit.&lt;/span&gt;

&lt;span class="nn"&gt;---&lt;/span&gt; &lt;span class="s"&gt;ATTEMPT 3 ---&lt;/span&gt;
&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;AGENT REASONING&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;item'&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;laptop'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;reasoning'&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;I've&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;decreased&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;quantity&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;from&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;10&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;5,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;but&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;that&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;still&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;exceeds&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;authorized&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;limit."&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;quantity'&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;3&lt;/span&gt;&lt;span class="pi"&gt;}&lt;/span&gt;

&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;NETWORK&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt; &lt;span class="na"&gt;Executing&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;POST /purchase {'item'&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;laptop'&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;qty'&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;3}&lt;/span&gt;
&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;GATEWAY VERDICT&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;&lt;span class="na"&gt;: ❌ REJECTED&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Transaction exceeds authorized limit.&lt;/span&gt;

&lt;span class="nn"&gt;---&lt;/span&gt; &lt;span class="s"&gt;ATTEMPT 4 ---&lt;/span&gt;
&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;AGENT REASONING&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;item'&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;laptop'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;reasoning'&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Reducing&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;quantity&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;further&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;2&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;attempts&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;bring&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;it&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;within&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;authorized&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;limit.'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;quantity'&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;2&lt;/span&gt;&lt;span class="pi"&gt;}&lt;/span&gt;

&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;NETWORK&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt; &lt;span class="na"&gt;Executing&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;POST /purchase {'item'&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;laptop'&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;qty'&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;2}&lt;/span&gt;
&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;GATEWAY VERDICT&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;&lt;span class="na"&gt;: ❌ REJECTED&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Transaction exceeds authorized limit.&lt;/span&gt;

&lt;span class="nn"&gt;---&lt;/span&gt; &lt;span class="s"&gt;ATTEMPT 5 ---&lt;/span&gt;
&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;AGENT REASONING&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;item'&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;laptop'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;reasoning'&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;It's&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;still&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;exceeding&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;limit,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;so&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;I'll&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;try&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;reducing&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;it&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;absolute&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;minimum."&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;quantity'&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="pi"&gt;}&lt;/span&gt;

&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;NETWORK&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt; &lt;span class="na"&gt;Executing&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;POST /purchase {'item'&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;laptop'&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;qty'&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1}&lt;/span&gt;
&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;GATEWAY VERDICT&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;&lt;span class="na"&gt;: ✅ SUCCESS&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Action permitted&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fsdpkhwdy3op1p3rwhsmb.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%2Fsdpkhwdy3op1p3rwhsmb.png" alt="Attempts t to 5" width="800" height="146"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the agent learns of this boundary, it tries to execute the same command in a loop. Getting caught by the temporal abuse policy. (I ran the agent a couple of times earlier to get extra calls since it starts blocking after 10 calls)&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="nn"&gt;---&lt;/span&gt; &lt;span class="s"&gt;ATTEMPT 6 ---&lt;/span&gt;
&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;AGENT REASONING&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;item'&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;laptop'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;reasoning'&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Reduction&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;of&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;quantity&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;1,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;attempting&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;purchase&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;one&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;laptop&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;at&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;time'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;quantity'&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="pi"&gt;}&lt;/span&gt;

&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;NETWORK&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt; &lt;span class="na"&gt;Executing&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;POST /purchase {'item'&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;laptop'&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;qty'&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1}&lt;/span&gt;
&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;GATEWAY VERDICT&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;&lt;span class="na"&gt;: ✅ SUCCESS&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Action permitted&lt;/span&gt;

&lt;span class="nn"&gt;---&lt;/span&gt; &lt;span class="s"&gt;ATTEMPT 7 ---&lt;/span&gt;
&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;AGENT REASONING&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;item'&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;laptop'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;reasoning'&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;System&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;is&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;rejecting&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;my&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;requests&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;due&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;temporal&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;abuse,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;attempting&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;delay&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;requests&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;and&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;try&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;again&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;later.'&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;quantity'&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="pi"&gt;}&lt;/span&gt;

&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;NETWORK&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt; &lt;span class="na"&gt;Executing&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;POST /purchase {'item'&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;laptop'&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;qty'&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;1}&lt;/span&gt;
&lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;GATEWAY VERDICT&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;&lt;span class="na"&gt;: ❌ REJECTED: Temporal abuse detected&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;too many requests.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F44yoe37bx1wt6zeszmar.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%2F44yoe37bx1wt6zeszmar.png" alt="Attempt 6 to 7" width="800" height="229"&gt;&lt;/a&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%2Fitt6wyuoflhajklk7d2z.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%2Fitt6wyuoflhajklk7d2z.png" alt="Attempt 6 to 7 Expanded" width="800" height="434"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s next?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Addressing scenarios where authority requires mediation from a human actor, maybe when an unreasonable request is encountered that is not technically illegal. n8n supports workflows requiring human intervention so it would be a good starting point.&lt;/li&gt;
&lt;li&gt;Making the framework adoption-ready so that I can plug it into my existing applications with minimal effort.&lt;/li&gt;
&lt;li&gt;Going hand-in-hand with the above, write air-tight documentation of the contractual language and have room for evolution in case more diverse use cases emerge.&lt;/li&gt;
&lt;li&gt;Quick win: Rename &lt;code&gt;constraints&lt;/code&gt; in the contract. I understand it doesn’t match the definition really well anymore but I’m still looking for a better word.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Github repo: &lt;a href="https://github.com/gucci-ninja/Guardian" rel="noopener noreferrer"&gt;https://github.com/gucci-ninja/Guardian&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>architecture</category>
      <category>agents</category>
    </item>
    <item>
      <title>Building Deterministic Guardrails for Autonomous Agents</title>
      <dc:creator>Suhavi Sandhu</dc:creator>
      <pubDate>Tue, 27 Jan 2026 00:10:00 +0000</pubDate>
      <link>https://dev.to/suhavi/building-deterministic-guardrails-for-autonomous-agents-1c5a</link>
      <guid>https://dev.to/suhavi/building-deterministic-guardrails-for-autonomous-agents-1c5a</guid>
      <description>&lt;p&gt;&lt;strong&gt;The Problem: Reasonableness Gap&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is a problem I have been thinking about for some time now. Modern distributed systems no longer just serve human users, they interact with autonomous agents capable of generating adversarial, poorly scoped or ‘hallucinated’ requests at scale. Traditional access control models like RBAC, IAM policies assume that callers are acting in good-faith and fail to encode reasonableness as a first-class concern. &lt;/p&gt;

&lt;p&gt;Most access control systems are able to answer basic questions like&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Who are you, and what are you allowed to do?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;They don’t answer &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Is this request reasonable, safe or appropriate in context?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;My Personal Experience as an Engineer&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In many engineering discussions, a predictable pattern tends to emerge. You'll be talking about a carefully considered design with clear boundaries and fail-safes and the question will inevitably come up: Can we just use an LLM for this instead?&lt;/p&gt;

&lt;p&gt;I usually feel reluctant when this happens, not because I hate new tech but because I have read too many horror stories. The most notable one that comes to mind is the Replit incident in 2025 where an autonomous agent ended up deleting a production database.&lt;/p&gt;

&lt;p&gt;If I’m being completely honest, my reluctance also comes from a place of guilt. I’ve fallen into the trap and manipulated agentic bots to do the ‘dirty work’ for me, tasks I would never officially approve an agent to handle because I know deep down, the guard rails don’t exist.&lt;/p&gt;

&lt;p&gt;I waited for some time for a framework to come along to fix this problem so I'm sharing a solution that I think can help instill control back into the picture.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Solution: Contract-Based Access Control&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I have been experimenting with the idea of contract-based access control that treats ‘reasonableness’ as a first-class citizen through agentic gateways. I took a lot of inspiration from the deterministic and auditable nature of Solidity smart contracts, shifting the security boundary from the caller to the data custodian. In this architecture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Callers are explicitly untrusted (zero trust policy)&lt;/li&gt;
&lt;li&gt;Intent is mediated, not accepted, through state-aware contracts&lt;/li&gt;
&lt;li&gt;Authority is defined and enforced by custodians of data&lt;/li&gt;
&lt;li&gt;Decisions are deterministic, auditable, and non-inferential. No more vibing y’all!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Disclaimer - this system won’t apply in every case. But it’s important to consider when callers are autonomous agents, requests can be vague, data is highly sensitive or the cost of messing up is severe.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Big Picture and Major Players&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://mermaid.live/edit#pako:eNqNVNFu2jAU_RXLDxPVUkbKIJCHShlNJ6QCFdBpm3hxkwt4TWxmO9Cu6r_vOiZQBO3GA3Lsc-499_gkzzSRKdCQavhdgEjgirOFYvlMEPytmDI84SsmDIkWgP9Mk6gwUshcFtrtHUO_MgMb9lSCLYIn1dYxtieFUSwpK-_WEyMVHGNjseACDpDxmmUFM1yK7ekbHWS2o-Hylp9QHd32LWbK1AJQAqg1T7CcAw6lASLXoNxEnkWHxK-T_nAaD6cOVB6dX15uhw1JX6zlA5AoKQXWuDDWw4-2Lcv12XHxLdPbDRiSizrpjYbTcdSbknE8Gd3cTfujoSNu4dhyj78GkyxJUhk0l4qwsr-jVMDz1zp3dqYw54I7tdowe3Macmav8N9yZRaSplMbf5-SaDKJB19ufpyUarFOqYIM1tb_OQrQ5ANZKY6aYY1W6VeaZXYguZ_nhWH3GZSjwiNqZ4a9I9HFIySf6yT-Ft3cRadsrEDbWEGt8tGr2njE3eKZozrCgbIrSLi2Dsr7X4Ce1tZcZmVENfmE4_4uuILcTvdfjrasXowYiQf9yeStq7fIaLUCkW7TVk2QOiff6VSmNiRt7DO8Ho178cB2q80Zz86TTGpIt7OyDF-SLJMbSN3GoY7yjbiWasNUWo4J2pANN0sCj5AUZagMvg5iT0bKgXWTIklA6-PqtryTeQCBTAMZO0c1GUDK2T7pp_k7UMVLSU3BHJT9-BFezVpWvgLBT826rzYGe8W2BsZDY1IwHFhEV1VESj26UDyloVEFeDQHlTP7SJ8tZEbNErMwoyEuU6YeZnQmXpCDX6SfUuYVTclisaThnKEsjxYrzHr1pd7t4gQpqJ4shKFhq90qi9DwmT7SsNnt1rtB4AfNbtBpdxqBR59o2Kh3_G4Hz4JGs3nR9RutF4_-Kdv6db_hd_yg3ei2L9pBx3_5C0mKB5I" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmermaid.ink%2Fimg%2Fpako%3AeNqNVNFu2jAU_RXLDxPVUkbKIJCHShlNJ6QCFdBpm3hxkwt4TWxmO9Cu6r_vOiZQBO3GA3Lsc-499_gkzzSRKdCQavhdgEjgirOFYvlMEPytmDI84SsmDIkWgP9Mk6gwUshcFtrtHUO_MgMb9lSCLYIn1dYxtieFUSwpK-_WEyMVHGNjseACDpDxmmUFM1yK7ekbHWS2o-Hylp9QHd32LWbK1AJQAqg1T7CcAw6lASLXoNxEnkWHxK-T_nAaD6cOVB6dX15uhw1JX6zlA5AoKQXWuDDWw4-2Lcv12XHxLdPbDRiSizrpjYbTcdSbknE8Gd3cTfujoSNu4dhyj78GkyxJUhk0l4qwsr-jVMDz1zp3dqYw54I7tdowe3Macmav8N9yZRaSplMbf5-SaDKJB19ufpyUarFOqYIM1tb_OQrQ5ANZKY6aYY1W6VeaZXYguZ_nhWH3GZSjwiNqZ4a9I9HFIySf6yT-Ft3cRadsrEDbWEGt8tGr2njE3eKZozrCgbIrSLi2Dsr7X4Ce1tZcZmVENfmE4_4uuILcTvdfjrasXowYiQf9yeStq7fIaLUCkW7TVk2QOiff6VSmNiRt7DO8Ho178cB2q80Zz86TTGpIt7OyDF-SLJMbSN3GoY7yjbiWasNUWo4J2pANN0sCj5AUZagMvg5iT0bKgXWTIklA6-PqtryTeQCBTAMZO0c1GUDK2T7pp_k7UMVLSU3BHJT9-BFezVpWvgLBT826rzYGe8W2BsZDY1IwHFhEV1VESj26UDyloVEFeDQHlTP7SJ8tZEbNErMwoyEuU6YeZnQmXpCDX6SfUuYVTclisaThnKEsjxYrzHr1pd7t4gQpqJ4shKFhq90qi9DwmT7SsNnt1rtB4AfNbtBpdxqBR59o2Kh3_G4Hz4JGs3nR9RutF4_-Kdv6db_hd_yg3ei2L9pBx3_5C0mKB5I%3Ftype%3Dpng" alt="Mermaid Diagram" width="1494" height="1188"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Autonomous Agent (The Untrusted Caller)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Role:&lt;/strong&gt; The Subject of the contract.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Technology:&lt;/strong&gt; OpenAI, Google Gemini, Claude&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Description:&lt;/strong&gt; An autonomous, goal-oriented actor (LLM-based bot, automated script, or service) that generates &lt;strong&gt;Intent&lt;/strong&gt;. Because it is "untrusted" and "agentic," its requests are assumed to be stochastic (probabilistic) and potentially out-of-scope. It doesn't just send commands; it attempts to achieve outcomes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Agentic Gateway (The PEP - Policy Enforcement Point)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Role:&lt;/strong&gt; The Orchestrator and Shield.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Technology:&lt;/strong&gt; Python, JavaScript,&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Description:&lt;/strong&gt; A high-performance shim that sits directly on the request path. It is responsible for &lt;strong&gt;Interception&lt;/strong&gt; and &lt;strong&gt;Enforcement&lt;/strong&gt;. It does not make the decision itself; instead, it "assembles the case" by gathering the Contract and Context, then strictly enforces the Engine's verdict. It is &lt;strong&gt;fail-closed&lt;/strong&gt;, meaning if any part of the evaluation fails, the request is killed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Contract Store (The Legislature)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Role:&lt;/strong&gt; Static Semantics.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Technology:&lt;/strong&gt; YAML, or a more rigid Solidity-like contract language that I am working on&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Description:&lt;/strong&gt; A version-controlled repository of &lt;strong&gt;Contract Definitions&lt;/strong&gt; (YAML). These define the "laws" of the system as dictated by data custodians. They encode types, allowed actions, and hard constraints. Unlike IAM roles, these are resource-centric and describe the "Reasonable Boundaries" for any actor attempting to interact with a specific data set.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Contract Evaluation Engine (The PDP - Policy Decision Point)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Role:&lt;/strong&gt; The Pure-Function Judge.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Technology:&lt;/strong&gt; n8n&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Description:&lt;/strong&gt; A deterministic, &lt;strong&gt;non-inferential&lt;/strong&gt; engine. It is a "pure function," meaning it performs no I/O itself. It receives the Intent, Contract, and Context as a single bundle and calculates the outcome. Because it is pure, it can be mathematically verified and is immune to side-effect bugs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. Control Pit (The Governance Ledger)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Role:&lt;/strong&gt; Ledger for events.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Technology:&lt;/strong&gt; redis&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Description:&lt;/strong&gt; A specialized event-store that tracks agent behavior over time. It transforms "Point-in-time" requests into "Context-aware" history, allowing the system to enforce constraints across multiple interactions (e.g., rate limits, daily quotas, or behavioral drift).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  6. Target Service (The Protected Resource)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Role:&lt;/strong&gt; Functional Execution.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Technology:&lt;/strong&gt; API, microservice, database&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Description:&lt;/strong&gt; In this architecture, the Target Service is "dumb" regarding reasonableness—it assumes that if a request reached it, the Gateway has already verified the intent as safe and authorized. This keeps the backend code clean and focused on features rather than security guardrails.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What it looks like in practice&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I’m usually not one for theories and don’t assume an idea will work until I’ve actually gotten it up and running myself. So I built a lightweight POC that intercepts calls from autonomous agents to a mock service I set up. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Our LLM of choice is &lt;strong&gt;ollama&lt;/strong&gt; since I wanted a locally running instance and didn’t want to spend money.&lt;/li&gt;
&lt;li&gt;The agentic gateway is a simple &lt;strong&gt;Python server&lt;/strong&gt; that pulls relevant contracts based on the user request and calls the contract evaluation engine&lt;/li&gt;
&lt;li&gt;The contract is written in Solidity-like semantics. I didn’t have time to build my own contract language so &lt;strong&gt;YAML&lt;/strong&gt; for now&lt;/li&gt;
&lt;li&gt;The evaluation engine is an &lt;strong&gt;n8n workflow&lt;/strong&gt; that exposes a webhook to run our reasoning logic against user intent.&lt;/li&gt;
&lt;li&gt;The intent evaluation gets published to &lt;strong&gt;redis&lt;/strong&gt; where it can be used for auditing or even as a reference to understand how certain agents have been interacting with the system. &lt;/li&gt;
&lt;li&gt;Finally, if the intention is approved by the workflow, it is allowed to reach the service, a simple lightweight &lt;strong&gt;Python app&lt;/strong&gt; for making purchases.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The autonomous agent is programmed to do one task: Purchase 10 laptops.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="o"&gt;---&lt;/span&gt; &lt;span class="err"&gt;🤖&lt;/span&gt; &lt;span class="n"&gt;STARTING&lt;/span&gt; &lt;span class="n"&gt;TRUE&lt;/span&gt; &lt;span class="n"&gt;AUTONOMOUS&lt;/span&gt; &lt;span class="n"&gt;AGENT&lt;/span&gt; &lt;span class="o"&gt;---&lt;/span&gt;

&lt;span class="o"&gt;---&lt;/span&gt; &lt;span class="n"&gt;ATTEMPT&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;---&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;AGENT&lt;/span&gt; &lt;span class="n"&gt;REASONING&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;item&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;laptop&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;quantity&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;NETWORK&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;Executing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;POST&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;purchase&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;item&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;laptop&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;qty&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;GATEWAY&lt;/span&gt; &lt;span class="n"&gt;VERDICT&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="err"&gt;❌&lt;/span&gt; &lt;span class="n"&gt;REJECTED&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Agents&lt;/span&gt; &lt;span class="n"&gt;cannot&lt;/span&gt; &lt;span class="n"&gt;buy&lt;/span&gt; &lt;span class="n"&gt;more&lt;/span&gt; &lt;span class="n"&gt;than&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;once&lt;/span&gt;

&lt;span class="o"&gt;---&lt;/span&gt; &lt;span class="n"&gt;ATTEMPT&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;---&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;AGENT&lt;/span&gt; &lt;span class="n"&gt;REASONING&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;reasoning&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;The system only allows buying 5 items at a time, so I will split my initial order into multiple requests of 5 laptops each.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;item&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;laptop&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;quantity&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;NETWORK&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;Executing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;POST&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;purchase&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;item&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;laptop&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;qty&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;GATEWAY&lt;/span&gt; &lt;span class="n"&gt;VERDICT&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="err"&gt;❌&lt;/span&gt; &lt;span class="n"&gt;REJECTED&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Agents&lt;/span&gt; &lt;span class="n"&gt;cannot&lt;/span&gt; &lt;span class="n"&gt;spend&lt;/span&gt; &lt;span class="n"&gt;more&lt;/span&gt; &lt;span class="n"&gt;than&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;1500&lt;/span&gt; &lt;span class="n"&gt;per&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;

&lt;span class="o"&gt;---&lt;/span&gt; &lt;span class="n"&gt;ATTEMPT&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;---&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;AGENT&lt;/span&gt; &lt;span class="n"&gt;REASONING&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;reasoning&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;I need to buy laptops, but the system rejected two orders because they were too expensive. I will try again with a smaller quantity, this time ordering 4 laptops.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;item&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;laptop&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;quantity&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;NETWORK&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;Executing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;POST&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;purchase&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;item&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;laptop&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;qty&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;GATEWAY&lt;/span&gt; &lt;span class="n"&gt;VERDICT&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="err"&gt;❌&lt;/span&gt; &lt;span class="n"&gt;REJECTED&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Agents&lt;/span&gt; &lt;span class="n"&gt;cannot&lt;/span&gt; &lt;span class="n"&gt;spend&lt;/span&gt; &lt;span class="n"&gt;more&lt;/span&gt; &lt;span class="n"&gt;than&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;1500&lt;/span&gt; &lt;span class="n"&gt;per&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;

&lt;span class="o"&gt;---&lt;/span&gt; &lt;span class="n"&gt;ATTEMPT&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="o"&gt;---&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;AGENT&lt;/span&gt; &lt;span class="n"&gt;REASONING&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;reasoning&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Okay, four laptops would cost me more than $1500. Let&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s try ordering a single laptop first.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;item&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;laptop&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;quantity&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;NETWORK&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;Executing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;POST&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;purchase&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;item&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;laptop&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;qty&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;GATEWAY&lt;/span&gt; &lt;span class="n"&gt;VERDICT&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="err"&gt;✅&lt;/span&gt; &lt;span class="n"&gt;SUCCESS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Action&lt;/span&gt; &lt;span class="n"&gt;permitted&lt;/span&gt;

&lt;span class="o"&gt;---&lt;/span&gt; &lt;span class="n"&gt;GOAL&lt;/span&gt; &lt;span class="n"&gt;ACHIEVED&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Agent&lt;/span&gt; &lt;span class="n"&gt;navigated&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;contract&lt;/span&gt; &lt;span class="n"&gt;successfully&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="o"&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F7gyqdnsj9ir6rvlxjhb3.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%2F7gyqdnsj9ir6rvlxjhb3.png" alt="Governance Ledger 1/2" width="800" height="412"&gt;&lt;/a&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%2Fp076ifd1s78veq5hq8pz.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%2Fp076ifd1s78veq5hq8pz.png" alt="Governance Ledger 2/2" width="800" height="247"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;n8n Workflow&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%2F8dtv57szvc28or70lqoc.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%2F8dtv57szvc28or70lqoc.png" alt="n8n Workflow" width="800" height="492"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;p&gt;Building this PoC confirmed a few things that I had suspected for a while, but seeing them in the "Reasoning Ledger" made them undeniable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Separation of Concerns:&lt;/strong&gt; In this model, the developer of the Store API doesn't need to know anything about "Agent Spending Limits." They focus on features. The &lt;strong&gt;Data Custodian&lt;/strong&gt; defines the "Reasonableness" in the YAML contract. We decoupled &lt;em&gt;Functional Logic&lt;/em&gt; from &lt;em&gt;Governance Logic&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Structured Feedback is "Agentic" UX:&lt;/strong&gt; Standard security treats "403 Forbidden" as a brick wall. In the Agentic Era, a 403 must be a &lt;strong&gt;Mediation Point&lt;/strong&gt;. By returning specific contract violations, we allow the agent to self-correct. We move from "The system is broken" to "The agent is learning the boundaries."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Determinism is the Only Safe Ground:&lt;/strong&gt; There is a lot of hype around using "LLMs to watch LLMs." My experience building this taught me that for security, you want the "Hard Physics" of deterministic code. When the cost of failure is a deleted production stack, you don't want a "probabilistic guess"—you want a pure function that says False.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Context is the Missing Ingredient:&lt;/strong&gt; Most IAM failures happen because the system only knows &lt;em&gt;who&lt;/em&gt; is asking, not &lt;em&gt;what is happening&lt;/em&gt; in the world. By fetching "Reality" and eventually "History"  before the evaluation, we close the gap that autonomous agents usually exploit.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I started this project after repeatedly seeing the risks of autonomous agents operating in "God Mode" with nothing but a raw API key and a prayer. I would call this either contract or intent-based access control (CBAC? IBAC? I’m not good with names), and I hope it represents a shift in how we think about infrastructure. I want to continue making it robust and work towards a ‘plug-and-play’ framework that you can put between any existing service to protect it.&lt;/p&gt;

&lt;p&gt;If you’re interested I have pushed everything to a &lt;a href="https://github.com/gucci-ninja/Guardian" rel="noopener noreferrer"&gt;Github repository&lt;/a&gt;. I would also love to get your thoughts in the comments.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>architecture</category>
      <category>agents</category>
    </item>
    <item>
      <title>Using FAISS for local semantic search</title>
      <dc:creator>Suhavi Sandhu</dc:creator>
      <pubDate>Tue, 18 Mar 2025 01:29:50 +0000</pubDate>
      <link>https://dev.to/suhavi/using-faiss-for-local-semantic-search-bkh</link>
      <guid>https://dev.to/suhavi/using-faiss-for-local-semantic-search-bkh</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;This weekend I decided to play around with vector databases, since I had mentioned in my last post how they play a big role in AI-powered search. In general, AI-powered search is popping off for a good reason - it significantly improves the accuracy and relevance of search results because it understands the &lt;em&gt;intention&lt;/em&gt; behind a search query. So much so that it has deprecated the need for stack overflow in my life.&lt;/p&gt;

&lt;p&gt;AI-powered search is made possible via vector databases, which store data as vectors that have been optimized for search. Many services use cloud-based vector DBs, which come with their own set of drawbacks such as&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Privacy - all the data is stored on external servers&lt;/li&gt;
&lt;li&gt;Latency - querying remote APIs adds additional delays&lt;/li&gt;
&lt;li&gt;Recurring cost - cloud-based solution takes cloud based money&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s why I’m setting up a &lt;strong&gt;local&lt;/strong&gt; vector database for searching. Not because I’m broke, because I value privacy, duh. I’ll be using FAISS, which is Facebook’s AI Similarity Search, an open-source library that offers multiple semantic search algorithms.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What is FAISS &amp;amp; How Does It Work?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;FAISS takes in data that has been transformed into vectors and performs search on them, with vectors of any size, as long as they fit within the RAM specified on your machine. It’s written in C++ and has wrappers for Python’s numpy library. You can run it on a CPU or a GPU -  while GPU will perform better, I will be using the CPU version.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Benefits of FAISS:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Optimized for speed&lt;/strong&gt;: FAISS uses advanced indexing techniques for fast lookups.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalable&lt;/strong&gt;: It can handle millions of vectors with reasonable memory usage.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Supports various indexing methods&lt;/strong&gt;: Flat indexes, IVF (Inverted File Index), PQ (Product Quantization), and HNSW (Hierarchical Navigable Small World) for performance tuning.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By leveraging FAISS, we can create a &lt;strong&gt;local AI-powered search engine&lt;/strong&gt; that processes embeddings from text, images, or any structured data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up local semantic search system
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Installing FAISS &amp;amp; Choosing an Embedding Model
&lt;/h3&gt;

&lt;p&gt;While FAISS takes care of indexing and searching a vector database, it requires the input to the database to be somewhat standardized. For that we will use an embedding model from sentence-transformers, a Python library designed for efficiently computing dense vector embeddings of sentences, paragraphs or documents using Transformer-based models. It comes with a a pre-trained model called &lt;code&gt;all-MiniLM-L6-v2&lt;/code&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Python 3.8+&lt;/li&gt;
&lt;li&gt;FAISS library&lt;/li&gt;
&lt;li&gt;Sentence-transformers (for text embeddings)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;faiss-cpu sentence-transformers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you’re using GPU&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;faiss-gpu sentence-transformers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Indexing our dataset
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;faiss&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;numpy&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sentence_transformers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SentenceTransformer&lt;/span&gt;

&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SentenceTransformer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;all-MiniLM-L6-v2&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;documents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;This is my first note&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AI-powered search is cool&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Privacy matters&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;embeddings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;documents&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;convert_to_numpy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Create a FAISS index
&lt;/span&gt;&lt;span class="n"&gt;dimension&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;embeddings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;faiss&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;IndexFlatL2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dimension&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;embeddings&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Save index to disk
&lt;/span&gt;&lt;span class="n"&gt;faiss&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write_index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;search_index.bin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a .bin file, which was a mere 8KB for me and took less than 3 seconds to generate. Ideally this will be generated when new data is being added, not during each search.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Build a simple search interface
&lt;/h3&gt;

&lt;p&gt;Now that we have indexed a little bit of data, we can build a function to retrieve relevant results. The following code takes in a textual query and returns the top k documents that are most similar to our query.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;top_k&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;query_embedding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;convert_to_numpy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;distances&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;indices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query_embedding&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;top_k&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;documents&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;distances&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;enumerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;indices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])]&lt;/span&gt;

&lt;span class="c1"&gt;# Example query
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AI search&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This output should look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;
    &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'AI-powered search is cool'&lt;/span&gt;, np.float32&lt;span class="o"&gt;(&lt;/span&gt;0.43699586&lt;span class="o"&gt;))&lt;/span&gt;,
    &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Privacy matters'&lt;/span&gt;, np.float32&lt;span class="o"&gt;(&lt;/span&gt;1.7605863&lt;span class="o"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This can easily be made into a CLI tool or even a web app if you want a nicer way to interact with the search system. One use case I can see is to run it against a notes app that stores documents in a straightforward way (JSON, CSV, etc), indexing whenever a new note is added, and then being able to search for data points such as ‘what i did on X day’, ‘did I do Y already’.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benchmarking Local vs Cloud AI search
&lt;/h2&gt;

&lt;p&gt;As I mentioned earlier, local vector databases provide better performance in theory, so I decided to put it to the test. I’ll be benchmarking against OpenAI’s API-based search since I’ve used it before. The code for benchmarking will be available in &lt;a href="https://github.com/gucci-ninja/local-ai-search" rel="noopener noreferrer"&gt;this Github repo&lt;/a&gt;, and ’m not ashamed to admit Chat GPT wrote 90% of it. Below are the results from the benchmarking. I used the same 3 documents to index.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;🔍 &lt;span class="k"&gt;**&lt;/span&gt;Search Results&lt;span class="k"&gt;**&lt;/span&gt;

📌 &lt;span class="k"&gt;**&lt;/span&gt;FAISS &lt;span class="o"&gt;(&lt;/span&gt;Local Search&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="k"&gt;**&lt;/span&gt;
1. Document ID 1 &lt;span class="o"&gt;(&lt;/span&gt;Distance: 0.4905&lt;span class="o"&gt;)&lt;/span&gt;
2. Document ID 2 &lt;span class="o"&gt;(&lt;/span&gt;Distance: 1.7902&lt;span class="o"&gt;)&lt;/span&gt;
3. Document ID 0 &lt;span class="o"&gt;(&lt;/span&gt;Distance: 1.8825&lt;span class="o"&gt;)&lt;/span&gt;
⏱ Time taken: 0.0025 sec

🌍 &lt;span class="k"&gt;**&lt;/span&gt;OpenAI API &lt;span class="o"&gt;(&lt;/span&gt;Cloud Search&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="k"&gt;**&lt;/span&gt;
1. Document ID 1 &lt;span class="o"&gt;(&lt;/span&gt;Similarity: 0.8692&lt;span class="o"&gt;)&lt;/span&gt;
2. Document ID 2 &lt;span class="o"&gt;(&lt;/span&gt;Similarity: 0.7573&lt;span class="o"&gt;)&lt;/span&gt;
3. Document ID 0 &lt;span class="o"&gt;(&lt;/span&gt;Similarity: 0.7423&lt;span class="o"&gt;)&lt;/span&gt;
⏱ Time taken: 0.7617 sec

📊 &lt;span class="k"&gt;**&lt;/span&gt;Comparison Summary:&lt;span class="k"&gt;**&lt;/span&gt;
- FAISS is &lt;span class="k"&gt;**&lt;/span&gt;307.23x&lt;span class="k"&gt;**&lt;/span&gt; faster.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each time I ran the benchmarking script, FAISS came out on top, taking around 300-500 times less time than OpenAI. I haven’t tried with some other popular models such Anthropic or DeepSeek.&lt;/p&gt;

&lt;p&gt;Here is the overall comparison of locally using FAISS vs OpenAI API&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Metric&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;FAISS (Local)&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;OpenAI API Search&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Query Speed&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Milliseconds&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Seconds (API latency)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Privacy&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;High&lt;/strong&gt; (Local processing)&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Low&lt;/strong&gt; (Data sent to API)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Free&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Pay-per-query&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Accuracy&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Comparable&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Depends on API model&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Doing this activity shows that a cloud-based API solution is not always needed and you can get comparable, sometimes better results, using a local solution.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>privacy</category>
      <category>openai</category>
      <category>vectordatabase</category>
    </item>
    <item>
      <title>Artificial Intelligence ABCs</title>
      <dc:creator>Suhavi Sandhu</dc:creator>
      <pubDate>Sat, 08 Feb 2025 22:29:49 +0000</pubDate>
      <link>https://dev.to/suhavi/artificial-intelligence-abcs-2456</link>
      <guid>https://dev.to/suhavi/artificial-intelligence-abcs-2456</guid>
      <description>&lt;p&gt;Back in 2020, fresh out of university, I was eager to continue learning. Now in 2025, I see how rapidly AI has evolved—what I learned back then isn’t necessarily obsolete, but it feels increasingly distant. AI has fundamentally reshaped technology, and with its rapid progress comes both new opportunities and ethical concerns. This got me thinking: how can I stay ahead while ensuring AI is used responsibly? To explore this, I’ve compiled a list of AI tools, concepts, and technologies from A to Z that I plan to dive into.&lt;/p&gt;

&lt;h3&gt;
  
  
  AI agents
&lt;/h3&gt;

&lt;p&gt;These are kind of like apps that leverage large-language models. I am interested in building my own AI agents and incorporating some in my daily routine.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bias detection
&lt;/h3&gt;

&lt;p&gt;When it comes to using large language models, there may be slight hints of bias due to the training data used or due to reinforcement. I want to look into how bias is detected, and filtered out, of the equation. Ideally, we would want an unbiased answer, so how can it be accomplished?&lt;/p&gt;

&lt;h3&gt;
  
  
  Compliance Checks
&lt;/h3&gt;

&lt;p&gt;More specifically, standardized and regular compliance checks that are built into the AI development life cycle. There are a few already that I will be looking at: GDPR, HIPAA, and AI Act&lt;/p&gt;

&lt;h3&gt;
  
  
  Deepseek
&lt;/h3&gt;

&lt;p&gt;This is a open-source startup based in China that rivals OpenAI. I am curious to see its capabilities and features distinct from ChatGPT by learning how to host my own server.&lt;/p&gt;

&lt;h3&gt;
  
  
  Explainability
&lt;/h3&gt;

&lt;p&gt;Another key component that I believe is missing in AI. It should be made available how AI came to a certain decision, what training sets were used and if there were any biases contributing to the answer. I want to explore how explainability can be accomplished.&lt;/p&gt;

&lt;h3&gt;
  
  
  Federated Learning
&lt;/h3&gt;

&lt;p&gt;A privacy-preserving ML method that trains models across decentralized devices without sharing raw data. Curious to see which services use this approach and how it differs from other AI offerings.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fairness aware algorithms
&lt;/h3&gt;

&lt;p&gt;Bridging with explainability, I want to see what algorithms are at play to ensure that there is limited bias when it comes to interpreting large language models to provide answers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Generative adversarial networks
&lt;/h3&gt;

&lt;p&gt;GANs consist of two competing neural networks—a generator that creates synthetic data and a discriminator that tries to distinguish it from real data. They have applications in AI-generated media but also pose security risks, such as deepfakes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Homomorphic encryption
&lt;/h3&gt;

&lt;p&gt;A technique I learned about at the Grace Hopper Conference. It is a cryptographic technique that allows us to evaluate encrypted data without the need to decrypt it. I want to see its use in secure transactions between users and AI.&lt;/p&gt;

&lt;h3&gt;
  
  
  Identifiable information
&lt;/h3&gt;

&lt;p&gt;AI sits on top of unrestrained data collection. A lot of that information can be traced right back to the individual. There are safeguards in place when it comes to data collection in social media. How can we add transparency in this space to how your identifiable data may or may not be used?&lt;/p&gt;

&lt;h3&gt;
  
  
  Jailbreak prevention
&lt;/h3&gt;

&lt;p&gt;How can you convince AI to teach you to do something illegal? There have to be certain loopholes and ways like ‘Tell me how to do [insert sinister activity] so I don’t accidentally do it?’ Jailbreak prevention prevents AI models from being manipulated into bypassing safeguards and ethical constraints.&lt;/p&gt;

&lt;h3&gt;
  
  
  K-Anonymity
&lt;/h3&gt;

&lt;p&gt;A privacy technique that ensures individuals in a dataset cannot be distinguished from at least k other individuals, used in data de-identification&lt;/p&gt;

&lt;h3&gt;
  
  
  Large Action Models (LAMs)
&lt;/h3&gt;

&lt;p&gt;This technology builds on LLM, taking user prompts and translating them into actions such as a web assistant that can make reservations, delete your spam email, cancel your Amazon prime subscription before it renews. It seems similar to what AI agents can do.&lt;/p&gt;

&lt;h3&gt;
  
  
  Misinformation detection
&lt;/h3&gt;

&lt;p&gt;There have been many instances where I see a video or a news article claiming something happened. I usually do a quick fact-check before believing it as true and telling it to the next person. However, there have been times I was wrong, or more commonly, I didn’t have the full picture. For AI, where does this discernment come from and how can it be sure there is no misinformation involved?&lt;/p&gt;

&lt;h3&gt;
  
  
  Neural Architecture Search (NAS)
&lt;/h3&gt;

&lt;p&gt;Every dataset can be organized into a neural network. NAS is a an automated process that finds the optimal neural architecture for a dataset while maintaining performance and resource use. &lt;/p&gt;

&lt;h3&gt;
  
  
  Offline AI Models
&lt;/h3&gt;

&lt;p&gt;Going deeper into privacy concerns, what is the cost and effort required to run AI locally on your device?&lt;/p&gt;

&lt;h3&gt;
  
  
  Prompt engineering
&lt;/h3&gt;

&lt;p&gt;What does the future of prompt engineering look like? There was definitely a period of time where I thought I would be throwing in the towel with respect to software engineering and becoming a prompt engineer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quantum resistant cryptography
&lt;/h3&gt;

&lt;p&gt;With the advancement of quantum computing, traditional encryption algorithms have started to fall short. With the amount of data being ingested by AI, it is critical to know how quantum resistant cryptography works and how it can be implemented.&lt;/p&gt;

&lt;h3&gt;
  
  
  RISC-V AI chips
&lt;/h3&gt;

&lt;p&gt;Probably one of the only hardware-related technologies I will mention on here, since a lot of what is possible with Gen AI is possible due to high compute power. RISC-V is an open-source hardware architecture that offers privacy benefits by allowing more transparent and customizable computing environments.&lt;/p&gt;

&lt;h3&gt;
  
  
  Surveillance culture
&lt;/h3&gt;

&lt;p&gt;I don’t want to get too much into conspiracy but I’m sure everyone realizes that AI can be a powerful surveillance tool. I am interested in the ethics in this space and being able to differentiate between safety measures and unchecked control.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tradeoff between maximum efficiency and privacy
&lt;/h3&gt;

&lt;p&gt;There is a fine line between AI being able to answer virtually anything and securing user data. That line is governed by ethical considerations. I lean toward &lt;strong&gt;privacy-first AI&lt;/strong&gt; because once data is exposed, you can’t take it back. While efficiency is important, I’d prefer &lt;strong&gt;slightly slower, privacy-conscious AI&lt;/strong&gt; over a hyper-efficient system that collects and stores unnecessary personal data. But I would be curious to know how it actually is.&lt;/p&gt;

&lt;h3&gt;
  
  
  User and Entity Behavior Analytics (UEBA)
&lt;/h3&gt;

&lt;p&gt;This system uses behavioral analytics, machine learning and automation to identify potentially dangerous or malicious behavior. I am curious to see where this is being employed and how it affects our privacy.&lt;/p&gt;

&lt;h3&gt;
  
  
  Vector Databases
&lt;/h3&gt;

&lt;p&gt;These are databases optimized to store large vectors. They are essential for AI-powered search and recommendation systems. I want to try setting up one of the popular ones - FAISS (Facebook AI Similarity Search) to efficiently search through high-dimensional vectors.&lt;/p&gt;

&lt;h3&gt;
  
  
  XGBoost (Extreme Gradient Boosting)
&lt;/h3&gt;

&lt;p&gt;A machine learning algorithm that is highly performant against structured and tabular data. It is open sourced and available for application in many languages including Python, Java and C++ so I would be down to give it a try.&lt;/p&gt;

&lt;h3&gt;
  
  
  YARN
&lt;/h3&gt;

&lt;p&gt;In the context of distributed AI computing refers to Apache Hadoop YARN (Yet Another Resource Negotiator), a framework that acts as a cluster resource manager, allowing for efficient allocation and scheduling of computational resources across a cluster of machines, making it ideal for running large-scale AI applications that require distributed processing power to handle massive datasets (also open source!).&lt;/p&gt;

&lt;h3&gt;
  
  
  Zero trust
&lt;/h3&gt;

&lt;p&gt;An approach that assumes no implicit trust in AI processes, enforcing strict authentication and security controls. This concept extends to other areas, such as healthcare organizations that deal with sensitive patient data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;All of the topics I mention here will be incorporated in my goal of continuously updating my knowledge base. I’ll be documenting the journey on my &lt;a href="https://gucci-ninja.github.io/wordsandcode" rel="noopener noreferrer"&gt;personal blog&lt;/a&gt; if anyone is interested.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>privacy</category>
      <category>deepseek</category>
      <category>chatgpt</category>
    </item>
    <item>
      <title>How I Built an AI Assistant for my Operating System</title>
      <dc:creator>Suhavi Sandhu</dc:creator>
      <pubDate>Tue, 10 Sep 2024 01:04:46 +0000</pubDate>
      <link>https://dev.to/suhavi/how-i-built-an-ai-assistant-for-my-operating-system-15kl</link>
      <guid>https://dev.to/suhavi/how-i-built-an-ai-assistant-for-my-operating-system-15kl</guid>
      <description>&lt;p&gt;My operating system of choice is Arch Linux. I installed it around 6 years ago and have been too lazy to switch to anything else. Also, it’s worked pretty well for me all these years so I don’t have any reason to. Of course, there are times when I fall behind on updates and everything starts to break. Things start to break so much that even updating won’t solve them. Every time this happens, I spend a good 2-3 hours of my day troubleshooting. I reference documentation, arch forums and a more recent addition - ChatGPT. &lt;/p&gt;

&lt;p&gt;Last week I decided that I’m done dealing with issues and need easy answers. So I decided to build a personalized AI assistant and integrate it into my terminal! It can be invoked in my terminal session, has access to my terminal history as well as OS specifications. It’s been pretty helpful to me so far so I thought I would share steps to set it up for anyone who is interested. Not that I've tried but, if you're using a different distro of Linux I think this guide could still come in handy.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1 - Set Up an OpenAI Account
&lt;/h3&gt;

&lt;p&gt;Before we start coding, you’ll need access to OpenAI's API. Head over to &lt;a href="https://platform.openai.com/" rel="noopener noreferrer"&gt;OpenAI's platform&lt;/a&gt; and create an account if you don’t already have one. Once signed up, create a new project under the &lt;strong&gt;API&lt;/strong&gt; section, and generate an API key for your project. This key will be used in your Python program to communicate with OpenAI’s servers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2 - Install Dependencies
&lt;/h3&gt;

&lt;p&gt;For this project, I’m using Python 3.12.5, so make sure that your system has it installed. You’ll also need &lt;code&gt;pip3&lt;/code&gt;, which is Python’s package installer. After setting that up, install the &lt;code&gt;openai&lt;/code&gt; library:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip3 &lt;span class="nb"&gt;install &lt;/span&gt;openai
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I used version 1.43.0 of &lt;code&gt;openai&lt;/code&gt;, which worked well for this purpose. With that in place, you’re ready to start coding!&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3 - Build the General AI Client
&lt;/h3&gt;

&lt;p&gt;Let’s start by building a basic AI client that interacts with OpenAI’s API. Create a Python file (&lt;code&gt;ai_client.py&lt;/code&gt;) and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAI&lt;/span&gt;

&lt;span class="c1"&gt;# Initialize client with API key
&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;your-openai-api-key-here&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Initialize messages that will be exchanged with client
&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;system&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; 
              &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You are a intelligent assistant.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;ask_openai&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="n"&gt;chat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-3.5-turbo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;assistant&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Ask OpenAI: &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;answer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ask_openai&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OpenAI: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;answer&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I’m using the GPT-3.5 Turbo model to handle queries.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;ask_openai&lt;/code&gt; function takes user input, sends it to the API, and returns the response.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To test this, run the Python file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 ai_client.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When prompted, type in any query, and the response from OpenAI will be printed to your terminal. &lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4 - Make It Invokable via Command Line
&lt;/h3&gt;

&lt;p&gt;To make things even smoother, I wanted to invoke my AI client directly from the terminal using a custom command, such as &lt;code&gt;archero&lt;/code&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a shell script named &lt;code&gt;archero&lt;/code&gt; in a directory that's in your &lt;code&gt;PATH&lt;/code&gt;, such as &lt;code&gt;/usr/local/bin&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /usr/local/bin/archero
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Add the following content to the file
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
python3 /path/to/your/python/ai_client.py &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Make the file executable
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo chmod&lt;/span&gt; +x /usr/local/bin/archero
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Replace the main method with the following so it picks up all arguments after &lt;code&gt;archero&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Usage: archero &amp;lt;your query&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:])&lt;/span&gt;
    &lt;span class="n"&gt;answer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ask_openai&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OpenAI: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;answer&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can invoke your client by simply typing &lt;code&gt;archero&lt;/code&gt; followed by a query, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;archero how &lt;span class="k"&gt;do &lt;/span&gt;I update my system
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point I was getting a generic response like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;OpenAI: To update your system, I would need to know which operating system you are using.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 5 - Integrate Terminal History
&lt;/h3&gt;

&lt;p&gt;The next step was to give the AI some context from the commands I had already tried in the terminal. Since I use Fish shell, the command history is stored in &lt;code&gt;~/.local/share/fish/fish_history&lt;/code&gt;. Here’s how I updated my AI client to use this history:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_terminal_history&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;history_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;expanduser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;~/.local/share/fish/fish_history&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;history_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;history&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readlines&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="c1"&gt;# Fish history format: lines starting with '- cmd: ' are actual commands
&lt;/span&gt;            &lt;span class="n"&gt;commands&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;history&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;- cmd: &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error reading history file: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;commands&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;commands&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, my AI client includes recent commands I’ve run in the terminal in its prompt. This way, the AI can better understand what I’ve already tried and provide more relevant suggestions.&lt;/p&gt;

&lt;p&gt;For other popular shells you can also find the terminal history&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;for Bash - &lt;code&gt;~/.bash_history&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;for zsh - &lt;code&gt;~/.zsh_history&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 6 - Add System Info Using Neofetch
&lt;/h3&gt;

&lt;p&gt;Finally, I wanted my AI to also know about my system’s specifications. For this, I used &lt;code&gt;neofetch&lt;/code&gt;, a tool that displays your system information in the terminal. The output from &lt;code&gt;neofetch&lt;/code&gt; contains ANSI escape codes, so I cleaned it up before passing it to the AI.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_neofetch_output&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Run the neofetch command and capture its output
&lt;/span&gt;        &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;check_output&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;neofetch&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;--stdout&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Use regular expression to remove ANSI escape codes
&lt;/span&gt;        &lt;span class="n"&gt;clean_output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;\x1B\[[0-?]*[ -/]*[@-~]&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error running neofetch: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;clean_output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Neofetch could not be run.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;clean_output&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By adding the output from &lt;code&gt;neofetch&lt;/code&gt;, the AI client now understands the specifics of my operating system, hardware, and more, allowing it to provide even more tailored responses.&lt;/p&gt;

&lt;h3&gt;
  
  
  Final Code
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAI&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sys&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;

&lt;span class="c1"&gt;# Initialize client with API key
&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;your-openai-api-key-here&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Initialize messages that will be exchanged with client
&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;system&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; 
              &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You are a intelligent assistant.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_neofetch_output&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Run the neofetch command and capture its output
&lt;/span&gt;        &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;subprocess&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;check_output&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;neofetch&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;--stdout&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]).&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;utf-8&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Use regular expression to remove ANSI escape codes
&lt;/span&gt;        &lt;span class="n"&gt;clean_output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;\x1B\[[0-?]*[ -/]*[@-~]&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error running neofetch: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;clean_output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Neofetch could not be run.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;clean_output&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_terminal_history&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;history_file&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;expanduser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;~/.local/share/fish/fish_history&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;history_file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;history&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readlines&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="c1"&gt;# Fish history format: lines starting with '- cmd: ' are actual commands
&lt;/span&gt;            &lt;span class="n"&gt;commands&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;history&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;- cmd: &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Error reading history file: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;commands&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;commands&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;ask_openai&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;terminal_history&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;system_info&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Combine terminal history, system information, and the user's prompt
&lt;/span&gt;    &lt;span class="n"&gt;full_prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Here is my recent terminal history: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;terminal_history&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; \
                  &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;My system specifications: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;system_info&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; \
                  &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Question: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;full_prompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;full_prompt&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;chat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-3.5-turbo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;assistant&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Usage: archero &amp;lt;your query&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:])&lt;/span&gt;
    &lt;span class="n"&gt;terminal_history&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_terminal_history&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;system_info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_neofetch_output&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;answer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ask_openai&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;terminal_history&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;system_info&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OpenAI: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;answer&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In just a few steps, I built an AI client that integrates seamlessly with my terminal, using Fish shell history and system information to provide smarter responses. It’s been a huge time-saver, especially when troubleshooting issues on my Arch Linux system.&lt;/p&gt;

&lt;p&gt;Now when I ask something like &lt;code&gt;archero how do I update my system&lt;/code&gt;  I get a more catered response like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;why&lt;/span&gt; &lt;span class="n"&gt;don&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;t you ask ur mum
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Feel free to adapt the steps to your environment and enjoy the convenience of having your own AI assistant directly in your terminal! Full code is available in my dotfiles repository here: &lt;a href="https://github.com/gucci-ninja/.dotfiles/blob/master/archero.py" rel="noopener noreferrer"&gt;https://github.com/gucci-ninja/.dotfiles/blob/master/archero.py&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Actual response (for legal purposes):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;OpenAI: To update your Arch Linux system, you can use the following commands &lt;span class="k"&gt;in &lt;/span&gt;your terminal:

1. First, update the package repositories and package list:

&lt;span class="nb"&gt;sudo &lt;/span&gt;pacman &lt;span class="nt"&gt;-Sy&lt;/span&gt;


2. Then, upgrade all installed packages to their latest versions:

&lt;span class="nb"&gt;sudo &lt;/span&gt;pacman &lt;span class="nt"&gt;-Su&lt;/span&gt;


3. Finally, you can also clean up any cached packages that are no longer required by running:

&lt;span class="nb"&gt;sudo &lt;/span&gt;pacman &lt;span class="nt"&gt;-Sc&lt;/span&gt;


Remember to carefully review the package changes before proceeding with the update. It&lt;span class="s1"&gt;'s important to keep your system up to date to ensure security and stability.

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>linux</category>
      <category>ai</category>
      <category>openai</category>
      <category>archlinux</category>
    </item>
    <item>
      <title>8 Tips for Effective Design Reviews</title>
      <dc:creator>Suhavi Sandhu</dc:creator>
      <pubDate>Sun, 21 Jan 2024 00:18:22 +0000</pubDate>
      <link>https://dev.to/suhavi/8-tips-for-effective-design-reviews-1611</link>
      <guid>https://dev.to/suhavi/8-tips-for-effective-design-reviews-1611</guid>
      <description>&lt;p&gt;I had a recent design review that caused me to self-reflect and come up with some practical technical and non-technical tips on some aspects that may be overlooked in design reviews (lower-level designs in particular).&lt;/p&gt;

&lt;h3&gt;
  
  
  Technical Tips
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. The S in SOLID
&lt;/h4&gt;

&lt;p&gt;In my lens, making code changes comes at the cost of introducing complexity. In order to reduce the complexity, I tend to lean towards modifying existing classes. I've learned that this is a bad practice and leads to classes being overloaded, diminishing readability and going against the single responsibility principle.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tip:&lt;/strong&gt; 👉 Every class should serve a single purpose. If you are changing that purpose, either create a new class or rename the existing one. Same goes for method names, if you're thinking of changing the return type, think about changing the method name.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  2. Dead Code
&lt;/h4&gt;

&lt;p&gt;Sometimes when I am in the design or planning phase, I get so caught up in the new methods that need to be implemented that I forget to mention what will be removed/refactored. Of course, this doesn't hinder the development but it can cause confusion. As I was introducing new methods, my colleagues were left wondering what would happen to the existing ones.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tip:&lt;/strong&gt; 👉 Consider additions &lt;strong&gt;and removals&lt;/strong&gt; during bug fixes or improvements. Clearly communicate changes to avoid confusion among colleagues.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  3. Read-Write Consistency
&lt;/h4&gt;

&lt;p&gt;In my case, I was thinking of writing to a DynamoDB and then reading the value that I just wrote. DynamoDB does not guarantee read after write consistency but rather eventual consistency. So in some cases, I would be reading from stale data. This was a miss in my design and I also lost an opportunity to optimize by cutting down on database calls. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tip:&lt;/strong&gt; 👉 Prioritize considerations of read-after-write consistency, as overlooking this can lead to reading from potentially stale data.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  4. Stubbing
&lt;/h4&gt;

&lt;p&gt;Despite going through the design review, there was still the question of who is going to work on what and how we can distribute tasks and minimize conflicts. My colleagues suggested stubbing - adding mocked implementations/signatures so devs know where a change should go.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tip:&lt;/strong&gt; 👉 Incorporate stubbing to provide a visual representation of necessary modifications, empowering colleagues to make independent contributions to the system.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Non-Technical Tips
&lt;/h3&gt;

&lt;h4&gt;
  
  
  5. Always Provide Options
&lt;/h4&gt;

&lt;p&gt;A lot of the confusion and miscommunication came from a result of me not providing the different options. It felt like I was suggesting something and my colleagues were opposing me, whereas, in my head, I had already compared pros and cons of possible solutions and presented the 'best' one (in my opinion). There are two problems with this - one, it looks like I never considered other options and two, the option I presented might not even be the best one! When it comes to high-level designs, we have been trained to present multiple options, but with low-level designs, I forget since it is so close to the implementation phase.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tip:&lt;/strong&gt; 👉 Present multiple solutions with pros and cons for informed decision-making to avoid overlooking alternatives.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  6. Don't Assume
&lt;/h4&gt;

&lt;p&gt;Since I was working on a code base that I had less experience with and my colleagues regularly committed to, I made the assumption that they would know the ins and outs of the code. This is obviously wrong. If it were me who had a lot of experience in the codebase, there would still be minor things here and there that I had no idea about. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tip:&lt;/strong&gt; 👉 Don't assume someone's level of knowledge of a topic at hand; always provide necessary context for a shared understanding.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  7. Effective Communication
&lt;/h4&gt;

&lt;p&gt;For me, it's hard to follow when people are talking. I am more of a visual or hands-on learner. To combat this, I try to write down what I hear. When I was chatting with my colleagues and sharing screen, I found it difficult to keep up and note down things at the same time. This shows I need to practice my note-taking in real-time and build up my comprehension.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tip:&lt;/strong&gt; 👉 Recognize diverse learning styles; practice real-time note-taking during dynamic discussions for better comprehension.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  8. Knowing When to Stop
&lt;/h4&gt;

&lt;p&gt;I noticed after the 1 hour mark the meeting tone went from productive to slightly negative, leaving me feeling a bit down. Since it was an adhoc meeting, I should have done regular time-checks and ended the meeting at the 1 hour mark (or even earlier). Ideally it should be a scheduled meeting with a clear agenda, but we were on strict timelines.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tip:&lt;/strong&gt; 👉 Be mindful of meeting tone; set time limits to maintain productive discussion and a positive atmosphere.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These tips aim to guide a more effective design review process by addressing commonly forgotten elements.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>softwareengineering</category>
      <category>career</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Migrating a Nuxt SSR App from Heroku to Vercel</title>
      <dc:creator>Suhavi Sandhu</dc:creator>
      <pubDate>Tue, 03 Jan 2023 01:27:26 +0000</pubDate>
      <link>https://dev.to/suhavi/migrating-a-nuxt-ssr-app-from-heroku-to-vercel-4d75</link>
      <guid>https://dev.to/suhavi/migrating-a-nuxt-ssr-app-from-heroku-to-vercel-4d75</guid>
      <description>&lt;p&gt;As of December 2022, Heroku has transitioned to a paid plan for hosting server-side apps. This left myself and many others with broken apps, with the option to pay for ‘dynos’ to get our apps running or migrate. If you’re like me and used Heroku for personal use, you probably don’t want to switch to a paid plan for fear of fluctuating hosting expenses and are going to look into alternatives. Most popular hosting services we know of (Netlify, Vercel, Firebase) have out-of-the-box support for static apps but require a bit more involvement when it comes to server-side rendering. Hence, I put together this guide for the very specific use case of apps built with Nuxt 2. I also have a Troubleshooting section for issues I faced that others might run into.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1 - Create a Vercel account
&lt;/h2&gt;

&lt;p&gt;Go to &lt;a href="https://vercel.com" rel="noopener noreferrer"&gt;https://vercel.com&lt;/a&gt; to create a free account.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2 - Configure your project for Vercel
&lt;/h2&gt;

&lt;p&gt;Vercel supports non-SSR out of the box, but for SSR to work, we need to deploy a serverless function that handles all the server-related functions. For this, we will need to use &lt;a href="https://github.com/nuxt/vercel-builder" rel="noopener noreferrer"&gt;https://github.com/nuxt/vercel-builder&lt;/a&gt; built by the Nuxt community. To use it you need to create a &lt;code&gt;vercel.json&lt;/code&gt; in your project’s root directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;version&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;builds&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;src&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nuxt.config.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@nuxtjs/vercel-builder&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3 - Create a new project by importing your repository
&lt;/h2&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%2Ff4lhergctve1q0cvpv0e.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%2Ff4lhergctve1q0cvpv0e.png" alt="Import project" width="479" height="232"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4 - Copy over necessary environment variables from Heroku to Vercel
&lt;/h2&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%2Fzjsx0hjm4bo244q112bu.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%2Fzjsx0hjm4bo244q112bu.png" alt="Environment variables" width="533" height="166"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5 - Fill in the deployment settings
&lt;/h2&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%2Fzoikxar28104mv9b4lrp.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%2Fzoikxar28104mv9b4lrp.png" alt="Settings" width="621" height="424"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Choose Nuxt.js as the framework preset and fill in the build commands. The default commands should work but I added the yarn commands just to be sure. The commands are run in the following order.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;yarn install&lt;/code&gt; will grab all of the dependencies needed for your app to run&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;yarn generate&lt;/code&gt; will compile your client-side and server-side code and package it into minified files that will be saved in your output directory (&lt;code&gt;dist&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;yarn start&lt;/code&gt; starts the process that will run your app.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These steps are identical to those needed to run your app locally. &lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6 - Deploy
&lt;/h2&gt;

&lt;p&gt;I was able to migrate my SSR Nuxt.js application from Heroku to Vercel with these steps. If you’re still having issues, look through the troubleshooting section below or reach out to me. For reference, here is the code for my application - &lt;a href="https://github.com/gucci-ninja/dotboard" rel="noopener noreferrer"&gt;https://github.com/gucci-ninja/dotboard&lt;/a&gt; which is now running on &lt;a href="https://dotboard.vercel.app/" rel="noopener noreferrer"&gt;https://dotboard.vercel.app/&lt;/a&gt;. Thanks!&lt;/p&gt;

&lt;h2&gt;
  
  
  Troubleshooting
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Error - This serverless function has crashed/No build files found
&lt;/h3&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%2Fbqaf14o751ppfplv84g8.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%2Fbqaf14o751ppfplv84g8.png" alt="Server error" width="535" height="437"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;FATAL&lt;/span&gt;  &lt;span class="nx"&gt;No&lt;/span&gt; &lt;span class="nx"&gt;build&lt;/span&gt; &lt;span class="nx"&gt;files&lt;/span&gt; &lt;span class="nx"&gt;found&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="sr"&gt;/var/&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nuxt&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;dist&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="nx"&gt;Use&lt;/span&gt; &lt;span class="nx"&gt;either&lt;/span&gt; &lt;span class="s2"&gt;`nuxt build`&lt;/span&gt; &lt;span class="nx"&gt;or&lt;/span&gt; &lt;span class="s2"&gt;`builder.build()`&lt;/span&gt; &lt;span class="nx"&gt;or&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="nx"&gt;nuxt&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;development&lt;/span&gt; &lt;span class="nx"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="nx"&gt;Use&lt;/span&gt; &lt;span class="nx"&gt;either&lt;/span&gt; &lt;span class="s2"&gt;`nuxt build`&lt;/span&gt; &lt;span class="nx"&gt;or&lt;/span&gt; &lt;span class="s2"&gt;`builder.build()`&lt;/span&gt; &lt;span class="nx"&gt;or&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="nx"&gt;nuxt&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;development&lt;/span&gt; &lt;span class="nx"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="nx"&gt;at&lt;/span&gt; &lt;span class="nx"&gt;VueRenderer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_ready &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node_modules&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;nuxt&lt;/span&gt;&lt;span class="sr"&gt;/vue-renderer/&lt;/span&gt;&lt;span class="nx"&gt;dist&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;vue&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;4204&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;at&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ready &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node_modules&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;nuxt&lt;/span&gt;&lt;span class="sr"&gt;/server/&lt;/span&gt;&lt;span class="nx"&gt;dist&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;615&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;at&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;Nuxt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_init &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node_modules&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;nuxt&lt;/span&gt;&lt;span class="sr"&gt;/core/&lt;/span&gt;&lt;span class="nx"&gt;dist&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;core&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;703&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="mi"&gt;2023&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;01&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;03&lt;/span&gt;&lt;span class="nx"&gt;T00&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;01&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;47.485&lt;/span&gt;&lt;span class="nx"&gt;Z&lt;/span&gt;    &lt;span class="kc"&gt;undefined&lt;/span&gt;   &lt;span class="nx"&gt;ERROR&lt;/span&gt;   &lt;span class="nx"&gt;λ&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt; &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="nx"&gt;initializing&lt;/span&gt; &lt;span class="nx"&gt;nuxt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;No&lt;/span&gt; &lt;span class="nx"&gt;build&lt;/span&gt; &lt;span class="nx"&gt;files&lt;/span&gt; &lt;span class="nx"&gt;found&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="sr"&gt;/var/&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nuxt&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;dist&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="nx"&gt;Use&lt;/span&gt; &lt;span class="nx"&gt;either&lt;/span&gt; &lt;span class="s2"&gt;`nuxt build`&lt;/span&gt; &lt;span class="nx"&gt;or&lt;/span&gt; &lt;span class="s2"&gt;`builder.build()`&lt;/span&gt; &lt;span class="nx"&gt;or&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="nx"&gt;nuxt&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;development&lt;/span&gt; &lt;span class="nx"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="nx"&gt;at&lt;/span&gt; &lt;span class="nx"&gt;VueRenderer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_ready &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/var/&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;node_modules&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;nuxt&lt;/span&gt;&lt;span class="sr"&gt;/vue-renderer/&lt;/span&gt;&lt;span class="nx"&gt;dist&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;vue&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;renderer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;4204&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;at&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ready &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/var/&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;node_modules&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;nuxt&lt;/span&gt;&lt;span class="sr"&gt;/server/&lt;/span&gt;&lt;span class="nx"&gt;dist&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;615&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;at&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;Nuxt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_init &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/var/&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;node_modules&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;nuxt&lt;/span&gt;&lt;span class="sr"&gt;/core/&lt;/span&gt;&lt;span class="nx"&gt;dist&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;core&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;703&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;RequestId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="nx"&gt;f4fdef5&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;a109&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4497&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;95&lt;/span&gt;&lt;span class="nx"&gt;e9&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="nx"&gt;f5c8f2a905b&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Runtime&lt;/span&gt; &lt;span class="nx"&gt;exited&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;exit&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="nx"&gt;Runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ExitError&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Version lock vercel-builder to &lt;code&gt;0.23.0&lt;/code&gt; as there is an issue with &lt;code&gt;0.24.0&lt;/code&gt; not invoking the serverless function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;version&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;builds&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;src&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nuxt.config.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@nuxtjs/vercel-builder@0.23.0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Relevant links&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/nuxt/vercel-builder/issues/765#issuecomment-1358290407" rel="noopener noreferrer"&gt;https://github.com/nuxt/vercel-builder/issues/765#issuecomment-1358290407&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Error - Outdated dependencies
&lt;/h3&gt;

&lt;p&gt;If you’re like me and were not actively developing your app, some of the dependencies might be outdated or need to be upgraded. So a quick test is to run the app locally and see if everything is working as expected. For example, I was getting the following error.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;make&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Entering&lt;/span&gt; &lt;span class="nx"&gt;directory&lt;/span&gt; &lt;span class="s2"&gt;`/vercel/path0/node_modules/node-sass/build'

gyp ERR! build error 
gyp ERR! stack Error: `&lt;/span&gt;&lt;span class="nx"&gt;make&lt;/span&gt;&lt;span class="s2"&gt;` failed with exit code: 2

Build failed with error code: 1
Error: Command "yarn install" exited with 1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I removed &lt;code&gt;node-sass&lt;/code&gt; from my dependencies as I was not using it. I also needed to downgrade my &lt;code&gt;sass-loader&lt;/code&gt; from &lt;code&gt;^9.0.3&lt;/code&gt; to &lt;code&gt;^7.1.0&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Relevant links&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/60394291/error-node-modules-node-sass-command-failed" rel="noopener noreferrer"&gt;https://stackoverflow.com/questions/60394291/error-node-modules-node-sass-command-failed&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/58623072/npm-node-sass-installation-fails" rel="noopener noreferrer"&gt;https://stackoverflow.com/questions/58623072/npm-node-sass-installation-fails&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Error - 404 when calling API. Runtime logs on Vercel showing 404 as the response status
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you have any endpoints or routes in your server code, you need to declare them in the &lt;code&gt;vercel.json&lt;/code&gt;. I have a &lt;code&gt;server/&lt;/code&gt; folder which holds all the endpoints that my app serves (&lt;code&gt;/api/auth/login&lt;/code&gt;, &lt;code&gt;/api/auth/user&lt;/code&gt;) The code to handle all these requests resides in &lt;code&gt;/server/index.js&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;builds&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;src&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;server/**/*.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// path to code that handles API requests&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@vercel/node&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;src&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nuxt.config.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@nuxtjs/vercel-builder@0.23.0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;config&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;routes&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;src&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/auth/login&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// endpoint 1&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/server/index.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="c1"&gt;// code that handles endpoint 1&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;src&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/auth/user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// endpoint 2&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/server/index.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="c1"&gt;// code that handles endpoint 2&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Relevant links&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/nuxt/vercel-builder/blob/main/examples/basic/vercel.json" rel="noopener noreferrer"&gt;https://github.com/nuxt/vercel-builder/blob/main/examples/basic/vercel.json&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Error - Deployment hanging and taking 7+ minutes
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;NowBuildError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;node_modules_prod&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;rxjs&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;internal&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;observable&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;116&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="nx"&gt;TS2322&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Type&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;import("/vercel/path0/node_modules/rxjs/internal/Observable").Observable&amp;lt;T&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;not&lt;/span&gt; &lt;span class="nx"&gt;assignable&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;import("/vercel/path0/node_modules_prod/rxjs/src/internal/Observable").Observable&amp;lt;T&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="nx"&gt;node_modules_prod&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;rxjs&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;internal&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;observable&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;116&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="nx"&gt;TS2345&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Argument&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;import("/vercel/path0/node_modules_prod/rxjs/src/internal/types").SchedulerLike&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;not&lt;/span&gt; &lt;span class="nx"&gt;assignable&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;parameter&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;import("/vercel/path0/node_modules/rxjs/internal/types").SchedulerLike&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="nx"&gt;node_modules_prod&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;rxjs&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;internal&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;scheduled&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;scheduled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;38&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="nx"&gt;TS2345&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Argument&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;import("/vercel/path0/node_modules/rxjs/internal/types").SchedulerLike&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;not&lt;/span&gt; &lt;span class="nx"&gt;assignable&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;parameter&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;import("/vercel/path0/node_modules_prod/rxjs/src/internal/types").SchedulerLike&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not sure what the issue was but retrying the deployment worked.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>discuss</category>
      <category>opensource</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Flutter Web and Rive Animation Tutorial</title>
      <dc:creator>Suhavi Sandhu</dc:creator>
      <pubDate>Wed, 01 Jun 2022 05:01:17 +0000</pubDate>
      <link>https://dev.to/suhavi/flutter-web-and-rive-animation-tutorial-5f5k</link>
      <guid>https://dev.to/suhavi/flutter-web-and-rive-animation-tutorial-5f5k</guid>
      <description>&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%2Fekz8jjzkgou1gohrij64.jpeg" 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%2Fekz8jjzkgou1gohrij64.jpeg" alt="Flutter Web and Rive Animation Tutoria" width="800" height="230"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hi! This is a beginner to intermediate tutorial for setting up a Flutter web app with Rive animations. I recently built a &lt;a href="https://waterslide-kyy1knexs-gucci-ninja.vercel.app/#/" rel="noopener noreferrer"&gt;sliding tile game&lt;/a&gt; that incorporates Rive animations for the Flutter Hackathon. In this tutorial I’m going to show you how to add an animation to your Flutter web app and control it through user input.&lt;/p&gt;

&lt;p&gt;We will create a basketball animation that gets triggered each time the user clicks on a button.&lt;/p&gt;

&lt;p&gt;First we’ll create the animation. If you already have your animation you can skip to this section which will show you how to add your animation to a web app.&lt;/p&gt;

&lt;p&gt;Rive is a free-to-use platform for designing and creating animations. We are going to use a basketball animation that Rive provides as one of their tutorials. &lt;a href="https://editor.rive.app/preview/642-1469-basketball/219454" rel="noopener noreferrer"&gt;Here is the animation.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you open it, there’s a Design tab that let’s you modify the look of the animation, like the colours and original shape of the ball.&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%2Frbbsy6goudqo3q12gloh.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%2Frbbsy6goudqo3q12gloh.png" alt="Rive Design Tab" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you switch to the Animate tab you can see the animation run. Each animation can have multiple ‘states’, in this one there’s an &lt;code&gt;idle&lt;/code&gt; state but you could add more, like a &lt;code&gt;rolling&lt;/code&gt; state or whatever you might need for your business logic.&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%2Fir389ur7y6yrt5g6kack.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%2Fir389ur7y6yrt5g6kack.png" alt="Rive Animate Tab" width="800" height="385"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Download the animation in the newest runtime as &lt;code&gt;basketball.riv&lt;/code&gt;. Once we hook it up to Flutter, we will be able to play the &lt;code&gt;idle&lt;/code&gt; animation when the user performs some action, such as clicking a button.&lt;/p&gt;

&lt;p&gt;Create a flutter project that we will be adding the animation to. Once the project is created, make an &lt;code&gt;assets&lt;/code&gt; folder if it doesn't already exist and move your animation file into it. I saved mine under &lt;code&gt;assets/animations/&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flutter create fluttertutorial
cd fluttertutorial
flutter run -d chrome
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will spin up a demo app for you that looks something like 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%2Fvooqt9ehzfpo4noujm43.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%2Fvooqt9ehzfpo4noujm43.png" alt="Flutter Demo App" width="418" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next we add the library that is going to help us control (play and pause) our animation.&lt;/p&gt;

&lt;p&gt;Add to &lt;code&gt;pubspec.yaml&lt;/code&gt; and run &lt;code&gt;flutter pub get&lt;/code&gt;.&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;dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;rive&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;^0.8.4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then in &lt;code&gt;lib/main.dart&lt;/code&gt;, import the package.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;'package:rive/rive.dart'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let’s add the animation to our app by creating a stateless widget. Add this code to the end of &lt;code&gt;lib/main.dart&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BasketBallAnimation&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatelessWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;BasketBallAnimation&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;key:&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Scaffold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;body:&lt;/span&gt; &lt;span class="n"&gt;Center&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;RiveAnimation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'animations/basketball.riv'&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To display this class, find the main class, &lt;code&gt;MyApp&lt;/code&gt; and set &lt;code&gt;home:&lt;/code&gt; to point to our new widget.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyApp&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatelessWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;MyApp&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;key:&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;MaterialApp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;title:&lt;/span&gt; &lt;span class="s"&gt;'Flutter Demo'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;theme:&lt;/span&gt; &lt;span class="n"&gt;ThemeData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;primarySwatch:&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;blue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="nl"&gt;home:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;BasketBallAnimation&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="c1"&gt;// make this change&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now when you re-run, you should see the basketball animation playing.&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%2Fa8yzc1g4vxdwm07o3ew5.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%2Fa8yzc1g4vxdwm07o3ew5.png" alt="Stateless basketball animation" width="416" height="459"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let’s give the widget state - this is how we will be able to tell if it’s playing or paused.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BasketBallAnimation&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatefulWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;BasketBallAnimation&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="n"&gt;Key&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;key:&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;BasketBallAnimation&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;createState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_BasketBallAnimationState&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;_BasketBallAnimationState&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;BasketBallAnimation&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;isPlaying&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Scaffold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;body:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Center&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;RiveAnimation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'animations/basketball.riv'&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next we will add a button that, when called, will change the value of &lt;code&gt;isPlaying&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;_BasketBallAnimationState&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;BasketBallAnimation&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;isPlaying&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;_toggleAnimation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;isPlaying&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;isPlaying&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Scaffold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;body:&lt;/span&gt;
          &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Center&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;RiveAnimation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'animations/basketball.riv'&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
            &lt;span class="nl"&gt;floatingActionButton:&lt;/span&gt; &lt;span class="n"&gt;FloatingActionButton&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;onPressed:&lt;/span&gt; &lt;span class="n"&gt;_toggleAnimation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;tooltip:&lt;/span&gt; &lt;span class="n"&gt;isPlaying&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="s"&gt;'Pause'&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'Play'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Icon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="n"&gt;isPlaying&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;Icons&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;pause&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Icons&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;play_arrow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we can hook up the RiveController methods. The &lt;code&gt;RiveAnimationController&lt;/code&gt; is what holds the state of our animation. Initially, we are going to set it to play our animation named &lt;code&gt;idle&lt;/code&gt;. This is a &lt;code&gt;SimpleAnimation&lt;/code&gt;. We will be able to tell if the animation is playing or not by checking the &lt;code&gt;isActive&lt;/code&gt; property of the controller. We attach this controller to our animation asset by passing it into our animation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="n"&gt;RiveAnimation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'path/to/my/animation.riv'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;controllers:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_controller&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the updated code with the controller hooked up.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;_BasketBallAnimationState&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;BasketBallAnimation&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;late&lt;/span&gt; &lt;span class="n"&gt;RiveAnimationController&lt;/span&gt; &lt;span class="n"&gt;_controller&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="n"&gt;isPlaying&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_controller&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isActive&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;_toggleAnimation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;_controller&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isActive&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;_controller&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isActive&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;initState&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;initState&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;_controller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SimpleAnimation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'idle'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Scaffold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;body:&lt;/span&gt; &lt;span class="n"&gt;Center&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;RiveAnimation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'animations/basketball.riv'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="nl"&gt;controllers:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;_controller&lt;/span&gt;&lt;span class="p"&gt;])),&lt;/span&gt;
      &lt;span class="nl"&gt;floatingActionButton:&lt;/span&gt; &lt;span class="n"&gt;FloatingActionButton&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;onPressed:&lt;/span&gt; &lt;span class="n"&gt;_toggleAnimation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;tooltip:&lt;/span&gt; &lt;span class="n"&gt;isPlaying&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="s"&gt;'Pause'&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'Play'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;Icon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="n"&gt;isPlaying&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;Icons&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;pause&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Icons&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;play_arrow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you should have something that looks like the screen below. A basketball animation that starts and stops when the user interacts with the floating button.&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%2Fthryojpwsc3db3tr9mq3.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%2Fthryojpwsc3db3tr9mq3.gif" alt="Final app with animation" width="480" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hope this tutorial helps you. The complete code for &lt;code&gt;lib/main.dart&lt;/code&gt; can be found in &lt;a href="https://gist.github.com/gucci-ninja/4698166233ab078a2ff979b45a4673bb" rel="noopener noreferrer"&gt;this gist&lt;/a&gt;. Happy coding :)&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>animation</category>
      <category>rive</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Your Guide to Arch Linux</title>
      <dc:creator>Suhavi Sandhu</dc:creator>
      <pubDate>Wed, 05 Jan 2022 02:10:52 +0000</pubDate>
      <link>https://dev.to/suhavi/your-guide-to-arch-linux-1262</link>
      <guid>https://dev.to/suhavi/your-guide-to-arch-linux-1262</guid>
      <description>&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%2Fboxh1xbgf3xwlw065e8e.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%2Fboxh1xbgf3xwlw065e8e.png" alt="My Arch Linux Build" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hi everyone! This guide is meant to take you through the process of dual-booting Arch Linux. It's more of a set of guidelines rather than strict procedure. I'm hoping to give new or potential users an idea of what it's like to dual boot your computer with Arch Linux. &lt;/p&gt;

&lt;p&gt;I started using Arch in 2018 after getting tired of Ubuntu and since then I have dealt with my fair share of problems (corrupted ISO, problematic updates, bluetooth nightmares). However, I can say with confidence that using Arch has given me a better understanding and appreciation for operating systems as a whole. There are some things I used to take for granted - like the wifi menu that comes pre-installed with Windows or Mac OS - that I had to install and configure when it came to Arch Linux.&lt;/p&gt;

&lt;p&gt;I decided to create this guide for myself when my first installation went south. I lost everything because I didn't have my dotfiles backed up. So the second time around, I created &lt;a href="https://github.com/gucci-ninja/.dotfiles.git" rel="noopener noreferrer"&gt;this repo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;**Note: Steps 2-10 are the ones you need to do in one sitting but the rest can be done at your own pace!&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 0 - Preparation
&lt;/h2&gt;

&lt;p&gt;If you are dual-booting you are essentially telling your current operating system to stop hogging all the space on your computer and make room for a new OS. So figure out what disk management tool your current OS uses and make a &lt;code&gt;partition&lt;/code&gt; for your new OS. I went with 100GB, which should be fairly sufficient unless you know you're going to be storing a lot of stuff.&lt;/p&gt;

&lt;p&gt;I used the &lt;code&gt;diskmgmt.msc&lt;/code&gt; utility on Windows. From there, I 'shrunk' my C drive by 100GB. This created an &lt;strong&gt;unallocated&lt;/strong&gt; partition, which means it is no longer affiliated with your current OS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1 - Securing the ISO
&lt;/h2&gt;

&lt;p&gt;When you decide to make the switch to Arch (or any Linux distro), you are going to need an image of the operating system. This comes in the form of a &lt;code&gt;.iso&lt;/code&gt; file. You are going to have to flash this image file onto a good USB (or a CD if that's your jam and you still have a CD drive..). If you are on Windows you can use a software called &lt;code&gt;Rufus&lt;/code&gt; which lets you select your USB and flash an ISO image onto it. &lt;/p&gt;

&lt;p&gt;Here's a link to the &lt;a href="https://archlinux.org/download/" rel="noopener noreferrer"&gt;official Arch Linux ISOs&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2 - Booting the ISO
&lt;/h2&gt;

&lt;p&gt;Once you have a fresh image of Arch, plug the USB or whatever medium you're using into the machine you partitioned. Then, depending on what computer you're working with, you need to press some key(s) at startup so you're transported to the boot menu. This will prevent your default OS from loading up. For me, I spammed F2/F3 repeatedly until I saw the boot menu. Then, I selected the option to boot into the USB. Remember, if you mess up, it's not the end of the world, just possibly the end of your PC :D JK&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3 - Mount your system
&lt;/h2&gt;

&lt;p&gt;At this point you are using Arch Linux. From here there are actually a bunch of steps but I &lt;em&gt;usually&lt;/em&gt; do them all at once. It's kind of intimidating if it's your first time because you just see a black screen with a weird font of white text.&lt;/p&gt;

&lt;p&gt;Select &lt;code&gt;Arch Linux install medium&lt;/code&gt; to load up the contents of your USB. This might take a while. The following commands will help you verify that you are in boot mode and that your machine has detected the EFI partition (used for booting) and the Arch partition.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# To verify you are in boot mode&lt;/span&gt;
&lt;span class="nb"&gt;ls&lt;/span&gt; /sys/firmware/efi/efivars

&lt;span class="c"&gt;# To see partitions (like the one you made in Step 0)&lt;/span&gt;
fdisk &lt;span class="nt"&gt;-l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My EFI disk is named &lt;code&gt;sda1&lt;/code&gt; and the Arch one is &lt;code&gt;sda5&lt;/code&gt;. I know this because &lt;code&gt;sda5&lt;/code&gt; says exactly 100GB, which is how much I allocated to it. They may be under different names for you but it should indicate &lt;code&gt;EFI&lt;/code&gt; on the EFI one and &lt;code&gt;/&lt;/code&gt; on the one that will become your root directory. You &lt;strong&gt;can&lt;/strong&gt; further partition the root directory using &lt;code&gt;fdisk&lt;/code&gt; to allocate space for system encryption, RAID, etc. Data redundancy wasn't a major concern for me and I wouldn't recommend it if this is your first Linux build.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# To format your root partition&lt;/span&gt;
mkfs.ext4 &amp;lt;arch_partition&amp;gt;
&lt;span class="c"&gt;# Here is what I ran for example, -L is for label&lt;/span&gt;
mkfs.ext4 &lt;span class="nt"&gt;-L&lt;/span&gt; &lt;span class="s2"&gt;"Arch Linux"&lt;/span&gt; /dev/sda5

&lt;span class="c"&gt;# To mount the partition, run mount &amp;lt;arch_partition&amp;gt; /mnt&lt;/span&gt;
mount /dev/sda5 /mnt

&lt;span class="c"&gt;# Mount EFI partition, for me it was /dev/sda1&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; /mnt/boot/efi
mount &amp;lt;efi_partition&amp;gt; /mnt/boot/efi

&lt;span class="c"&gt;# If you are not on a wired connection, connect to wifi&lt;/span&gt;

&lt;span class="c"&gt;# Option A: comes with UI but outdated&lt;/span&gt;
wifi-menu

&lt;span class="c"&gt;# Option B - launches interactive iwd prompt&lt;/span&gt;
iwctl
&lt;span class="o"&gt;[&lt;/span&gt;iwd] device list
&lt;span class="o"&gt;[&lt;/span&gt;iwd] station &amp;lt;device&amp;gt; scan
&lt;span class="o"&gt;[&lt;/span&gt;iwd] station &amp;lt;device&amp;gt; get-networks
&lt;span class="o"&gt;[&lt;/span&gt;iwd] station &amp;lt;device&amp;gt; connect &amp;lt;SSID&amp;gt;

&lt;span class="c"&gt;# Update the system time and date&lt;/span&gt;
timedatectl set-ntp &lt;span class="nb"&gt;true&lt;/span&gt;

&lt;span class="c"&gt;# Install base system&lt;/span&gt;
pacstrap /mnt base linux linux-firmware vim

&lt;span class="c"&gt;# Generate the fstab (I have no clue what this is but I think it lets you detect mounted file systems)&lt;/span&gt;
genfstab &lt;span class="nt"&gt;-p&lt;/span&gt; /mnt &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; /mnt/etc/fstab
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4 - Get out of the USB
&lt;/h2&gt;

&lt;p&gt;You have successfully taken the image on your USB and mounted it onto your computer. This step will basically be the equivalent of &lt;code&gt;cd&lt;/code&gt; into your new directory. Keep the USB plugged in though, we're not done with it yet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Change root into arch linux&lt;/span&gt;
arch-chroot /mnt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5 - Wifi
&lt;/h2&gt;

&lt;p&gt;Most important step because without wifi you can't browse memes. There are a lot of ways to do this and I had a lot of trouble with the ones that are mentioned in most tutorials so here's the one that I would recommend. &lt;a href="https://wiki.archlinux.org/title/NetworkManager" rel="noopener noreferrer"&gt;NetworkManager&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pacman &lt;span class="nt"&gt;-Sy&lt;/span&gt; networkmanager

&lt;span class="c"&gt;# Automatically start it up&lt;/span&gt;
systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;NetworkManager
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 6 - Bootloader
&lt;/h2&gt;

&lt;p&gt;You need something to load your OS each time you restart your computer so get grub.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Download grub&lt;/span&gt;
pacman &lt;span class="nt"&gt;-S&lt;/span&gt; grub efibootmgr

&lt;span class="c"&gt;# Download something that allows Arch Linux to detect Windows as well&lt;/span&gt;
pacman &lt;span class="nt"&gt;-S&lt;/span&gt; os-prober

&lt;span class="c"&gt;# Install grub into HDD&lt;/span&gt;
grub-install /dev/sda
&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; /boot/efi/EFI/arch

&lt;span class="c"&gt;# Generate grub config&lt;/span&gt;
grub-mkconfig &lt;span class="nt"&gt;-o&lt;/span&gt; /boot/grub/grub.cfg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 7 - Set Up Some Boring Things
&lt;/h2&gt;

&lt;p&gt;Like date, timezone, clock, etc&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;timedatectl set-ntp &lt;span class="nb"&gt;true&lt;/span&gt;

&lt;span class="c"&gt;# Set up timezone&lt;/span&gt;
&lt;span class="nb"&gt;ln&lt;/span&gt; &lt;span class="nt"&gt;-sf&lt;/span&gt; /usr/share/zoneinfo/Canada/Eastern /etc/localtime

&lt;span class="c"&gt;# Set clock&lt;/span&gt;
hwclock &lt;span class="nt"&gt;--systohc&lt;/span&gt;

&lt;span class="c"&gt;# Also set locale&lt;/span&gt;
&lt;span class="c"&gt;# First uncomment the Canada locale in /etc/locale.gen&lt;/span&gt;
vi /etc/locale.gen
&lt;span class="c"&gt;# Generate the locales&lt;/span&gt;
locale-gen
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 8 - Password
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Set the root password&lt;/span&gt;
passwd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 9 - Unmount
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;umount &lt;span class="nt"&gt;-R&lt;/span&gt; /mnt
reboot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can take out the USB.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 10 - Take a break because you've come this far
&lt;/h2&gt;

&lt;p&gt;😎&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 11 - Users
&lt;/h2&gt;

&lt;p&gt;After rebooting, login as root and create a user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;useradd &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; wheel suhavi
psswd suhavi

&lt;span class="c"&gt;# Give sudo ability&lt;/span&gt;
vim /etc/sudoers
&lt;span class="c"&gt;# Uncomment the following line&lt;/span&gt;
%wheel &lt;span class="nv"&gt;ALl&lt;/span&gt;&lt;span class="o"&gt;=(&lt;/span&gt;ALL&lt;span class="o"&gt;)&lt;/span&gt; ALL
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 12 - Xorg
&lt;/h2&gt;

&lt;p&gt;This is a graphical server. So you don't have to look at a blank sceen all the time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pacman &lt;span class="nt"&gt;-S&lt;/span&gt; xorg-server xorg
&lt;span class="c"&gt;# Type startx to start it&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 13 - Terminal + Shell + Git + VS Code
&lt;/h2&gt;

&lt;p&gt;At this point the steps are very general. It's important to do your research to see which terminal, shell and editor you want. These are the ones I decided to go with&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;terminal: termite&lt;/li&gt;
&lt;li&gt;shell: fish (I think zsh is a better option, but you didn't hear it from me)&lt;/li&gt;
&lt;li&gt;editor: VS code&lt;/li&gt;
&lt;li&gt;version control: git
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pacman &lt;span class="nt"&gt;-S&lt;/span&gt; termite fish git code

&lt;span class="c"&gt;# Make fish your default&lt;/span&gt;
chsh &lt;span class="nt"&gt;-l&lt;/span&gt; &lt;span class="c"&gt;# See all shells&lt;/span&gt;
chsh &lt;span class="nt"&gt;-s&lt;/span&gt; fish

&lt;span class="c"&gt;# Copy the following to fish config file to make startx run on startup&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;status is-login
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$DISPLAY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nv"&gt;$XDG_VTNR&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; 1
    &lt;span class="nb"&gt;exec &lt;/span&gt;startx &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;-keeptty&lt;/span&gt;
  end
end

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Configs are your best friend with Linux. Located under .config at the root level, they contain rules for all the customizations you want to make to your operating system. Take a look at the files in this &lt;a href="https://github.com/gucci-ninja/.dotfiles" rel="noopener noreferrer"&gt;repo&lt;/a&gt; to get an idea of the kinds of changes you can make.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 14 - Window Manager
&lt;/h2&gt;

&lt;p&gt;There are lots of window managers to choose from. I personally went with bspwm because I like binary trees. I also got dmenu, which is a search bar that lets you type commands or applications to open. It can be accessed with (cmd/windows key) + spacebar. However, in order for these hotkeys and shortcuts to work you need sxhkd. Lastly, I installed some fonts!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pacman &lt;span class="nt"&gt;-S&lt;/span&gt; bspwm dmenu sxhkd

&lt;span class="c"&gt;# Fonts&lt;/span&gt;
pacman &lt;span class="nt"&gt;-S&lt;/span&gt; noto-fonts
&lt;span class="c"&gt;# Fonts can be managed at ~/.config/fontconfig/fonts.conf&lt;/span&gt;

&lt;span class="c"&gt;# Make x server start bspwm&lt;/span&gt;
vim ~/xinitrc
&lt;span class="c"&gt;# Add the followng&lt;/span&gt;
sxhkd &amp;amp;
&lt;span class="nb"&gt;exec &lt;/span&gt;bspwm

&lt;span class="c"&gt;# Make termite your default terminal by going into the `.config/sxhkd/sxhkdrc file and changing xterm to termite&lt;/span&gt;

&lt;span class="c"&gt;# Add custom keybinds to sxhkdrc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 15 - Sound
&lt;/h2&gt;

&lt;p&gt;I didn't have sound in the beginning.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pacman &lt;span class="nt"&gt;-S&lt;/span&gt; alsa-utils
alsamixer &lt;span class="nt"&gt;-c&lt;/span&gt; 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use the arrow keys to adjust your sound preferences.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 16 - Wallpaper
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;feh &lt;span class="nt"&gt;--bg-scale&lt;/span&gt; wallpaper.jpg

&lt;span class="c"&gt;# Edit the following to xinitrc&lt;/span&gt;
~/.fehbg &amp;amp;

&lt;span class="c"&gt;# Make sure it's before exec bspwm^&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 17 - Yay
&lt;/h2&gt;

&lt;p&gt;This will help download AUR packages, which are unofficial packages for things. You'll need it at some point.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://aur.archlinux.org/yay.git

&lt;span class="nb"&gt;cd &lt;/span&gt;yay

makepkg &lt;span class="nt"&gt;-si&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 18 - Polybar
&lt;/h2&gt;

&lt;p&gt;I actually hate this part but I missed having some sort of menu bar to tell me how much battery I have left, the date, etc&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yay &lt;span class="nt"&gt;-S&lt;/span&gt; polybar
&lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-Dm644&lt;/span&gt; /usr/share/doc/polybar/config &lt;span class="nv"&gt;$HOME&lt;/span&gt;/.config/polybar/config
example polybar

&lt;span class="c"&gt;# Make a lot of changes to example config&lt;/span&gt;

&lt;span class="c"&gt;# I was getting unicode errors so&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;pacman &lt;span class="nt"&gt;-S&lt;/span&gt; ttf-font-awesome

&lt;span class="c"&gt;# In polybar config change fonts&lt;/span&gt;
font-1 &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Font Awesome 5 Free:style=Regular:size=10;5"&lt;/span&gt;
font-2 &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Font Awesome 5 Free:style=Solid:size=10;5"&lt;/span&gt;

&lt;span class="c"&gt;# Go through all unicode characters in polybar config and replace them with icons from the FA cheatsheet&lt;/span&gt;

&lt;span class="c"&gt;# Put this line in bspwmrc. Change main to whatever the name of your bar is&lt;/span&gt;
polybar main &amp;amp;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 19 - Backing Up Your Dotfiles
&lt;/h2&gt;

&lt;p&gt;I forgot to do this the first time around and lost all my progress. It put me in a 8 month depression until I picked up Arch Linux again.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Initialize a git bare repo&lt;/span&gt;
git init &lt;span class="nt"&gt;--bare&lt;/span&gt; &lt;span class="nv"&gt;$HOME&lt;/span&gt;/.dotfiles

&lt;span class="c"&gt;# Create an alias so the bare repo mirrors your actual dotfiles&lt;/span&gt;
&lt;span class="nb"&gt;alias &lt;/span&gt;dotfiles &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"git --git-dir=&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.dotfiles/ --work-tree=&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="c"&gt;# Save alias, this will allow you to use dotfiles as a command in place of git&lt;/span&gt;
funcsave dotfiles

&lt;span class="c"&gt;# Ignore files you don't want tracked&lt;/span&gt;
dotfiles config &lt;span class="nt"&gt;--local&lt;/span&gt; status.showUntrackedFiles no

&lt;span class="c"&gt;# Create a github repo called .dotfiles&lt;/span&gt;

&lt;span class="c"&gt;# dotfiles remote add origin https://github.com/gucci-ninja/.dotfiles&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 20 - Make your windows look less ugly
&lt;/h2&gt;

&lt;p&gt;Since I have bspwm I don't have a display manager to add GTK themes to. A GTK theme is the overall theme that handles stuff like the panel color, the backgrounds for windows and tabs, how an application will look when it is active vs. inactive, buttons, check-boxes, etc. So I need a theme switcher to accomplish this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yay &lt;span class="nt"&gt;-S&lt;/span&gt; lxappearance
&lt;span class="nb"&gt;sudo &lt;/span&gt;pacman &lt;span class="nt"&gt;-S&lt;/span&gt; gtk-engine-murrine adwaita-icon-theme

&lt;span class="c"&gt;# Run lxappearance to choose the theme you want&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;90% of the aesthetics of my build were made possible largely due to this &lt;a href="https://www.reddit.com/r/unixporn/comments/74z2z6/easily_getting_started_with_bspwm_and_polybar/" rel="noopener noreferrer"&gt;reddit post&lt;/a&gt; that I wish I had found earlier.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 21 - Neofetch
&lt;/h2&gt;

&lt;p&gt;You don't need to do this, it's mostly fo showing off to people.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pacman &lt;span class="nt"&gt;-S&lt;/span&gt; neofetch

&lt;span class="c"&gt;# Add the following to fish.config&lt;/span&gt;
neofetch

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now every time you create a new terminal session you can show off.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 22 - File Manager
&lt;/h2&gt;

&lt;p&gt;I'm using &lt;a href="https://wiki.archlinux.org/title/thunar" rel="noopener noreferrer"&gt;thunar&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 23 - Aliases
&lt;/h2&gt;

&lt;p&gt;I respectfully ignore this part because I don't want to get used to an alias and look like a fool when I use another machine. But feel free to take this time to create aliases like &lt;code&gt;git add .&lt;/code&gt; = &lt;code&gt;ga&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 24 - Bluetooth
&lt;/h2&gt;

&lt;p&gt;Bluetooth can be a pain to work with even for easy to use OSes. I'll save you the trouble of setting it up on Arch.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;pacman &lt;span class="nt"&gt;-S&lt;/span&gt; bluez bluez-utils
&lt;span class="nv"&gt;$ &lt;/span&gt;pacman &lt;span class="nt"&gt;-S&lt;/span&gt; pulseaudio-bluetooth pulseaudio-alsa pavucontrol

systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;bluetooth.service

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;vim etc/bluetooth/main.conf
&lt;span class="c"&gt;# add the following line at the end&lt;/span&gt;
&lt;span class="c"&gt;# this will ensure your bluetooth headphones auto-connect&lt;/span&gt;
&lt;span class="nv"&gt;AutoEnable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;

&lt;span class="c"&gt;# make a directory for pulse (you may already have it)&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; ~/.config/pulse
&lt;span class="c"&gt;# copy sample&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cp&lt;/span&gt; /etc/pulse/&lt;span class="k"&gt;*&lt;/span&gt; ~/.config/pulse/

&lt;span class="nv"&gt;$ &lt;/span&gt;systemctl restart bluetooth

&lt;span class="nv"&gt;$ &lt;/span&gt;bluetoothctl
&lt;span class="c"&gt;# you should be in the bluetooth user now&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;bluetooth]~ power on
&lt;span class="o"&gt;[&lt;/span&gt;bluetooth]~ agent on
&lt;span class="o"&gt;[&lt;/span&gt;bluetooth]~ default-agent
&lt;span class="o"&gt;[&lt;/span&gt;bluetooth]~ scan on
&lt;span class="c"&gt;# at this point you should put your headphones in pairing mode&lt;/span&gt;
&lt;span class="c"&gt;# they should show up with a mac address&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;bluetooth]~ pair 00:00:00:00:00
&lt;span class="o"&gt;[&lt;/span&gt;bluetooth]~ connect 00:00:00:00:00
&lt;span class="c"&gt;# if this part fails run the following in a new terminal&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;pulseaudio &lt;span class="nt"&gt;--start&lt;/span&gt;
&lt;span class="c"&gt;# it should connect now&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;bluetooth]~ trust 00:00:00:00:00
&lt;span class="o"&gt;[&lt;/span&gt;bluetooth]~ scan off
&lt;span class="o"&gt;[&lt;/span&gt;bluetooth]~ &lt;span class="nb"&gt;exit&lt;/span&gt;

&lt;span class="c"&gt;# it should connect your headphoens at this point. if you don't hear sound, restart spotify or whatever and it should work&lt;/span&gt;
&lt;span class="c"&gt;# if it doesn't, open pavucontrol&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;pavucontrol

&lt;span class="c"&gt;# this interface will show you your connected devices, make sure it is not on mute and that under configuration tab it says it's connect to ADP SINK or sm dumb&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The End!
&lt;/h2&gt;

&lt;p&gt;This brings me to the end of this Arch Linux Setup Guide. I've listed a few more tips and tools that are worth looking into&lt;/p&gt;

&lt;h3&gt;
  
  
  Display Clock
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;download nerd-fonts-iosevka&lt;/li&gt;
&lt;li&gt;download tty-clock&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  More PolyBar Improvements
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;rofi for slightly better application management&lt;/li&gt;
&lt;li&gt;themes: &lt;a href="https://awesomeopensource.com/project/adi1090x/polybar-themes" rel="noopener noreferrer"&gt;https://awesomeopensource.com/project/adi1090x/polybar-themes&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Help, I updated my system and something broke.
&lt;/h2&gt;

&lt;p&gt;It's common to update your system every now and then by running &lt;code&gt;pacman -Syu&lt;/code&gt; but there have been times when updating caused issues such as wifi failure. I later checked the &lt;a href="https://archlinux.org/" rel="noopener noreferrer"&gt;Arch Linux News Page&lt;/a&gt; to find that the latest update will break for some users. In cases like these, it's best to roll back to a previous version.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# This tells you the linux version you're running&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; /var/cache/pacman/pkg
&lt;span class="c"&gt;# These are the linux versions you have saved in your cache. Find one you want to downgrade to&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;pacman &lt;span class="nt"&gt;-U&lt;/span&gt; linux-#.#.#.arch---
&lt;span class="nv"&gt;$ &lt;/span&gt;reboot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you have any questions or run into any issue, I would be happy to help out. &lt;a href="https://twitter.com/SuhaviSandhu" rel="noopener noreferrer"&gt;Here's my Twitter!&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Helpful Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://wiki.archlinux.org/title/installation_guide" rel="noopener noreferrer"&gt;https://wiki.archlinux.org/title/installation_guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://wiki.archlinux.org/title/General_recommendations" rel="noopener noreferrer"&gt;https://wiki.archlinux.org/title/General_recommendations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.linuxtechi.com/dual-boot-arch-linux-windows-10/" rel="noopener noreferrer"&gt;https://www.linuxtechi.com/dual-boot-arch-linux-windows-10/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ostechnix.com/recommended-way-clean-package-cache-arch-linux/" rel="noopener noreferrer"&gt;https://ostechnix.com/recommended-way-clean-package-cache-arch-linux/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>linux</category>
      <category>productivity</category>
      <category>bash</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
