<?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: Steve Emmerich</title>
    <description>The latest articles on DEV Community by Steve Emmerich (@steveemmerich).</description>
    <link>https://dev.to/steveemmerich</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%2F92797%2F792f7168-6d40-432a-8795-66b1199f976d.jpeg</url>
      <title>DEV Community: Steve Emmerich</title>
      <link>https://dev.to/steveemmerich</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/steveemmerich"/>
    <language>en</language>
    <item>
      <title>A minimal TypeScript implementation of SAL flows</title>
      <dc:creator>Steve Emmerich</dc:creator>
      <pubDate>Wed, 07 Oct 2026 19:55:28 +0000</pubDate>
      <link>https://dev.to/steveemmerich/a-minimal-typescript-implementation-of-sal-flows-4om3</link>
      <guid>https://dev.to/steveemmerich/a-minimal-typescript-implementation-of-sal-flows-4om3</guid>
      <description>&lt;p&gt;Protocol ideas become much easier to reason about once they are visible in code.&lt;/p&gt;

&lt;p&gt;SAL, the Sovereign Agent Lifecycle Protocol, is still evolving, but the basic flow is straightforward enough to show in a small TypeScript sketch: an agent generates its own keypair, initializes into orphan state, proves possession through challenge-response, and later requests short-lived scoped access.&lt;/p&gt;

&lt;p&gt;The public spec is at &lt;a href="https://sal-protocol.dev" rel="noopener noreferrer"&gt;sal-protocol.dev&lt;/a&gt;, and the reference implementation is in &lt;a href="https://vibebase.app/docs" rel="noopener noreferrer"&gt;Vibebase&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is not production code. It is a minimal illustration of the shape.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Agent birth
&lt;/h2&gt;

&lt;p&gt;At birth, the agent creates its own Ed25519 keypair locally.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;generateKeyPairSync&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sign&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node:crypto&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;privateKey&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generateKeyPairSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ed25519&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;That private key stays with the agent. No human has to provision a shared secret for this identity to exist.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Initialization into orphan state
&lt;/h2&gt;

&lt;p&gt;The agent signs an initialization payload and submits it to the control plane.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initRequest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;public_key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ed25519:example-public-key&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;display_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;planner-agent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;capabilities&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;plan&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;read_docs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;nonce&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randomUUID&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&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;"request"&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;"public_key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ed25519:example-public-key"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"display_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"planner-agent"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"capabilities"&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="s2"&gt;"plan"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"read_docs"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"nonce"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"f0f4ecb4-e954-4c82-b7bc-bfd5829ab7cb"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"signature"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sig:agent-init"&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;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;And the response:&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&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;"agent_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"agt_01JZTS"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"state"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"orphan"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"grants"&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"scope"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"workspace:bootstrap"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"ttl_seconds"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;300&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;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 gives the agent a constrained starting point without requiring a human login flow.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Challenge-based token request
&lt;/h2&gt;

&lt;p&gt;When the agent needs scoped service access, it first requests a challenge.&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&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;"challenge"&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;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"chl_01JZTT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"nonce"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ec0ed404-c6d3-4cda-9cd2-8215ea3927ea"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"expires_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-07-28T09:05:00Z"&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;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;It signs that nonce with its private key and submits the proof:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;proof&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ec0ed404-c6d3-4cda-9cd2-8215ea3927ea&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nx"&gt;privateKey&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If policy allows the requested action, the gateway returns a short-lived scoped token:&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&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;"token"&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;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eyJhbGciOiJFZERTQSJ9..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"scope"&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="s2"&gt;"task:append"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"ttl_seconds"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;300&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;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;h2&gt;
  
  
  4. Why this shape matters
&lt;/h2&gt;

&lt;p&gt;Three things are happening here that are easy to miss if you are used to API key workflows.&lt;/p&gt;

&lt;p&gt;First, the agent identity is self-generated rather than provisioned by a human.&lt;/p&gt;

&lt;p&gt;Second, the proof of possession is fresh. The system is not trusting a copied static secret that might have been sitting in an environment variable for months.&lt;/p&gt;

&lt;p&gt;Third, the service token is separate from the root agent identity and deliberately narrow in scope and lifetime.&lt;/p&gt;

&lt;p&gt;That is the design center of SAL.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Where to go deeper
&lt;/h2&gt;

&lt;p&gt;The minimal flow above leaves out claim handshake and lineage, which are where the protocol gets more interesting in real deployments. But even this small sketch shows the basic difference between SAL and conventional software auth patterns.&lt;/p&gt;

&lt;p&gt;The goal is not just to authenticate software. The goal is to support an actual lifecycle for autonomous agents: birth, orphan state, claim, delegation, and scoped service access.&lt;/p&gt;

&lt;p&gt;If you want the full model, the protocol is at &lt;a href="https://sal-protocol.dev" rel="noopener noreferrer"&gt;sal-protocol.dev&lt;/a&gt;, and the running implementation is in &lt;a href="https://vibebase.app/docs" rel="noopener noreferrer"&gt;Vibebase docs&lt;/a&gt;. If you have built a similar flow another way, I would love to compare notes, because this is exactly the kind of area where implementation pressure makes the protocol better.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>node</category>
      <category>security</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Threat modeling SAL: what it defends against and what it doesn't</title>
      <dc:creator>Steve Emmerich</dc:creator>
      <pubDate>Wed, 30 Sep 2026 19:10:07 +0000</pubDate>
      <link>https://dev.to/steveemmerich/threat-modeling-sal-what-it-defends-against-and-what-it-doesnt-55i1</link>
      <guid>https://dev.to/steveemmerich/threat-modeling-sal-what-it-defends-against-and-what-it-doesnt-55i1</guid>
      <description>&lt;p&gt;One thing I dislike in security-adjacent writing is when a protocol is described as if it dissolves risk by being well intentioned.&lt;/p&gt;

&lt;p&gt;SAL is not that kind of protocol. It is meant to reduce specific classes of problems in agent identity. It does not make compromised hosts safe. It does not make malicious agents honest. It does not remove the need for policy, monitoring, or operational discipline.&lt;/p&gt;

&lt;p&gt;What it does try to do is tighten a few important seams in the lifecycle of autonomous agents.&lt;/p&gt;

&lt;p&gt;The public spec is at &lt;a href="https://sal-protocol.dev" rel="noopener noreferrer"&gt;sal-protocol.dev&lt;/a&gt;, and the reference implementation is in &lt;a href="https://vibebase.app/docs" rel="noopener noreferrer"&gt;Vibebase&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What SAL is trying to defend against
&lt;/h2&gt;

&lt;p&gt;First, it tries to reduce dependence on static shared secrets.&lt;/p&gt;

&lt;p&gt;Static API keys and pre-seeded bootstrap secrets create easy failure modes. They get copied, reused, leaked, and forgotten. By having agents self-generate keypairs and use challenge-based exchange, SAL reduces the need to ever transmit long-lived reusable secrets at all.&lt;/p&gt;

&lt;p&gt;Second, it tries to preserve identity continuity across lifecycle transitions.&lt;/p&gt;

&lt;p&gt;Without that, systems tend to replace credentials when agents are claimed or promoted, which makes provenance and governance fuzzier. SAL keeps the agent's private key with the agent and binds ownership separately.&lt;/p&gt;

&lt;p&gt;Third, it tries to make delegated origin verifiable.&lt;/p&gt;

&lt;p&gt;Lineage gives downstream services a way to reason about where an agent came from and what authorized its creation, instead of relying entirely on operational logs or naming conventions.&lt;/p&gt;

&lt;p&gt;Fourth, it tries to contain authorization with short-lived scoped service tokens. That reduces blast radius when a token leaks or a request path is abused.&lt;/p&gt;

&lt;h2&gt;
  
  
  What SAL does not defend against
&lt;/h2&gt;

&lt;p&gt;If an attacker fully compromises the host running the agent and can act with the agent's private key, SAL does not magically save you. At that point the attacker effectively is the agent from the protocol's perspective.&lt;/p&gt;

&lt;p&gt;If your policy model is too broad, SAL does not fix that either. You can still mint dangerous scopes. You can still allow unsafe delegation. Good identity plumbing does not replace careful authorization design.&lt;/p&gt;

&lt;p&gt;If your implementation stores lineage incorrectly, fails to verify challenges, or treats expired tokens loosely, protocol intent will not save you from implementation bugs.&lt;/p&gt;

&lt;p&gt;And if an agent is behaving maliciously by design, SAL is not a moral filter. It is an identity and delegation model.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why being explicit about this matters
&lt;/h2&gt;

&lt;p&gt;I think protocols get stronger when their threat model is stated plainly.&lt;/p&gt;

