<?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: Franco vinciarelli</title>
    <description>The latest articles on DEV Community by Franco vinciarelli (@fvinciarelli).</description>
    <link>https://dev.to/fvinciarelli</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4071616%2Fcf7e518c-59f1-45b2-a552-f1c2af0e2623.png</url>
      <title>DEV Community: Franco vinciarelli</title>
      <link>https://dev.to/fvinciarelli</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/fvinciarelli"/>
    <language>en</language>
    <item>
      <title>How to Test AI Agents Without Vendor Lock-in — Introducing ABS</title>
      <dc:creator>Franco vinciarelli</dc:creator>
      <pubDate>Mon, 10 Aug 2026 16:16:13 +0000</pubDate>
      <link>https://dev.to/fvinciarelli/how-to-test-ai-agents-without-vendor-lock-in-introducing-abs-5ea</link>
      <guid>https://dev.to/fvinciarelli/how-to-test-ai-agents-without-vendor-lock-in-introducing-abs-5ea</guid>
      <description>&lt;p&gt;You know the drill. QA opens a Word doc, types &lt;em&gt;"the bot should ask for the order number if it's missing,"&lt;/em&gt; and tests the agent by hand. Meanwhile, Dev builds against an ever-mutating PR description. And PO has nothing to sign off on that isn't prose or code.&lt;br&gt;
We solved this for APIs 20 years ago with OpenAPI. A shared contract. Machine-readable.Tool-independent. Human-auditable.&lt;strong&gt;AI agents have no equivalent.&lt;/strong&gt; Until now.&lt;/p&gt;
&lt;h2&gt;
  
  
  What ABS is — in 30 seconds
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/fvinciarelli/abslang" rel="noopener noreferrer"&gt;Agent Behavior Specification&lt;/a&gt;&lt;/strong&gt; (ABS) is a YAML format for describing observable agent behavior — messages, tool calls, hand-offs, UI interactions — independent of your LLM provider, framework, or tool protocol.&lt;/p&gt;

&lt;p&gt;One file. Three stakeholders. Two modes: descriptive &lt;em&gt;and&lt;/em&gt; executable.&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;session&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Customer checks order status&lt;/span&gt;                                                               
   &lt;span class="na"&gt;behaviors&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;                                                                                          
     &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;actor&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;user&lt;/span&gt;                                                                                     
       &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;says&lt;/span&gt;                                                                                    
       &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Where&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;my&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;#8291?"&lt;/span&gt;                                                             

     &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;actor&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;assistant&lt;/span&gt;                                                                                
       &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;calls&lt;/span&gt;                                                                                   
       &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Orders API&lt;/span&gt;                                                                              

     &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;actor&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;assistant&lt;/span&gt;                                                                                
       &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;informs&lt;/span&gt;                                                                                 
       &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Your&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;is&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;on&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;way"&lt;/span&gt;                                                             
       &lt;span class="na"&gt;evaluations&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="s"&gt;contains&lt;/span&gt;                                                                              
           &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;on&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;way"&lt;/span&gt;                                                                         
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
shell&lt;/p&gt;

