<?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.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>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>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>
    <item>
      <title>Sound Scape</title>
      <dc:creator>Steve Emmerich</dc:creator>
      <pubDate>Mon, 11 Nov 2024 05:59:13 +0000</pubDate>
      <link>https://dev.to/steveemmerich/sound-scape-hi1</link>
      <guid>https://dev.to/steveemmerich/sound-scape-hi1</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2z4vo3qo5i7pdiwiu4ta.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2z4vo3qo5i7pdiwiu4ta.png" alt="coverimage" width="709" height="187"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/pgai"&gt;Open Source AI Challenge with pgai and Ollama &lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I built a Chat bot that accepts and generates audio files and provides analysis about the sound files. It can also generate mashup of the audio files. &lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="//widdleai.com/soundscape"&gt;Sound Scape&lt;/a&gt;&lt;br&gt;
&lt;a href="https://dev.toWIP"&gt;github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuduz0hm1b6s3doopjxxl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuduz0hm1b6s3doopjxxl.png" alt="Main Screen" width="800" height="601"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzz43r6bte5r0e9bql2n6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzz43r6bte5r0e9bql2n6.png" alt="Audio Manager" width="800" height="603"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk70soy2dn2us3fqs6mzz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk70soy2dn2us3fqs6mzz.png" alt="Chat" width="800" height="604"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhno7psz65jdcp7dyz5ky.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhno7psz65jdcp7dyz5ky.png" alt="Generate" width="800" height="603"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq2jvbg459096x4m8c02c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq2jvbg459096x4m8c02c.png" alt="Mashup" width="800" height="604"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuyn5edd7eyp1j3ddf5ie.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuyn5edd7eyp1j3ddf5ie.png" alt="Audio Analysis" width="800" height="603"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Tools Used
&lt;/h2&gt;

&lt;p&gt;pgai Vectorizer is used for generating the embeddings for ollama. pgvectorscale is used to for the similarity checks.&lt;br&gt;
Ollama is used for chat, mashup generation, and analysis.&lt;br&gt;
Docker was used to host ollama, postgres, and the vectorizer worker&lt;/p&gt;

&lt;h2&gt;
  
  
  Technology Used:
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://nextjs.org" rel="noopener noreferrer"&gt;Next.js&lt;/a&gt;&lt;br&gt;
&lt;a href="https://ui.shadcn.com" rel="noopener noreferrer"&gt;Shadcn&lt;/a&gt;&lt;br&gt;
&lt;a href="https://js.langchain.com" rel="noopener noreferrer"&gt;Langchain&lt;/a&gt;&lt;br&gt;
&lt;a href="https://langchain-ai.github.io/langgraphjs/" rel="noopener noreferrer"&gt;Langgraph&lt;/a&gt;&lt;br&gt;
&lt;a href="https://docs.smith.langchain.com/" rel="noopener noreferrer"&gt;Langsmith&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.prisma.io/" rel="noopener noreferrer"&gt;Prisma&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Overall I found the tools to be very interesting and useful. being able to trigger the embedding generation as soon as records are entered into the Database is very useful. &lt;/p&gt;

&lt;p&gt;Prize Categories&lt;/p&gt;

&lt;p&gt;This submission qualifies for:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Open-source Models from Ollama
Vectorizer Vibe
All the Extensions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>devchallenge</category>
      <category>pgaichallenge</category>
      <category>database</category>
      <category>ai</category>
    </item>
    <item>
      <title>Remote workers, how do you handle at home distractions?</title>
      <dc:creator>Steve Emmerich</dc:creator>
      <pubDate>Fri, 21 Sep 2018 21:44:01 +0000</pubDate>
      <link>https://dev.to/steveemmerich/remote-workers-how-do-you-handle-at-home-distractions-oep</link>
      <guid>https://dev.to/steveemmerich/remote-workers-how-do-you-handle-at-home-distractions-oep</guid>
      <description>&lt;p&gt;I work remotely and juggle two kids (6mo, 3yr). I am basically a stay at home dad that moonlights as a tech lead. I am curious how others manage their remote work vs family life?&lt;/p&gt;

&lt;p&gt;To start things off I have two workstations one in my kitchen, and one in my office. My general day consists of many meetings; I mostly float between the two depending on what the noise level is like plus what the kids are doing. Trying to split my concentration between the two. (FYI not a good idea.)&lt;/p&gt;

&lt;p&gt;What about you?&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>remote</category>
    </item>
  </channel>
</rss>