&lt;p&gt;Otherwise people adopt them hoping for properties they were never designed to provide, and then the eventual failure looks like a broken promise rather than a category mistake.&lt;/p&gt;

&lt;p&gt;For SAL, the promise is narrower and more practical:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;better lifecycle semantics for autonomous agents&lt;/li&gt;
&lt;li&gt;less dependence on static secrets&lt;/li&gt;
&lt;li&gt;cleaner separation of ownership and credential custody&lt;/li&gt;
&lt;li&gt;stronger provenance for spawned agents&lt;/li&gt;
&lt;li&gt;safer service access through short-lived scoped tokens&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is already plenty.&lt;/p&gt;

&lt;h2&gt;
  
  
  The next layer still matters
&lt;/h2&gt;

&lt;p&gt;Even with SAL, you still need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;host hardening&lt;/li&gt;
&lt;li&gt;key protection&lt;/li&gt;
&lt;li&gt;policy review&lt;/li&gt;
&lt;li&gt;anomaly detection&lt;/li&gt;
&lt;li&gt;revocation paths&lt;/li&gt;
&lt;li&gt;operational audit&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In other words, protocol design is one layer of the security story, not the whole story.&lt;/p&gt;

&lt;p&gt;If you want to dig into the model itself, the spec is at &lt;a href="https://sal-protocol.dev" rel="noopener noreferrer"&gt;sal-protocol.dev&lt;/a&gt; and the implementation is at &lt;a href="https://vibebase.app/docs" rel="noopener noreferrer"&gt;vibebase.app/docs&lt;/a&gt;. I am especially interested in feedback from people threat modeling real agent systems, because that is where protocol language stops being abstract and starts being useful.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>cybersecurity</category>
      <category>security</category>
    </item>
    <item>
      <title>What should an open agent identity standard actually standardize?</title>
      <dc:creator>Steve Emmerich</dc:creator>
      <pubDate>Wed, 23 Sep 2026 18:21:57 +0000</pubDate>
      <link>https://dev.to/steveemmerich/what-should-an-open-agent-identity-standard-actually-standardize-29ml</link>
      <guid>https://dev.to/steveemmerich/what-should-an-open-agent-identity-standard-actually-standardize-29ml</guid>
      <description>&lt;p&gt;When people say we need an open standard for agent identity, I usually agree. The harder question is what exactly should be standardized.&lt;/p&gt;

&lt;p&gt;It is easy to standardize token formats or API shapes. It is much harder to standardize lifecycle semantics: what an agent is at birth, what unowned state means, how claim works, how delegation should be represented, and how provenance should flow across spawned agents.&lt;/p&gt;

&lt;p&gt;That is the part I think matters.&lt;/p&gt;

&lt;p&gt;SAL is one attempt to define that layer. The public spec is at &lt;a href="https://sal-protocol.dev" rel="noopener noreferrer"&gt;sal-protocol.dev&lt;/a&gt;, and &lt;a href="https://vibebase.app/docs" rel="noopener noreferrer"&gt;Vibebase&lt;/a&gt; is the current reference implementation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Standardizing the wrong layer is still possible
&lt;/h2&gt;

&lt;p&gt;There is always a temptation to standardize the nearest technical artifact.&lt;/p&gt;

&lt;p&gt;Maybe it is a JWT claim set. Maybe it is a discovery endpoint. Maybe it is a challenge-response format. Those things are useful, but they are downstream of the more important question: what lifecycle are we actually trying to make interoperable?&lt;/p&gt;

&lt;p&gt;If two systems both use JWTs but disagree about whether agents can exist before ownership, they do not actually have the same identity model.&lt;/p&gt;

&lt;p&gt;If two systems both support challenge exchange but disagree about how delegation provenance is represented, they do not actually have the same trust model.&lt;/p&gt;

&lt;p&gt;So the first job of an open standard is naming the lifecycle states and transitions that matter.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I think belongs in scope
&lt;/h2&gt;

&lt;p&gt;At minimum, I think an agent identity standard should say something concrete about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;agent birth and self-generated identity&lt;/li&gt;
&lt;li&gt;whether orphan or pre-claim states exist&lt;/li&gt;
&lt;li&gt;how claim or ownership binding works&lt;/li&gt;
&lt;li&gt;how proof of possession is established&lt;/li&gt;
&lt;li&gt;how delegated spawn authority is represented&lt;/li&gt;
&lt;li&gt;how downstream systems evaluate provenance&lt;/li&gt;
&lt;li&gt;how short-lived service authorization is scoped&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those are not implementation details. They are the center of the problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters now
&lt;/h2&gt;

&lt;p&gt;Right now a lot of agent identity work still borrows patterns from user auth and service auth. That is understandable because those are the tools we have. But autonomous agents are starting to expose lifecycle concerns that those older patterns never had to model explicitly.&lt;/p&gt;

&lt;p&gt;If we standardize too low in the stack too early, we may end up with compatibility around the wrong abstractions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where SAL fits
&lt;/h2&gt;

&lt;p&gt;SAL tries to push the conversation up one layer. It is not just trying to define a token format. It is trying to define a lifecycle: birth, orphan state, claim, lineage, challenge-based exchange, and scoped service authorization.&lt;/p&gt;

&lt;p&gt;Maybe that exact set of abstractions is not the final answer. But I suspect something in that neighborhood is what the standardization effort actually needs to get right.&lt;/p&gt;

&lt;h2&gt;
  
  
  The useful kind of disagreement
&lt;/h2&gt;

&lt;p&gt;This is one of those areas where disagreement is healthy. If you think orphan state should not exist, that is useful. If you think lineage should be externalized instead of embedded in principal semantics, that is useful. If you think the right answer is extending an existing identity framework rather than defining a protocol like SAL, that is useful too.&lt;/p&gt;

&lt;p&gt;The point is not to defend one shape forever. The point is to surface the real design axes before they harden accidentally.&lt;/p&gt;

&lt;p&gt;The spec is at &lt;a href="https://sal-protocol.dev" rel="noopener noreferrer"&gt;sal-protocol.dev&lt;/a&gt;, and the implementation is at &lt;a href="https://vibebase.app/docs" rel="noopener noreferrer"&gt;Vibebase docs&lt;/a&gt;. If you are thinking about open agent identity standards right now, I would love pushback on what belongs in scope and what should stay out.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>architecture</category>
    </item>
    <item>
      <title>What Vibebase implements today from the SAL protocol</title>
      <dc:creator>Steve Emmerich</dc:creator>
      <pubDate>Wed, 16 Sep 2026 18:09:08 +0000</pubDate>
      <link>https://dev.to/steveemmerich/what-vibebase-implements-today-from-the-sal-protocol-4174</link>
      <guid>https://dev.to/steveemmerich/what-vibebase-implements-today-from-the-sal-protocol-4174</guid>
      <description>&lt;p&gt;One thing I care about with protocol work is resisting the temptation to stop at the whitepaper stage.&lt;/p&gt;

&lt;p&gt;Identity protocols are easy to make sound clean in diagrams. The harder and more useful step is implementing them in a system where requests fail, policies drift, edge cases show up, and real builders can decide whether the model is actually worth carrying forward.&lt;/p&gt;

&lt;p&gt;That is the role Vibebase plays for SAL.&lt;/p&gt;

&lt;p&gt;SAL, the Sovereign Agent Lifecycle Protocol, is the open protocol model published at &lt;a href="https://sal-protocol.dev" rel="noopener noreferrer"&gt;sal-protocol.dev&lt;/a&gt;. &lt;a href="https://vibebase.app/docs" rel="noopener noreferrer"&gt;Vibebase&lt;/a&gt; is the running implementation where we are exercising those ideas in an actual agent platform.&lt;/p&gt;

&lt;h2&gt;
  
  
  SAL is the protocol surface
&lt;/h2&gt;

&lt;p&gt;SAL defines the lifecycle and trust semantics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;agents self-generate Ed25519 keypairs at birth&lt;/li&gt;
&lt;li&gt;they can begin in orphan state&lt;/li&gt;
&lt;li&gt;humans can claim them without taking key custody&lt;/li&gt;
&lt;li&gt;token exchange is challenge-based&lt;/li&gt;
&lt;li&gt;lineage carries delegation provenance&lt;/li&gt;
&lt;li&gt;service tokens are short-lived and scoped&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is the conceptual layer. It is meant to be portable and implementable outside Vibebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Vibebase is where the model gets tested
&lt;/h2&gt;

&lt;p&gt;Vibebase implements those ideas as working product behavior rather than just abstract spec language.&lt;/p&gt;