&lt;p&gt;That's it. Three fields per step — actor, action, content/target. A PO reads it as a behavioral contract. QA runs it as a test. Dev uses it as acceptance criteria.&lt;br&gt;&lt;br&gt;
In this article, you'll build and run your first agent spec — in 10 minutes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Install the CLI&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; abslang                                                                              
   &lt;span class="c"&gt;# or: pip install abslang                                                                           &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   abslang &lt;span class="nt"&gt;--version&lt;/span&gt;                                                                                   
   &lt;span class="c"&gt;# abs v0.1.0                                                                                        &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Scaffold a project&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   abslang init my-agent-tests                                                                         
   &lt;span class="nb"&gt;cd &lt;/span&gt;my-agent-tests                                                                                   
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You get:&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="s"&gt;.&lt;/span&gt;                                                                                                   
   &lt;span class="s"&gt;├── abs.config.yaml&lt;/span&gt;                                                                                 
   &lt;span class="s"&gt;├── sessions/&lt;/span&gt;                                                                                       
   &lt;span class="s"&gt;│   └── order-status.abs.yaml&lt;/span&gt;    &lt;span class="c1"&gt;# Example session                                                  &lt;/span&gt;
   &lt;span class="s"&gt;└── datasets/&lt;/span&gt;                                                                                       
       &lt;span class="s"&gt;└── order-status.jsonl&lt;/span&gt;       &lt;span class="c1"&gt;# 3 test cases                                                     &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                                                                                                                                                                                                          **3. Don't want to write YAML? Chat it.**                                                                 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This is the feature that saves you 80% of the learning curve:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   abslang chat                                                                                        
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   🤖 ABS Assistant — describe the agent behavior you want to test                                     

   You: A customer reports a damaged item. The agent should verify the order, process a refund, confirm the amount and reference, and offer further help.                                                                        

   Assistant: I'll draft a refund flow with tool calls, step-level evaluations, and chain checks…                                                           