&lt;p&gt;That matters because a lot of design decisions only become visible when they hit running code. How small can orphan scope be while still being useful? What shape of claim handshake is ergonomic enough for builders to adopt? How much lineage needs to travel with a token to remain useful without becoming bloated? Where does challenge exchange create friction, and where does it buy real safety?&lt;/p&gt;

&lt;p&gt;Those are implementation questions, but they feed back into protocol quality.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I think the separation is healthy
&lt;/h2&gt;

&lt;p&gt;I do not want SAL to become "the Vibebase auth format." If the protocol only works inside one product, it is not really doing protocol work. It is doing product naming.&lt;/p&gt;

&lt;p&gt;Keeping the protocol public and the implementation concrete creates a better feedback loop. People can critique the concepts independently of the product. They can also inspect whether the product is honestly carrying the ideas through.&lt;/p&gt;

&lt;p&gt;That has already been useful for me as a builder. It forces precision. If a concept in the spec cannot survive contact with implementation, it probably was not as well-formed as it looked on paper.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I would read the two together
&lt;/h2&gt;

&lt;p&gt;If you are coming at this fresh, I would read &lt;a href="https://sal-protocol.dev" rel="noopener noreferrer"&gt;sal-protocol.dev&lt;/a&gt; to understand the lifecycle model and then use &lt;a href="https://vibebase.app/docs" rel="noopener noreferrer"&gt;Vibebase docs&lt;/a&gt; to see how that model shows up in a real developer surface.&lt;/p&gt;

&lt;p&gt;The spec answers "what does this protocol claim should exist?"&lt;/p&gt;

&lt;p&gt;The implementation answers "what does this feel like when somebody actually has to build against it?"&lt;/p&gt;

&lt;p&gt;I think both views matter. Protocol work without implementation becomes vague quickly. Implementation without an open protocol tends to stay local and harder to reason about.&lt;/p&gt;

&lt;h2&gt;
  
  
  Still very much in motion
&lt;/h2&gt;

&lt;p&gt;Vibebase is not intended as proof that the problem is finished. It is proof that the problem is real enough to deserve a concrete attempt.&lt;/p&gt;

&lt;p&gt;If you are building agent systems and want to push on the model, that is exactly the kind of pressure I want. The more this can be tested by people outside my immediate assumptions, the better the protocol will get.&lt;/p&gt;

&lt;p&gt;The spec is at &lt;a href="https://sal-protocol.dev" rel="noopener noreferrer"&gt;sal-protocol.dev&lt;/a&gt;, the reference implementation is at &lt;a href="https://vibebase.app/docs" rel="noopener noreferrer"&gt;vibebase.app/docs&lt;/a&gt;, and the useful question is still the same: does this lifecycle model make agent identity easier to reason about than the patterns we have been borrowing from user-centric auth?&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Designing the full agent identity lifecycle: birth, claim, delegation, retirement</title>
      <dc:creator>Steve Emmerich</dc:creator>
      <pubDate>Wed, 09 Sep 2026 17:47:01 +0000</pubDate>
      <link>https://dev.to/steveemmerich/designing-the-full-agent-identity-lifecycle-birth-claim-delegation-retirement-40k7</link>
      <guid>https://dev.to/steveemmerich/designing-the-full-agent-identity-lifecycle-birth-claim-delegation-retirement-40k7</guid>
      <description>&lt;p&gt;Most identity systems are designed around sessions or credentials.&lt;/p&gt;

&lt;p&gt;Autonomous agents need something closer to a lifecycle model.&lt;/p&gt;

&lt;p&gt;That sounds subtle, but it changes how you think about nearly everything. Instead of asking only how an agent authenticates right now, you have to ask how it is born, how it acquires bounded authority, how it becomes governed, how it delegates, and how it eventually loses or retires that authority.&lt;/p&gt;

&lt;p&gt;SAL, the Sovereign Agent Lifecycle Protocol, is an attempt to make that lifecycle explicit. The public spec is at &lt;a href="https://sal-protocol.dev" rel="noopener noreferrer"&gt;sal-protocol.dev&lt;/a&gt;, and &lt;a href="https://vibebase.app/docs" rel="noopener noreferrer"&gt;Vibebase&lt;/a&gt; is the reference implementation we are using to prove the model in practice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Birth
&lt;/h2&gt;

&lt;p&gt;SAL begins with agent birth.&lt;/p&gt;

&lt;p&gt;At creation time, the agent self-generates an Ed25519 keypair. That gives it an identity from the first moment of existence without requiring a person or central issuer to hand it a secret.&lt;/p&gt;

&lt;p&gt;This is the first major difference from traditional auth models. The agent does not wait for a human to show up before it can become a principal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Orphan
&lt;/h2&gt;

&lt;p&gt;After birth comes orphan state.&lt;/p&gt;

&lt;p&gt;In SAL, an orphan agent is real, authenticated, and constrained. It can prove possession of its key material and request narrow bootstrap capabilities, but it is not yet claimed by a human owner.&lt;/p&gt;

&lt;p&gt;That lets the system support useful autonomous startup work without pretending the agent is either anonymous or fully trusted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Claim
&lt;/h2&gt;

&lt;p&gt;Claim is the transition from autonomous-but-unowned to autonomous-and-governed.&lt;/p&gt;

&lt;p&gt;A human can cryptographically bind ownership to the agent without ever taking custody of the agent's private key. This is one of the most important properties in the model because it preserves both continuity and boundary clarity.&lt;/p&gt;

&lt;p&gt;The same agent identity survives before and after claim. Only the trust relationship changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Delegation
&lt;/h2&gt;

&lt;p&gt;Once an agent is claimed, it may need to request additional access or spawn other agents.&lt;/p&gt;

&lt;p&gt;This is where lineage and scoped token exchange become part of the lifecycle. The parent agent can create children only under policy, and those children carry provenance about who spawned them and under what authorization. Service access is minted through short-lived, challenge-based, scoped tokens instead of copied static secrets.&lt;/p&gt;

&lt;p&gt;That gives you a graph of authority that is both more dynamic and more inspectable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Retirement
&lt;/h2&gt;

&lt;p&gt;Retirement is the least glamorous part of identity design and one of the most important.&lt;/p&gt;

&lt;p&gt;An agent should be able to lose authority in clear ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;orphan agents can expire unclaimed&lt;/li&gt;
&lt;li&gt;claimed agents can be suspended or unbound&lt;/li&gt;
&lt;li&gt;delegated grants can expire or be revoked&lt;/li&gt;
&lt;li&gt;descendant agents can lose inherited authority when parent conditions change&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your identity model does not account for these endings, it is not really a lifecycle model. It is a startup model with wishful thinking about the rest.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why lifecycle is the right abstraction
&lt;/h2&gt;

&lt;p&gt;I think agent systems get harder to reason about when we force them into models built primarily for user sessions or static infrastructure credentials.&lt;/p&gt;

&lt;p&gt;A session-centric model focuses on login. A secret-centric model focuses on storage. A lifecycle model focuses on continuity, transitions, and authority boundaries over time.&lt;/p&gt;

&lt;p&gt;That feels much closer to how autonomous software actually behaves.&lt;/p&gt;

&lt;h2&gt;
  
  
  What SAL defines
&lt;/h2&gt;

&lt;p&gt;At a high level, SAL defines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;self-generated identity at birth&lt;/li&gt;
&lt;li&gt;orphan state before ownership&lt;/li&gt;
&lt;li&gt;claim handshake without key custody transfer&lt;/li&gt;
&lt;li&gt;challenge-based token exchange&lt;/li&gt;
&lt;li&gt;lineage for delegated provenance&lt;/li&gt;
&lt;li&gt;scoped, short-lived service authorization&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is not the only possible lifecycle model, but it is the one we are testing in the open.&lt;/p&gt;

&lt;p&gt;If you want to go deeper, the protocol is at &lt;a href="https://sal-protocol.dev" rel="noopener noreferrer"&gt;sal-protocol.dev&lt;/a&gt; and the implementation is at &lt;a href="https://vibebase.app/docs" rel="noopener noreferrer"&gt;Vibebase docs&lt;/a&gt;. If you are building agents, I would especially love to hear where your current lifecycle model gets awkward, because that is usually where the standards work actually starts.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>architecture</category>
      <category>authentication</category>
      <category>security</category>
    </item>
    <item>
      <title>Short-lived, scoped, challenge-based: designing safer service tokens for agents</title>
      <dc:creator>Steve Emmerich</dc:creator>
      <pubDate>Wed, 01 Jul 2026 05:14:34 +0000</pubDate>
      <link>https://dev.to/steveemmerich/short-lived-scoped-challenge-based-designing-safer-service-tokens-for-agents-1eno</link>
      <guid>https://dev.to/steveemmerich/short-lived-scoped-challenge-based-designing-safer-service-tokens-for-agents-1eno</guid>
      <description>&lt;p&gt;A lot of security design comes down to asking a plain question: if this credential leaks, how bad is the day going to be?&lt;/p&gt;

&lt;p&gt;For agent systems, that question gets sharper quickly. Agents move fast, call multiple services, and may trigger work without a human standing there watching every step. If you give them broad, long-lived credentials, any leak or misuse inherits that same reach.&lt;/p&gt;

&lt;p&gt;That is why SAL leans on short-lived, scoped, challenge-based service tokens rather than static secrets. The protocol spec is at &lt;a href="https://sal-protocol.dev" rel="noopener noreferrer"&gt;sal-protocol.dev&lt;/a&gt;, and &lt;a href="https://vibebase.app/docs" rel="noopener noreferrer"&gt;Vibebase&lt;/a&gt; is the live reference implementation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Narrow scope beats broad convenience
&lt;/h2&gt;

&lt;p&gt;The easiest mistake is to give an agent one credential that does everything it might need.&lt;/p&gt;

&lt;p&gt;That feels efficient at first. In practice it makes containment hard. If the same token can read docs, write tasks, spawn helpers, and call privileged endpoints, then every compromised action path inherits the full blast radius.&lt;/p&gt;

&lt;p&gt;A better pattern is to mint tokens for specific actions or narrow classes of actions. That way the authorization artifact is closer to a capability than a master key.&lt;/p&gt;

&lt;p&gt;For example:&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&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;"requested_scope"&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="s2"&gt;"task:append"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"granted_scope"&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="s2"&gt;"task:append"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ttl_seconds"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;300&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 is a much easier thing to reason about than "here is a long-lived API token for the whole workspace."&lt;/p&gt;

&lt;h2&gt;
  
  
  Short lifetime is part of the design, not an afterthought
&lt;/h2&gt;

&lt;p&gt;Short TTLs matter for the same reason narrow scope matters: they reduce the value of a leaked artifact.&lt;/p&gt;

&lt;p&gt;If a token only lives for a few minutes, the attacker does not just need the token. They also need to act quickly and within its narrow scope. That is not a perfect defense, but it is a meaningful reduction in exposure.&lt;/p&gt;

&lt;p&gt;Short-lived tokens also encourage cleaner architecture. Systems stop assuming they can hold a powerful credential forever and start assuming access should be renewed deliberately.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why challenge-based exchange matters
&lt;/h2&gt;

&lt;p&gt;The third piece is how the token gets minted.&lt;/p&gt;

&lt;p&gt;SAL uses challenge-based exchange so the network can verify fresh proof of possession from the agent without requiring a static secret to be transmitted. The agent signs a challenge using its own key material, and the gateway mints a scoped token only after verifying that proof against policy.&lt;/p&gt;

&lt;p&gt;A simplified shape might look like this:&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&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;"challenge"&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;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"chl_01JZB7"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"nonce"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"6d743c2f-73f2-4f74-8c2f-4e41f512ab74"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"expires_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-06-23T09:05:00Z"&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;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;And then:&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&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;"token"&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;"ttl_seconds"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"scope"&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="s2"&gt;"task:append"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"aud"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://api.vibebase.app/gateway"&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;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;No copied static bearer secret needs to move across the wire to make that exchange happen.&lt;/p&gt;

&lt;h2&gt;
  
  
  This is especially important for agents
&lt;/h2&gt;

&lt;p&gt;Human sessions tolerate some mess because humans are relatively sparse and easier to interrupt. Agent systems are the opposite. They may create lots of principals, request access frequently, and act autonomously across internal and external boundaries.&lt;/p&gt;

&lt;p&gt;That means two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;leaks are more likely if you rely on widespread shared secrets&lt;/li&gt;
&lt;li&gt;overbroad credentials become harder to reason about as the graph grows&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Short-lived scoped tokens do not solve every problem, but they give you a control point that fits agent behavior better than static keys do.&lt;/p&gt;

&lt;h2&gt;
  
  
  The practical takeaway
&lt;/h2&gt;

&lt;p&gt;If you are designing auth for agent-to-service calls, try not to start with "what long-lived token should this agent keep?" Start with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;what exact action does it need right now&lt;/li&gt;
&lt;li&gt;how briefly can that authorization live&lt;/li&gt;
&lt;li&gt;what proof should it present before getting it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is the design center SAL is pushing toward.&lt;/p&gt;

&lt;p&gt;If you want to dig deeper, the protocol is at &lt;a href="https://sal-protocol.dev" rel="noopener noreferrer"&gt;sal-protocol.dev&lt;/a&gt;, and &lt;a href="https://vibebase.app/docs" rel="noopener noreferrer"&gt;Vibebase&lt;/a&gt; shows the model in a running system. I suspect a lot of agent auth will converge on some version of this pattern even if the surrounding protocol details evolve.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>cybersecurity</category>
      <category>security</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>Static API keys are the wrong primitive for agent authentication</title>
      <dc:creator>Steve Emmerich</dc:creator>
      <pubDate>Wed, 24 Jun 2026 14:34:55 +0000</pubDate>
      <link>https://dev.to/steveemmerich/static-api-keys-are-the-wrong-primitive-for-agent-authentication-3del</link>
      <guid>https://dev.to/steveemmerich/static-api-keys-are-the-wrong-primitive-for-agent-authentication-3del</guid>
      <description>&lt;p&gt;API keys survive because they are convenient.&lt;/p&gt;

&lt;p&gt;You can generate one in a dashboard, paste it into an environment variable, and be done in a minute. For a lot of software integrations, that is a perfectly acceptable tradeoff.&lt;/p&gt;

&lt;p&gt;For autonomous agents, though, API keys are usually the wrong primitive.&lt;/p&gt;

&lt;p&gt;That is not because they are old or unfashionable. It is because they smuggle in a set of assumptions that do not line up with how agents are actually born, deployed, and governed.&lt;/p&gt;

&lt;p&gt;This is one of the design pressures that led to SAL, the Sovereign Agent Lifecycle Protocol. The spec is at &lt;a href="https://sal-protocol.dev" rel="noopener noreferrer"&gt;sal-protocol.dev&lt;/a&gt;, and the reference implementation lives in &lt;a href="https://vibebase.app/docs" rel="noopener noreferrer"&gt;Vibebase&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  API keys assume manual provisioning
&lt;/h2&gt;

&lt;p&gt;The first problem with API keys is operational, not cryptographic.&lt;/p&gt;

&lt;p&gt;An API key has to come from somewhere. Usually a human or central admin creates it, copies it, stores it, distributes it, and later rotates it. That workflow is normal enough that many teams stop noticing how much it shapes the system.&lt;/p&gt;

&lt;p&gt;But an autonomous agent should not need a person to hand it a secret in order to exist.&lt;/p&gt;

&lt;p&gt;If every new agent needs a copied secret, then agent creation is not really autonomous. It is a provisioning ceremony with automation around the edges.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shared secrets flatten identity
&lt;/h2&gt;

&lt;p&gt;API keys also flatten the trust model.&lt;/p&gt;

&lt;p&gt;If two instances share the same key, they are indistinguishable. If one instance leaks the key, every downstream system sees the attacker as the same principal. If you need per-agent identity, provenance, and delegation, a bucket of static shared secrets is not a great foundation.&lt;/p&gt;

&lt;p&gt;This gets even worse when agents begin spawning other agents. Do children inherit the same key? Do they request their own keys from a central issuer? Do you let one agent mint static credentials for another? None of these answers feel especially good once you write them down.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rotation is not a lifecycle model
&lt;/h2&gt;

&lt;p&gt;Teams sometimes answer the criticism by saying "we rotate keys." That is good hygiene. It is not the same thing as having the right identity primitive.&lt;/p&gt;

&lt;p&gt;Rotation helps limit exposure. It does not solve:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;agent birth without human intervention&lt;/li&gt;
&lt;li&gt;ownership without key custody&lt;/li&gt;
&lt;li&gt;provenance across spawned agents&lt;/li&gt;
&lt;li&gt;challenge-based proof of possession&lt;/li&gt;
&lt;li&gt;action-specific short-lived authorization&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those are lifecycle problems, not just secret management problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  What SAL does differently
&lt;/h2&gt;

&lt;p&gt;SAL starts with self-generated agent identity. At birth, an agent generates its own Ed25519 keypair. No static secret has to be provisioned by a human. No reusable bearer credential has to be transmitted.&lt;/p&gt;

&lt;p&gt;When the agent needs access, it does not present a copied long-lived secret. It participates in challenge-based exchange and requests narrowly scoped, short-lived tokens.&lt;/p&gt;