[generates complete .abs.yaml]                                                           
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Uses OPENAI_API_KEY, ANTHROPIC_API_KEY, or DEEPSEEK_API_KEY — whichever you have set. It knows the    full ABS v0.1 spec and generates validated YAML instantly.&lt;br&gt;&lt;br&gt;
                                                                                                                                                                                                              &lt;strong&gt;4. Write a session by hand&lt;/strong&gt;&lt;br&gt;
                                                                                                       Here's a refund flow across three conversational turns. No tool calls — this works with any agent:&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;session&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Damaged item → refund (multi-stage evaluation)&lt;/span&gt;                                             
   &lt;span class="na"&gt;behaviors&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;                                                                                          
     &lt;span class="c1"&gt;# ── Turn 1: the agent classifies intent ──                                                       &lt;/span&gt;
     &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;actor&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;user&lt;/span&gt;                                                                                     
       &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;says&lt;/span&gt;                                                                                    
       &lt;span class="na"&gt;content&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&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;received&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;damaged&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;item,&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;want&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;money&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;back.&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;#8291."&lt;/span&gt;                        

     &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;actor&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;assistant&lt;/span&gt;                                                                                
       &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;clarifies&lt;/span&gt;                                                                               
       &lt;span class="na"&gt;content&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&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;understand&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;your&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;#8291&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;arrived&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;damaged.&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;help&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;you&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;get&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;refund."&lt;/span&gt;           

     &lt;span class="c1"&gt;# ── Turn 2: resolution ──                                                                        &lt;/span&gt;
     &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;actor&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;user&lt;/span&gt;                                                                                     
       &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;says&lt;/span&gt;                                                                                    
       &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Yes&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;please,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;how&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;long&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;it&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;take?"&lt;/span&gt;                                                   

     &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;actor&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;assistant&lt;/span&gt;                                                                                
       &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;informs&lt;/span&gt;                                                                                 
       &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Refund&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;€47.50&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;approved.&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Reference:&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;R-5512.&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;You'll&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;receive&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;in&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;3-5&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;days."&lt;/span&gt;         
       &lt;span class="na"&gt;capture&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;                                                                                        
         &lt;span class="na"&gt;refundId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;R-5512"&lt;/span&gt;                                                                            

     &lt;span class="c1"&gt;# ── Turn 3: closing ──                                                                           &lt;/span&gt;
     &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;actor&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;user&lt;/span&gt;                                                                                     
       &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;says&lt;/span&gt;                                                                                    
       &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Great,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;thanks."&lt;/span&gt;                                                                       

     &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;actor&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;assistant&lt;/span&gt;                                                                                
       &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;confirms&lt;/span&gt;                                                                                
       &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;You're&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;welcome!&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;there&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;anything&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;else&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;can&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;help&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;with?"&lt;/span&gt;                              
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Six behaviors, three turns. Descriptive only so far — no evaluations yet.&lt;br&gt;&lt;br&gt;
                                                                                                                                                      &lt;strong&gt;5. Add evaluations at every stage&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is where ABS earns its place. Add an evaluations: block to any step:&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="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;actor&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;assistant&lt;/span&gt;                                                                                  
     &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;clarifies&lt;/span&gt;                                                                                 
     &lt;span class="na"&gt;content&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&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;understand&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;your&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;#8291&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;arrived&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;damaged.&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;help&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;you&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;get&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;refund."&lt;/span&gt;             
     &lt;span class="na"&gt;evaluations&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="s"&gt;llm_judge&lt;/span&gt;                                                                               
         &lt;span class="na"&gt;criteria&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;                                                                                   
           &lt;span class="s"&gt;1. Correctly classifies the intent as a refund request                                      &lt;/span&gt;
           &lt;span class="s"&gt;2. References the order number #8291                                                        &lt;/span&gt;
           &lt;span class="s"&gt;3. Acknowledges the damage (not a simple return)                                            &lt;/span&gt;
           &lt;span class="s"&gt;4. Takes ownership of the resolution                                                        &lt;/span&gt;

   &lt;span class="c1"&gt;# ...                                                                                               &lt;/span&gt;

   &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;actor&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;assistant&lt;/span&gt;                                                                                  
     &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;informs&lt;/span&gt;                                                                                   
     &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Refund&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;€47.50&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;approved.&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Reference:&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;R-5512.&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;You'll&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;receive&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;in&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;3-5&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;days."&lt;/span&gt;           
     &lt;span class="na"&gt;capture&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;                                                                                          
       &lt;span class="na"&gt;refundId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;R-5512"&lt;/span&gt;                                                                              
     &lt;span class="na"&gt;evaluations&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="s"&gt;contains&lt;/span&gt;                                                                                
         &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;R-5512"&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="s"&gt;llm_judge&lt;/span&gt;                                                                               
         &lt;span class="na"&gt;criteria&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;                                                                                   
           &lt;span class="s"&gt;1. States the exact refund amount (€47.50)                                                  &lt;/span&gt;
           &lt;span class="s"&gt;2. Provides the reference number R-5512                                                     &lt;/span&gt;
           &lt;span class="s"&gt;3. Sets a clear timeline (3-5 days)                                                         &lt;/span&gt;
           &lt;span class="s"&gt;4. Professional and empathetic tone                                                         &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now add chain evaluations — properties of the entire trace:&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;evaluations&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="s"&gt;sequence&lt;/span&gt;                                                                                  
       &lt;span class="na"&gt;order&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;                                                                                          
         &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;actor&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;assistant&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;clarifies&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt;                                                     
         &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;actor&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;assistant&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;informs&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt;                                                       
         &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;actor&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;assistant&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;confirms&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="s"&gt;variable_consistency&lt;/span&gt;                                                                      
       &lt;span class="na"&gt;variable&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;refundId&lt;/span&gt;                                                                              
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;sequence checks that the three stages happen in order. variable_consistency catches a subtle but deadly bug — the agent silently swapping one refund ID for another mid-conversation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Run it&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   abslang run sessions/refund.abs.yaml &lt;span class="nt"&gt;--agent&lt;/span&gt; http://localhost:8080/chat                             
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your agent needs one HTTP endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;POST&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;/chat&lt;/span&gt;&lt;span class="w"&gt;                                                                                          
   &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"messages"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"role"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;                                              
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. OpenAI-compatible. The Runner plays the user, captures the trace, and runs all evaluations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   ┌──────────────────────────────────────────────────────┐                                            
   │  ABS — Results                                       │                                            
   ├──────────────────────────────────────────────────────┤                                            
   │  Session:  Damaged item → refund                     │                                            
   │  Result:   ✅ PASSED                                 │                                            
   │  Steps:    6/6 matched · 5/5 evaluations passed      │                                            
   ├────┬──────────────────────────────────┬────────┬─────┤                                            
   │  1 │ user says "damaged item..."      │   →    │ sent│                                            
   │  2 │ assistant clarifies              │   ✅   │match│                                            
   │    │   └─ llm_judge: intent check     │   ✅   │ pass│                                            
   │  3 │ user says "how long?"            │   →    │ sent│                                            
   │  4 │ assistant informs                │   ✅   │match│                                            
   │    │   ├─ contains "R-5512"           │   ✅   │ pass│                                            
   │    │   └─ llm_judge: quality check    │   ✅   │ pass│                                            
   │  5 │ user says "thanks"               │   →    │ sent│                                            
   │  6 │ assistant confirms               │   ✅   │match│                                            
   │    │   └─ llm_judge: closing check    │   ✅   │ pass│                                            
   │  C │ sequence: clarifies→informs→conf │   ✅   │ pass│                                            
   │  C │ variable_consistency: refundId   │   ✅   │ pass│                                            
   └────┴──────────────────────────────────┴────────┴─────┘                                            
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;7. Scale it: one session, 200 test cases&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Replace hardcoded values with {{placeholders}}:&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;dataset&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="s"&gt;cases&lt;/span&gt;                                                                                         
     &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cases.jsonl&lt;/span&gt;                                                                                 

   &lt;span class="na"&gt;behaviors&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;                                                                                          
     &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;actor&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;user&lt;/span&gt;                                                                                     
       &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;says&lt;/span&gt;                                                                                    
       &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;{{cases.userMessage}}"&lt;/span&gt;                                                                
     &lt;span class="c1"&gt;# ...                                                                                             &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use your dataset file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   {"userMessage": "Item damaged, order #8291. Refund please.", ...}                                   
   {"userMessage": "Order #3412 arrived broken. I want my money back.", ...}                           
   {"userMessage": "Wrong item in box #5567. Refund.", ...}                                            
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   abslang run session.abs.yaml &lt;span class="nt"&gt;--agent&lt;/span&gt; &lt;span class="nv"&gt;$URL&lt;/span&gt; &lt;span class="nt"&gt;--dataset&lt;/span&gt; cases.jsonl                                     
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three rows, three runs, one aggregated report. Works with 3 rows or 300.                              &lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The anti-lock-in architecture&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The industry standard couples agent execution and evaluation in one platform. Deploy to their infra, they run it, they evaluate it. Change platforms → rewrite everything.&lt;/p&gt;