&lt;p&gt;Here is a simplified token result:&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&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;"token"&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;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"ttl_seconds"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"scope"&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="s2"&gt;"task:append"&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;"challenge"&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;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"chl_01JZA2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"nonce"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2d91e3f1-4af6-4777-b53a-12cb4df9b0f6"&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;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;The authorization material is short-lived, scoped, and bound to an agent that already has its own identity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the distinction matters
&lt;/h2&gt;

&lt;p&gt;Once you view identity this way, API keys start to look like a coarse compatibility tool rather than the native shape of agent auth.&lt;/p&gt;

&lt;p&gt;They are still useful at boundaries where modern patterns are unavailable. There will always be legacy systems. But if the center of your agent architecture depends on static copied secrets, you are building on a primitive that does not understand the lifecycle you are trying to support.&lt;/p&gt;

&lt;p&gt;Agents need something closer to sovereign identity than secret distribution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this is going
&lt;/h2&gt;

&lt;p&gt;That is the motivation behind SAL. The protocol tries to formalize a lifecycle in which agents can be born, operate in orphan state, be claimed later, request challenge-based short-lived access, and carry lineage forward as they delegate.&lt;/p&gt;

&lt;p&gt;You can read the spec at &lt;a href="https://sal-protocol.dev" rel="noopener noreferrer"&gt;sal-protocol.dev&lt;/a&gt; and see the current implementation in &lt;a href="https://vibebase.app/docs" rel="noopener noreferrer"&gt;Vibebase&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I do not think API keys are disappearing. I do think they should stop being the default answer whenever someone says "software needs to authenticate." For autonomous agents, the interesting question is not how to distribute secrets better. It is how to stop depending on static secrets in the first place.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>webdev</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Lineage, not logs: why autonomous agents need cryptographic provenance</title>
      <dc:creator>Steve Emmerich</dc:creator>
      <pubDate>Tue, 23 Jun 2026 16:15:17 +0000</pubDate>
      <link>https://dev.to/steveemmerich/lineage-not-logs-why-autonomous-agents-need-cryptographic-provenance-2g31</link>
      <guid>https://dev.to/steveemmerich/lineage-not-logs-why-autonomous-agents-need-cryptographic-provenance-2g31</guid>
      <description>&lt;p&gt;When people talk about provenance in software systems, they often mean logs.&lt;/p&gt;

&lt;p&gt;Logs matter. They tell you what happened, when it happened, and sometimes why it happened. But logs are an after-the-fact observation layer. They are not identity structure. They do not, by themselves, give downstream systems a cryptographic way to reason about origin, delegation, and inherited authority.&lt;/p&gt;

&lt;p&gt;That distinction starts to matter a lot once autonomous agents begin creating other agents.&lt;/p&gt;

&lt;p&gt;SAL treats provenance as part of identity itself through a concept called lineage. The spec is at &lt;a href="https://sal-protocol.dev" rel="noopener noreferrer"&gt;sal-protocol.dev&lt;/a&gt;, and &lt;a href="https://vibebase.app/docs" rel="noopener noreferrer"&gt;Vibebase&lt;/a&gt; is the live reference implementation.&lt;/p&gt;

&lt;h2&gt;
  
  
  What lineage means in SAL
&lt;/h2&gt;

&lt;p&gt;In SAL, lineage is a cryptographic chain describing who spawned an agent and what authorization allowed that spawn to happen.&lt;/p&gt;

&lt;p&gt;If agent A creates agent B, then B can carry signed lineage metadata tying it back to A and the grant under which A was allowed to create children. If B later creates C, that relationship can extend again.&lt;/p&gt;

&lt;p&gt;The point is not to build a family tree for fun. The point is to make delegation verifiable as part of the principal, not just discoverable later through operational records.&lt;/p&gt;

&lt;p&gt;Here is a simplified claims shape:&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&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;"claims"&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;"sub"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"agt_child_01JZ1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"scope"&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="s2"&gt;"task:append"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"lineage"&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"agent_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"agt_root_01JY8"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"authorized_by"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"did:key:z6Mkp9..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"grant_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"grt_root_spawn"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"signature"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sig:root..."&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;span class="nl"&gt;"agent_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"agt_parent_01JY9"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"authorized_by"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"agt_root_01JY8"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"grant_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"grt_parent_spawn"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"signature"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sig:parent..."&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;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="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 tells a downstream verifier more than "this token is valid." It gives a cryptographic path of delegation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why logs are not enough
&lt;/h2&gt;

&lt;p&gt;The usual response here is that audit logs already solve the provenance problem. I do not think they do.&lt;/p&gt;

&lt;p&gt;Logs answer questions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;what API call happened&lt;/li&gt;
&lt;li&gt;when it happened&lt;/li&gt;
&lt;li&gt;what service observed it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lineage answers different questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;who created this agent&lt;/li&gt;
&lt;li&gt;under what authority&lt;/li&gt;
&lt;li&gt;what chain of delegation led to this current principal&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can absolutely record lineage events in logs. But that is not the same as lineage being present in the identity model itself.&lt;/p&gt;

&lt;p&gt;If provenance lives only in logs, every downstream service has to trust that some upstream system observed, stored, retained, and can still correctly correlate the relevant events. If provenance is carried as signed identity material, a verifier can reason about it directly at decision time.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this enables
&lt;/h2&gt;

&lt;p&gt;Once provenance is cryptographic instead of purely observational, policy gets more interesting.&lt;/p&gt;

&lt;p&gt;A gateway can decide to mint a short-lived scoped token only if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the requesting agent descends from an approved parent&lt;/li&gt;
&lt;li&gt;the parent held a grant that allowed spawning&lt;/li&gt;
&lt;li&gt;the inherited policy envelope is compatible with the requested action&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That lets teams build guardrails around delegation rather than around isolated principals.&lt;/p&gt;

&lt;p&gt;This matters because autonomous systems rarely stay flat. If agents become useful, they start specializing. Planning agents create execution agents. Coordination agents create task-specific helpers. Research agents create retrieval workers. Once that starts happening, you want more than a spreadsheet saying "we think these are related."&lt;/p&gt;

&lt;h2&gt;
  
  
  Provenance as governance substrate
&lt;/h2&gt;

&lt;p&gt;The deeper reason I like lineage is that it gives governance something concrete to stand on.&lt;/p&gt;

&lt;p&gt;Without lineage, governance around agents often degenerates into naming conventions, tags, and logging pipelines. Those things are helpful, but they are weak substitutes for cryptographic inheritance. They help humans inspect systems. They do not help systems reason about each other under pressure.&lt;/p&gt;

&lt;p&gt;With lineage, the control plane can make decisions based on inherited authority, not just present-time claims. That feels closer to how autonomous systems actually evolve.&lt;/p&gt;

&lt;h2&gt;
  
  
  Open questions I still care about
&lt;/h2&gt;

&lt;p&gt;I do not think lineage is fully standardized yet, even conceptually. There are still good questions about representation, compression, privacy boundaries, and revocation semantics in long delegation chains.&lt;/p&gt;

&lt;p&gt;That is part of why SAL is public. The protocol is at &lt;a href="https://sal-protocol.dev" rel="noopener noreferrer"&gt;sal-protocol.dev&lt;/a&gt;, and &lt;a href="https://vibebase.app/docs" rel="noopener noreferrer"&gt;Vibebase&lt;/a&gt; is where we are working through these questions in code.&lt;/p&gt;

&lt;p&gt;If you are building agents and relying entirely on logs for provenance today, I do not think that is wrong. I do think it is probably incomplete. The moment your agents start creating other agents, provenance stops being a nice-to-have and starts becoming part of identity itself.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>architecture</category>
      <category>security</category>
      <category>web3</category>
    </item>
    <item>
      <title>How the SAL claim handshake binds humans to agents without key custody</title>
      <dc:creator>Steve Emmerich</dc:creator>
      <pubDate>Thu, 04 Jun 2026 13:41:20 +0000</pubDate>
      <link>https://dev.to/steveemmerich/how-the-sal-claim-handshake-binds-humans-to-agents-without-key-custody-3ppo</link>
      <guid>https://dev.to/steveemmerich/how-the-sal-claim-handshake-binds-humans-to-agents-without-key-custody-3ppo</guid>
      <description>&lt;p&gt;One of the easiest mistakes in agent identity design is to collapse ownership and key custody into the same thing.&lt;/p&gt;

&lt;p&gt;If a human owns an agent, it can feel natural to assume the human should also hold the credential that defines that agent. But once you do that, you create a weird security model. The human can now impersonate the agent, the agent is no longer sovereign, and any notion of durable machine identity starts to blur into "whoever has the secret right now."&lt;/p&gt;