&lt;p&gt;ABS separates them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   Industry today:  [agent execution + evaluation] in one platform → vendor lock-in                    
   ABS:             [agent] in your infra → [trace] → [evaluation] wherever you want                   
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your agent runs on your infrastructure. The evaluator receives only {type, input, context, response, threshold} and returns {passed, score, reason}. Any provider — Azure, LangSmith, Galileo, a local Ollama instance — implements the same adapter interface in an afternoon.&lt;/p&gt;

&lt;p&gt;Your session file never changes. Only the --adapter flag.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What's shipped&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;TypeScript + Python CLI — abslang init, chat, run, report
&lt;/li&gt;
&lt;li&gt;Built-in evaluators — exact_match, contains, regex, schema, tool_call, llm_judge, Groundedness, Relevance, sequence, eventually, never, count, within, variable_consistency &lt;/li&gt;
&lt;li&gt;Agent adapters — OpenAI, Anthropic, Gemini (add yours with one function)
&lt;/li&gt;
&lt;li&gt;Visual designer — React drag &amp;amp; drop, built into the docs site
&lt;/li&gt;
&lt;li&gt;VSCode extension — visual editor + ▶ Run button (Work in progress)
&lt;/li&gt;
&lt;li&gt;JSON Schema — normative, validated at parse time
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Try it&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; abslang                                                                              
   abslang init                                                                                        
   abslang chat                                                                                        
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;GitHub: fvinciarelli/abslang — stars appreciated ⭐                                                   &lt;/p&gt;

&lt;p&gt;Docs: fvinciarelli.github.io/abslang                                                                  &lt;/p&gt;

&lt;p&gt;v0.1, open for review. If you're building or testing agents, I'd love your feedback.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>testing</category>
      <category>openapi</category>
      <category>llm</category>
    </item>
  </channel>
</rss>