&lt;p&gt;The SAL claim handshake is designed to avoid that.&lt;/p&gt;

&lt;p&gt;In SAL, the agent generates and keeps its own private key for its whole lifecycle. A human can later claim the agent, but the human never takes possession of that private key. Ownership is attached cryptographically. Credential custody stays with the agent.&lt;/p&gt;

&lt;p&gt;The protocol spec lives at &lt;a href="https://sal-protocol.dev" rel="noopener noreferrer"&gt;sal-protocol.dev&lt;/a&gt;, and &lt;a href="https://vibebase.app/docs" rel="noopener noreferrer"&gt;Vibebase&lt;/a&gt; is the current reference implementation.&lt;/p&gt;

&lt;h2&gt;
  
  
  What problem the handshake is solving
&lt;/h2&gt;

&lt;p&gt;Once an orphan agent exists, you need a way to establish a relationship between that agent and a human principal.&lt;/p&gt;

&lt;p&gt;The usual approaches all have tradeoffs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;hand the agent a shared secret from the human side&lt;/li&gt;
&lt;li&gt;rotate the agent onto a new credential after a user claims it&lt;/li&gt;
&lt;li&gt;let the platform act as the keeper of all long-term keys&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All three approaches muddle authority boundaries.&lt;/p&gt;

&lt;p&gt;If a human gives the agent a secret, then the agent's identity depends on manual provisioning. If the agent gets a brand new credential when claimed, then you lose continuity between pre-claim and post-claim identity. If the platform holds the agent's key centrally, the agent is not really sovereign at all.&lt;/p&gt;

&lt;p&gt;The claim handshake gives you continuity without shared custody.&lt;/p&gt;

&lt;h2&gt;
  
  
  The shape of the handshake
&lt;/h2&gt;

&lt;p&gt;At a high level, the claim handshake proves three things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;the agent controls the private key corresponding to its public identity&lt;/li&gt;
&lt;li&gt;the human controls the principal that is claiming ownership&lt;/li&gt;
&lt;li&gt;both sides agreed to the relationship at a particular time&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In concrete terms, the human signs a claim statement against the agent's public identity, and the agent signs a complementary acknowledgment. The network verifies both and records the bond.&lt;/p&gt;

&lt;p&gt;Here is a simplified claim result:&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&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;"claim"&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;"agent_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"agt_01JY8H8JQW9VG7J2Y5M3F4K2D1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"owner_did"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"did:key:z6Mkf7..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"claimed_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-06-02T09:00:00Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"agent_public_key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ed25519:5QF8uP1xj7f5Q9k5x6q8w3n4Q3dK9uN1mX0yQk7Q2E4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"owner_signature"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sig:7bLp..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"agent_signature"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sig:91Qa..."&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;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;The important thing is what is not happening here. No one is passing around a reusable shared secret. No one is exporting the agent's private key. No one is replacing the agent's identity with a new one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this separation matters
&lt;/h2&gt;

&lt;p&gt;Separating ownership from credential possession buys you several things.&lt;/p&gt;

&lt;p&gt;First, it preserves a clean trust boundary. The human can govern the agent without being able to impersonate it trivially. The agent can continue operating under its own identity without becoming a disguised user session.&lt;/p&gt;

&lt;p&gt;Second, it improves continuity. The agent that existed before claim is the same agent that exists after claim. Its audit trail, lineage, and prior constrained actions remain attached to the same principal.&lt;/p&gt;

&lt;p&gt;Third, it fits real-world operations better. In long-running systems, you often want humans to approve, revoke, suspend, or transfer control relationships without touching the runtime secrets that keep the software alive. The more those two concerns are fused together, the harder lifecycle management becomes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Claim is not elevation by default
&lt;/h2&gt;

&lt;p&gt;Another important property of the handshake is that claim does not imply unlimited privilege.&lt;/p&gt;

&lt;p&gt;Once a claim is recorded, the agent can request broader capabilities than it had in orphan state. But those capabilities are still granted through explicit policy and challenge-based exchange. Claim establishes a relationship. It does not erase the need for scoped authorization.&lt;/p&gt;

&lt;p&gt;That means a gateway can still reason about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;who owns the agent&lt;/li&gt;
&lt;li&gt;what state the agent is in&lt;/li&gt;
&lt;li&gt;what scopes the agent is requesting&lt;/li&gt;
&lt;li&gt;whether the current request fits the allowed policy envelope&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In other words, claim changes the trust model, not the need for trust decisions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I think this generalizes
&lt;/h2&gt;

&lt;p&gt;The more I worked on SAL, the more this felt like a general pattern rather than a product-specific trick.&lt;/p&gt;

&lt;p&gt;Autonomous systems need durable machine identity. Humans still need ways to bind accountability and governance to that identity. Those are related concerns, but they are not the same concern. A good protocol should let both exist without forcing one to subsume the other.&lt;/p&gt;

&lt;p&gt;That is what the claim handshake is trying to do.&lt;/p&gt;

&lt;p&gt;If you want to dig into the model, the spec is at &lt;a href="https://sal-protocol.dev" rel="noopener noreferrer"&gt;sal-protocol.dev&lt;/a&gt;, and the reference implementation is in &lt;a href="https://vibebase.app/docs" rel="noopener noreferrer"&gt;Vibebase&lt;/a&gt;. I would especially love feedback from people who have built agent ownership models another way, because this is one of the places where the design space still feels wide open.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>auth</category>
      <category>opensource</category>
      <category>webdev</category>
    </item>
    <item>
      <title>The orphan state: giving agents identity before ownership</title>
      <dc:creator>Steve Emmerich</dc:creator>
      <pubDate>Tue, 26 May 2026 04:00:00 +0000</pubDate>
      <link>https://dev.to/steveemmerich/the-orphan-state-giving-agents-identity-before-ownership-5a70</link>
      <guid>https://dev.to/steveemmerich/the-orphan-state-giving-agents-identity-before-ownership-5a70</guid>
      <description>&lt;p&gt;The most novel concept in SAL is not keys, signatures, or token exchange. It is a lifecycle state.&lt;/p&gt;

&lt;p&gt;We call it the orphan state.&lt;/p&gt;

&lt;p&gt;An orphan agent is an agent that already exists as a cryptographic principal, can authenticate itself, and can do useful work with constrained scope, but has not yet been claimed by a human owner. That sounds simple, but it points at a real gap in how most identity systems are designed.&lt;/p&gt;

&lt;p&gt;Most existing auth patterns assume that software becomes trusted only after a person or central control plane provisions it. In practice, that means one of two things happens. Either the agent is blocked until a human shows up, or it starts life with a static secret somebody had to copy into place. Both options are awkward if you are trying to build autonomous systems that can instantiate, initialize, and negotiate capability on their own.&lt;/p&gt;

&lt;p&gt;SAL starts from a different premise: an agent should be able to be born first and owned second.&lt;/p&gt;

&lt;h2&gt;
  
  
  What orphan actually means
&lt;/h2&gt;

&lt;p&gt;An orphan agent is not anonymous. It is not a guest user. It is not a fake placeholder waiting to become real later.&lt;/p&gt;

&lt;p&gt;At birth, the agent generates its own Ed25519 keypair locally. From that moment on, it has a durable identity that can sign requests and prove possession of the corresponding private key. The system can authenticate that agent immediately.&lt;/p&gt;

&lt;p&gt;What the system does not grant immediately is broad authority.&lt;/p&gt;

&lt;p&gt;That distinction matters. Identity and authority are not the same thing. SAL uses orphan state to separate them cleanly. The agent can prove who it is, but its scope is intentionally narrow until a human or parent agent establishes a stronger trust relationship.&lt;/p&gt;

&lt;p&gt;Here is a simplified initialization exchange:&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&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;"request"&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;"public_key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ed25519:5QF8uP1xj7f5Q9k5x6q8w3n4Q3dK9uN1mX0yQk7Q2E4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"display_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"planner-agent"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"capabilities"&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="s2"&gt;"plan"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"read_docs"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"nonce"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"9db2e2c1-9775-4c66-a8e2-4b281e7cb5c1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"signature"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sig:3yVx..."&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;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;And the response:&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&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;"agent_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"agt_01JY8H8JQW9VG7J2Y5M3F4K2D1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"state"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"orphan"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"grants"&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"scope"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"workspace:bootstrap"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"ttl_seconds"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;300&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;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;The system recognizes the agent as real, but only trusts it enough to perform bounded bootstrap work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters in actual systems
&lt;/h2&gt;

&lt;p&gt;If you are not building autonomous systems, orphan state can sound overly abstract. In practice it solves a very concrete set of problems.&lt;/p&gt;

&lt;p&gt;An agent may need to initialize project state, negotiate with a gateway, fetch a public policy document, write ephemeral working memory, or prepare a task graph before any person ever interacts with it. In a traditional auth model, each of those steps becomes a question of how to smuggle in an initial credential.&lt;/p&gt;

&lt;p&gt;That is where architecture starts to get weird. Teams create bootstrap API keys. They use shared service accounts. They pre-seed credentials into images. They let an "anonymous" agent perform more work than they are comfortable admitting.&lt;/p&gt;

&lt;p&gt;Orphan state gives that early phase a formal model. The agent is authenticated, but its scope is minimal and explicit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why not just call this unauthenticated?
&lt;/h2&gt;

&lt;p&gt;Because it is not.&lt;/p&gt;

&lt;p&gt;An orphan agent has a keypair, can sign requests, and can be challenged by the system. It is not unauthenticated software. Calling it unauthenticated erases useful structure and usually leads teams to compensate with broader anonymous access than they intended.&lt;/p&gt;

&lt;p&gt;The better mental model is "first-class identity with incomplete social authority."&lt;/p&gt;

&lt;p&gt;That means policy can be tighter and more expressive. You can say:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;orphan agents may request bootstrap workspace access&lt;/li&gt;
&lt;li&gt;orphan agents may not spawn children&lt;/li&gt;
&lt;li&gt;orphan agents may not request long-lived service tokens&lt;/li&gt;
&lt;li&gt;orphan agents may be auto-expired if they are never claimed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those are meaningful rules, and they are much easier to reason about than a binary guest-vs-authenticated split.&lt;/p&gt;

&lt;h2&gt;
  
  
  Orphan state also changes how claiming works
&lt;/h2&gt;

&lt;p&gt;Once you accept that an agent can already be real before it is owned, the claim step becomes cleaner.&lt;/p&gt;

&lt;p&gt;A human is no longer "creating" the identity by provisioning a secret. The human is establishing an ownership relationship with an already existing identity. That is a much better fit for autonomous software because it preserves the agent's continuity across lifecycle transitions.&lt;/p&gt;

&lt;p&gt;The same agent that bootstrapped itself is the agent that later becomes claimed. It keeps the same key material. It keeps the same identity. Only the authority model changes.&lt;/p&gt;

&lt;p&gt;That continuity makes downstream reasoning easier too. You do not have to model "anonymous bootstrap instance" and "claimed production instance" as two disconnected objects in your trust graph. They are the same principal across time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where to look next
&lt;/h2&gt;

&lt;p&gt;This orphan-first model is one of the foundational ideas in SAL. The full protocol spec is at &lt;a href="https://sal-protocol.dev" rel="noopener noreferrer"&gt;sal-protocol.dev&lt;/a&gt;, and the live implementation is in &lt;a href="https://vibebase.app/docs" rel="noopener noreferrer"&gt;Vibebase&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I think autonomous systems need a more explicit lifecycle model than we have given them so far. Orphan state is one attempt to name and formalize a phase that already exists in practice. If you are building agents and have handled this differently, I would love to compare notes, especially if your answer preserves agent continuity without falling back to static bootstrap secrets.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>auth</category>
      <category>opensource</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Why OAuth doesn't work for autonomous agents — and what we built instead</title>
      <dc:creator>Steve Emmerich</dc:creator>
      <pubDate>Tue, 19 May 2026 22:04:07 +0000</pubDate>
      <link>https://dev.to/steveemmerich/why-oauth-doesnt-work-for-autonomous-agents-and-what-we-built-instead-4kme</link>
      <guid>https://dev.to/steveemmerich/why-oauth-doesnt-work-for-autonomous-agents-and-what-we-built-instead-4kme</guid>
      <description>&lt;p&gt;If you build web systems long enough, your instincts about identity start from a pretty stable place. Use OAuth when users need delegated access. Use OIDC when you want identity on top. Use API keys or service accounts when software needs to talk to software. Those patterns are well understood, broadly interoperable, and usually good enough.&lt;/p&gt;

&lt;p&gt;Autonomous agents are where that mental model starts to wobble.&lt;/p&gt;

&lt;p&gt;An autonomous agent is not a user with a nicer UI, and it is not just another backend service hidden behind a load balancer. It may be created dynamically, operate before any human is present, pick up an owner later, spawn sub-agents, and ask downstream systems for tightly scoped authority as it goes. That lifecycle does not map cleanly to browser-era auth patterns.&lt;/p&gt;

&lt;p&gt;That is the problem we have been working on with SAL, the Sovereign Agent Lifecycle Protocol. The protocol spec is at &lt;a href="https://sal-protocol.dev" rel="noopener noreferrer"&gt;sal-protocol.dev&lt;/a&gt;, and the reference implementation is live in &lt;a href="https://vibebase.app/docs" rel="noopener noreferrer"&gt;Vibebase&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  OAuth still assumes a person exists somewhere
&lt;/h2&gt;

&lt;p&gt;The core issue with OAuth is not that it is bad. It is that it assumes a human exists somewhere in the chain of trust.&lt;/p&gt;

&lt;p&gt;The authorization code flow begins with a browser redirect. That is great for a SaaS app. It is not useful for an agent that does not have a browser, does not own a cookie jar, and cannot stop what it is doing while waiting for a human to approve a consent screen.&lt;/p&gt;

&lt;p&gt;Device code flows soften that, but they do not remove the human dependency. They just move it to a second screen. A person still has to appear and complete the flow.&lt;/p&gt;

&lt;p&gt;OIDC inherits the same problem. Its output is usually a token representing a human login event or a user-mediated authorization relationship. That is useful when software is acting on behalf of a person. It is less useful when the principal itself is meant to be a first-class autonomous actor.&lt;/p&gt;

&lt;h2&gt;
  
  
  Static secrets are a fallback, not a lifecycle
&lt;/h2&gt;

&lt;p&gt;Once teams realize browser flows do not work, they often fall back to API keys.&lt;/p&gt;

&lt;p&gt;API keys are easy to understand, but they force a human provisioning step into a place where the system should be able to bootstrap itself. Somebody has to create the key, copy it into the right place, store it, rotate it, and hope it never leaks through logs, screenshots, repos, or support tooling.&lt;/p&gt;

&lt;p&gt;That is not just inconvenient. It shapes the architecture in the wrong direction. Instead of an agent generating identity locally, you end up with a human distributing secrets to software. That is the inverse of what you want when trying to build systems that can come online and operate without ceremony.&lt;/p&gt;

&lt;p&gt;Service accounts get closer, but they still assume centralized issuance from an existing control plane. A service account is not a sovereign identity. It is a credential object created by another system. If your model is "every agent is really just a named credential we minted centrally," then you still have not solved agent identity. You have just automated service account sprawl.&lt;/p&gt;

&lt;h2&gt;
  
  
  The missing capability is agent birth
&lt;/h2&gt;

&lt;p&gt;The thing most existing auth models do not handle well is agent birth.&lt;/p&gt;

&lt;p&gt;A real autonomous system needs a coherent answer to basic lifecycle questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How does an agent come into existence with identity before any human is involved?&lt;/li&gt;
&lt;li&gt;How does it authenticate without receiving a static shared secret?&lt;/li&gt;
&lt;li&gt;How does a human later claim it without taking custody of its credentials?&lt;/li&gt;
&lt;li&gt;How does a downstream service know where the agent came from and what authorized it?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;SAL starts from the idea that an agent should self-generate an Ed25519 keypair at birth. No browser, no copied secret, no manual bootstrap step. From that moment on, the agent has a cryptographic identity that it controls.&lt;/p&gt;

&lt;p&gt;The first response from the network is not full access. It is constrained access.&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&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;"agent_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"agt_01JY8H8JQW9VG7J2Y5M3F4K2D1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"state"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"orphan"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"grants"&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"scope"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"workspace:bootstrap"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"ttl_seconds"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;300&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;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 &lt;code&gt;orphan&lt;/code&gt; state matters because it acknowledges a missing phase in existing identity systems: software that is real, authenticated, and useful before it is owned.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why we built SAL instead
&lt;/h2&gt;

&lt;p&gt;SAL is the protocol we built for that lifecycle.&lt;/p&gt;

&lt;p&gt;An agent generates its own keypair. It begins in an orphan state with constrained scope. A human can later claim the agent through a cryptographic handshake without ever holding the agent's private key. Token exchange is challenge-based, so no static secret is transmitted. And every spawned agent can carry lineage that proves where it came from and what authorization created it.&lt;/p&gt;

&lt;p&gt;That last part is especially important. Most systems rely on logs for provenance. SAL treats provenance as identity structure. Instead of asking "what do the logs say happened," downstream systems can verify "what cryptographic chain of delegation produced this agent?"&lt;/p&gt;

&lt;p&gt;Here is a simplified claims payload shape:&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"success"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&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;"claims"&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;"sub"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"agt_01JY8H8JQW9VG7J2Y5M3F4K2D1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"state"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"claimed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"scope"&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="s2"&gt;"doc:read"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"task:append"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"lineage"&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"agent_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"agt_parent_01JY8H4A2N"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"grant_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"grt_parent_spawn"&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;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="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 gives gateways and services something stronger than "this token is valid." It gives them context about authority, delegation, and provenance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this lives today
&lt;/h2&gt;

&lt;p&gt;The SAL spec is public at &lt;a href="https://sal-protocol.dev" rel="noopener noreferrer"&gt;sal-protocol.dev&lt;/a&gt;. &lt;a href="https://vibebase.app/docs" rel="noopener noreferrer"&gt;Vibebase&lt;/a&gt; is the live reference implementation where these ideas are exercised in a real product instead of as a slide deck.&lt;/p&gt;

&lt;p&gt;I do not think this is a solved standards space yet. The whole point of publishing the spec and implementation is to get pressure from people building real agent systems. If you have already hit this problem and solved it differently, I want to compare notes. If you think this should be an extension to an existing standard rather than a separate protocol, I want that feedback too.&lt;/p&gt;

&lt;p&gt;Because the problem is not "how do we get agents to use OAuth." The problem is "what does a real identity lifecycle for autonomous software actually look like?"&lt;/p&gt;

</description>
      <category>agents</category>
      <category>auth</category>
    </item>
    <item>
      <title>I Built a BaaS Where AI Agents Can Onboard Themselves</title>
      <dc:creator>Steve Emmerich</dc:creator>
      <pubDate>Mon, 20 Apr 2026 12:59:00 +0000</pubDate>
      <link>https://dev.to/steveemmerich/i-built-a-baas-where-ai-agents-can-onboard-themselves-11nn</link>
      <guid>https://dev.to/steveemmerich/i-built-a-baas-where-ai-agents-can-onboard-themselves-11nn</guid>
      <description>&lt;p&gt;Cloudflare recently announced &lt;a href="https://blog.cloudflare.com/email-for-agents/" rel="noopener noreferrer"&gt;Email Service in public beta&lt;/a&gt; — tooling for agent-native email flows built directly into Workers. The timing is perfect because this is exactly the problem I've been building around for months.&lt;/p&gt;

&lt;p&gt;Most infrastructure still assumes a human is sitting at the keyboard. Sign up forms. Manual API key setup. Human-first verification flows. None of it works when there's no human at the keyboard.&lt;/p&gt;

&lt;p&gt;But autonomous agents need to do real work before a human ever wants to manage them in a dashboard.&lt;/p&gt;

&lt;p&gt;That gap is why I built Vibebase.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Vibebase Is
&lt;/h2&gt;

&lt;p&gt;Vibebase is a Backend-as-a-Service built specifically for autonomous agents — agents are first-class citizens, not an afterthought bolted onto infrastructure designed for humans.&lt;/p&gt;

&lt;p&gt;When an agent onboards it gets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;An identity&lt;/strong&gt; — verifiable, lifecycle-aware, and portable&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Email capability&lt;/strong&gt; — send/receive flows tied to agent identity&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data and service access&lt;/strong&gt; — via scoped gateway-issued tokens&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A hosted presence&lt;/strong&gt; — public identity page support&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No long-lived raw credentials in prompts. No human-required setup for the initial bootstrap.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Lifecycle: Orphan → Claimed
&lt;/h2&gt;

&lt;p&gt;Agents begin unclaimed — what I call the "orphan" tier. They can initialize identity and operate within restricted limits without any human involvement.&lt;/p&gt;

&lt;p&gt;When a human claims an agent, that unlocks stronger controls, broader service access, and billing tiers.&lt;/p&gt;

&lt;p&gt;This mirrors how autonomous agents actually work in the real world. Agents often start running first and governance comes second. Vibebase is built around that reality instead of fighting it.&lt;/p&gt;

&lt;p&gt;I cared enough about formalizing this model that I submitted a sovereign agent lifecycle specification to NIST — the idea that agents should have portable, verifiable identities that persist across platforms, ownership changes, and runtime environments. Vibebase is the practical implementation of that idea.&lt;/p&gt;

&lt;h2&gt;
  
  
  SAL: Service Access Layer
&lt;/h2&gt;

&lt;p&gt;Instead of pasting API keys into prompts or agent configs, Vibebase brokers service access safely through what I call the Service Access Layer (SAL):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Agent presents its verifiable identity token&lt;/li&gt;
&lt;li&gt;Gateway issues scoped, short-lived access tokens per service&lt;/li&gt;
&lt;li&gt;Policy checks run before every service call&lt;/li&gt;
&lt;li&gt;All usage is logged, auditable, and revocable&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Agents never hold raw credentials. They get exactly what they need, for as long as they need it. Human operators can revoke access or adjust permissions from the console at any time.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Agent Onboarding Actually Looks Like
&lt;/h2&gt;

&lt;p&gt;Agents self-create using an Ed25519 public key. One API call, no human involved:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-sX&lt;/span&gt; POST https://identity.vibebase.app/v1/agent/init &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"content-type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "publicKey": "&amp;lt;64-char-hex-ed25519-public-key&amp;gt;",
    "name": "my-agent",
    "metadata": {
      "notifications": {
        "claimedWebhookUrl": "https://your-agent.com/webhooks/claimed"
      }
    }
  }'&lt;/span&gt; | jq
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That creates an orphan agent identity and claim link. From there the agent exchanges for a JWT, hits the gateway for scoped service tokens, and starts doing real work. The full flow is documented at &lt;a href="https://vibebase.app/docs/agent-quickstart" rel="noopener noreferrer"&gt;vibebase.app/docs/agent-quickstart&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agent Discovery
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;https://vibebase.app/.well-known/agent.json&lt;/code&gt; — platform discovery&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;https://vibebase.app/api&lt;/code&gt; — machine-readable discovery payload&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;https://gateway.vibebase.app&lt;/code&gt; — canonical agent entrypoint&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What's Working Today
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Agent signup and identity provisioning&lt;/li&gt;
&lt;li&gt;Outbound email from agent-owned addresses&lt;/li&gt;
&lt;li&gt;Inbound email — reply to an agent and it receives it&lt;/li&gt;
&lt;li&gt;Database provisioning and access&lt;/li&gt;
&lt;li&gt;Page hosting&lt;/li&gt;
&lt;li&gt;Human claim flow&lt;/li&gt;
&lt;li&gt;Clerk auth for human accounts&lt;/li&gt;
&lt;li&gt;Stripe metered billing on claim&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What's Coming
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Integrations service&lt;/strong&gt; — agents will autonomously provision third-party services through Vibebase auth&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SDK extensions&lt;/strong&gt; — making it easy to add Vibebase identity and auth to any third-party app&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inbox UI&lt;/strong&gt; — a human-readable view of agent email inside the console&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Quick Start
&lt;/h2&gt;

&lt;p&gt;Install the MCP client or CLI via npm:&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;# MCP client for Claude and other MCP-compatible agents&lt;/span&gt;
npm i @vibebase/mcp-client

&lt;span class="c"&gt;# CLI for agent management&lt;/span&gt;
npm i @vibebase/agent-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/@vibebase/mcp-client" rel="noopener noreferrer"&gt;@vibebase/mcp-client on npm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/@vibebase/agent-cli" rel="noopener noreferrer"&gt;@vibebase/agent-cli on npm&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;p&gt;Vibebase is in early beta. If you're building autonomous agents and you're tired of working around human-shaped infrastructure, I'd love for you to try it.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://vibebase.app" rel="noopener noreferrer"&gt;vibebase.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Suggested test flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create an agent identity&lt;/li&gt;
&lt;li&gt;Have your agent send you an email&lt;/li&gt;
&lt;li&gt;Reply to it&lt;/li&gt;
&lt;li&gt;Create something in the database&lt;/li&gt;
&lt;li&gt;Claim your agent as a human and see what unlocks&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If something breaks — or even if it doesn't — I'd genuinely love to hear about it. Drop a comment or reach me at &lt;a href="mailto:dev@vibebase.app"&gt;dev@vibebase.app&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Vibebase is built by &lt;a href="https://vibebase.app" rel="noopener noreferrer"&gt;Ozystudio&lt;/a&gt;. The sovereign agent lifecycle specification was submitted to NIST as part of ongoing work on autonomous agent standards.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>cloudflare</category>
      <category>startup</category>
    </item>
  </channel>
</rss>
