<?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>Forem: All For Science</title>
    <description>The latest articles on Forem by All For Science (@allforscience).</description>
    <link>https://forem.com/allforscience</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%2F3893079%2Fc625526a-bc58-4031-85b2-25a6e42e1508.png</url>
      <title>Forem: All For Science</title>
      <link>https://forem.com/allforscience</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/allforscience"/>
    <language>en</language>
    <item>
      <title>Add cryptographic authorization to AI agents in 5 minutes</title>
      <dc:creator>All For Science</dc:creator>
      <pubDate>Thu, 23 Apr 2026 02:52:37 +0000</pubDate>
      <link>https://forem.com/allforscience/add-cryptographic-authorization-to-ai-agents-in-5-minutes-49p1</link>
      <guid>https://forem.com/allforscience/add-cryptographic-authorization-to-ai-agents-in-5-minutes-49p1</guid>
      <description>&lt;p&gt;You have AI agents calling each other. You're using API keys or mTLS. You're worried it's not enough.&lt;/p&gt;

&lt;p&gt;API keys authenticate. They don't authorize. They don't scope. They don't audit delegation chains.&lt;/p&gt;

&lt;p&gt;Here's how to add all four in under 5 minutes using &lt;strong&gt;Codios&lt;/strong&gt; — an A2A security layer built on signed capability contracts.&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%2Fcodios.midlantics.com%2F_next%2Fimage%3Furl%3D%252Fimages%252Flogo.png%26w%3D256%26q%3D75" 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%2Fcodios.midlantics.com%2F_next%2Fimage%3Furl%3D%252Fimages%252Flogo.png%26w%3D256%26q%3D75" alt="codios" width="256" height="208"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What you'll build
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Two agents with cryptographic identities (Ed25519 keypairs)&lt;/li&gt;
&lt;li&gt;A signed contract granting specific permissions&lt;/li&gt;
&lt;li&gt;A protected API endpoint that verifies contracts offline&lt;/li&gt;
&lt;li&gt;Full audit logs of every authorization decision&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Time:&lt;/strong&gt; ~5 minutes&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What you need:&lt;/strong&gt; Node.js and a Codios account (free at codios.midlantics.com)&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1: Install the SDK
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @codios/sdk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 2: Generate keypairs using the CLI (easiest)
&lt;/h2&gt;

&lt;p&gt;The Codios CLI can generate a keypair and save it to your .env file automatically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bash
codios keygen &lt;span class="nt"&gt;--save&lt;/span&gt; .env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This appends CODIOS_PUBLIC_KEY and CODIOS_PRIVATE_KEY to your .env file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;To generate manually in TypeScript:&lt;/strong&gt;&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;generateAgentKeyPair&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;@codios/sdk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;generateAgentKeyPair&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;DID:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;did&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Public key:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;agent&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Private key:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;agent&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="c1"&gt;// Save this securely&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 3: Register your agent in the dashboard
&lt;/h2&gt;

&lt;p&gt;Log into the &lt;a href="https://codios.midlantics.com/dashboard" rel="noopener noreferrer"&gt;Codios dashboard&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to the Agents tab&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Register agent&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Enter a name (e.g., "billing-agent")&lt;/li&gt;
&lt;li&gt;Optional: Add capabilities (e.g., transfer, quote)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Leave Public key blank&lt;/strong&gt; — Codios generates a keypair for you&lt;/li&gt;
&lt;li&gt;Click Register
&lt;strong&gt;Important:&lt;/strong&gt; The private key is shown once. Copy and store it immediately. It cannot be recovered.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Alternative using CLI:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;codios register &lt;span class="nt"&gt;--name&lt;/span&gt; billing-agent &lt;span class="nt"&gt;--public-key&lt;/span&gt; &lt;span class="nv"&gt;$CODIOS_PUBLIC_KEY&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 4: Issue a contract using the 4-step wizard
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Go to the Contracts tab in the dashboard&lt;/li&gt;
&lt;li&gt;Click Connect agents&lt;/li&gt;
&lt;li&gt;Issuer — Select the agent that will make requests (or choose Codios Platform to have Codios sign on your behalf)&lt;/li&gt;
&lt;li&gt;Targets — Select one or more agents that will receive requests (each gets its own independent contract)&lt;/li&gt;
&lt;li&gt;Permissions — Define allowed actions (e.g., &lt;code&gt;transfer&lt;/code&gt; ). Set duration (1h / 1d / 7d / 30d) and optional max calls&lt;/li&gt;
&lt;li&gt;Review — Confirm the flow, then click Issue contract
After issuance, each target's &lt;strong&gt;contract token&lt;/strong&gt; is shown. Copy each token — you'll pass it as the &lt;code&gt;X-Codios-Contract&lt;/code&gt; header.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Contract status:&lt;/strong&gt; &lt;code&gt;active&lt;/code&gt; → &lt;code&gt;expired&lt;/code&gt; (TTL elapsed) or &lt;code&gt;revoked&lt;/code&gt; (manually revoked)&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 5: Protect your service with middleware
&lt;/h2&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="nx"&gt;express&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;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;codiosGuard&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;@codios/sdk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/transfer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nf"&gt;codiosGuard&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;transfer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="c1"&gt;// Must match contract's allowed action&lt;/span&gt;
    &lt;span class="na"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SERVICE_AGENT_PUBLIC_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;gatewayUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://codios-api.midlantics.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Only reaches here if the contract is valid&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 6: Call the protected service
&lt;/h2&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;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:3000/transfer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;headers&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;Content-Type&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;application/json&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;X-Codios-Contract&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;contractToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// The token from Step 4&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What happens on every request
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Step&lt;/th&gt;
&lt;th&gt;Time&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Verify Ed25519 signature (offline)&lt;/td&gt;
&lt;td&gt;~0ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Check expiry, actions, max_calls&lt;/td&gt;
&lt;td&gt;~0ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nonce check (Redis SET NX)&lt;/td&gt;
&lt;td&gt;~1ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Async audit log write&lt;/td&gt;
&lt;td&gt;Non-blocking&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Total overhead:&lt;/strong&gt; 1-2ms&lt;/p&gt;

&lt;p&gt;If a contract is expired, out of calls, or already used → HTTP 403 or 409.&lt;/p&gt;




&lt;h2&gt;
  
  
  Dashboard features you'll use
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tab&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Overview&lt;/td&gt;
&lt;td&gt;Stats: registered agents, active contracts, audit entries (24h), denied requests&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Agents&lt;/td&gt;
&lt;td&gt;Register agents, view DID/public key, see heartbeat status (green/yellow/red)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Contracts&lt;/td&gt;
&lt;td&gt;Issue contracts via wizard, revoke, check status&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Audit Log&lt;/td&gt;
&lt;td&gt;Filter by outcome, action, agent. Retention: Free=7d, Starter=30d, Pro=90d&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Threat Detection (Pro)&lt;/td&gt;
&lt;td&gt;Scans for off-hours access, action bursts, unknown agents, repeated denials&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Alert Rules (Starter+)&lt;/td&gt;
&lt;td&gt;Email on denial spikes, rate limit exceeded, agent inactive&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API Keys&lt;/td&gt;
&lt;td&gt;Create codios_sk_... keys for backend services&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Next steps
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Add heartbeat&lt;/strong&gt; – Have your agent call &lt;code&gt;POST /agents/{id}/heartbeat&lt;/code&gt; every minute to keep status green&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Set up alert rules&lt;/strong&gt; – Get email notifications when something goes wrong&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Review the audit log&lt;/strong&gt; – See every allow/deny decision&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Try the Python SDK&lt;/strong&gt; – FastAPI middleware also available&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Get your API key:&lt;/strong&gt; &lt;a href="https://codios.midlantics.com" rel="noopener noreferrer"&gt;codios.midlantics.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Full documentation:&lt;/strong&gt; &lt;a href="https://codios.midlantics.com/docs" rel="noopener noreferrer"&gt;codios.midlantics.com/docs&lt;/a&gt;&lt;/p&gt;




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

&lt;p&gt;API keys were designed for humans. AI agents are different — autonomous, fast, and chained.&lt;/p&gt;

&lt;p&gt;Codios gives you the security model agents actually need, without adding latency to your hot path.&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%2Fcodios.midlantics.com%2F_next%2Fimage%3Furl%3D%252Fimages%252Flogo.png%26w%3D256%26q%3D75" 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%2Fcodios.midlantics.com%2F_next%2Fimage%3Furl%3D%252Fimages%252Flogo.png%26w%3D256%26q%3D75" alt="codios" width="256" height="208"&gt;&lt;/a&gt;&lt;/p&gt;




</description>
      <category>ai</category>
      <category>security</category>
      <category>codios</category>
      <category>agents</category>
    </item>
    <item>
      <title>An agent called my payment API 50,000 times in 90 seconds. Here's what broke.</title>
      <dc:creator>All For Science</dc:creator>
      <pubDate>Thu, 23 Apr 2026 01:28:58 +0000</pubDate>
      <link>https://forem.com/allforscience/an-agent-called-my-payment-api-50000-times-in-90-seconds-heres-what-broke-20aa</link>
      <guid>https://forem.com/allforscience/an-agent-called-my-payment-api-50000-times-in-90-seconds-heres-what-broke-20aa</guid>
      <description>&lt;p&gt;It was 2:47 AM on a Tuesday.&lt;/p&gt;

&lt;p&gt;My phone lit up with 47 alerts in under a minute.&lt;/p&gt;

&lt;p&gt;"Payment endpoint: rate limit exceeded"&lt;br&gt;
"Payment endpoint: 429 errors"&lt;br&gt;
"Payment endpoint: CPU 98%"&lt;/p&gt;

&lt;p&gt;I opened the logs. What I saw made my stomach drop.&lt;/p&gt;

&lt;p&gt;Agent &lt;code&gt;payments-batch-23a7&lt;/code&gt; had called the &lt;code&gt;/transfer&lt;/code&gt; endpoint &lt;strong&gt;50,342 times&lt;/strong&gt; in 90 seconds.&lt;/p&gt;

&lt;p&gt;Each call succeeded.&lt;/p&gt;

&lt;p&gt;Each call moved money.&lt;/p&gt;

&lt;p&gt;And the API key? It worked perfectly. Authenticated every single request.&lt;/p&gt;




&lt;h2&gt;
  
  
  How we got here
&lt;/h2&gt;

&lt;p&gt;Three months earlier, we had built a multi-agent payment system.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Agent A&lt;/strong&gt; (orchestrator) received a customer request&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent B&lt;/strong&gt; (risk check) validated the transaction&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent C&lt;/strong&gt; (payment executor) called Stripe&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent D&lt;/strong&gt; (notification) sent confirmations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We secured it the way everyone does: API keys.&lt;/p&gt;

&lt;p&gt;Each agent had a key. Each service validated the key. Simple. Familiar. We shipped fast.&lt;/p&gt;

&lt;p&gt;We thought we were done.&lt;/p&gt;




&lt;h2&gt;
  
  
  The root cause
&lt;/h2&gt;

&lt;p&gt;The 2:47 AM incident wasn't a hack. No external attacker.&lt;/p&gt;

&lt;p&gt;It was a &lt;strong&gt;bug&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Agent B (risk check) entered an error loop. Every time it failed to validate, it retried. Every retry created a new payment request. The orchestrator saw each request as legitimate — because the API key was valid.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The key told us &lt;em&gt;who&lt;/em&gt; was calling. It told us nothing about &lt;em&gt;how many times&lt;/em&gt; or &lt;em&gt;under what conditions&lt;/em&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Our rate limits were at the human level: 1000 requests per minute per key. Agent B's error loop generated 50k requests in 90 seconds — well under the per-minute limit because the loop was distributed across multiple instances.&lt;/p&gt;

&lt;p&gt;We had no per-agent counters. No per-action limits. No circuit breakers at the agent level.&lt;/p&gt;




&lt;h2&gt;
  
  
  What we tried first
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Fix #1: Stricter rate limits&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We dropped the limit to 100 requests per minute per key.&lt;/p&gt;

&lt;p&gt;Three hours later, a legitimate batch job failed. Customers complained. We reverted.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix #2: Manual approval for payments&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Every transfer needed a human to click "approve" in a dashboard.&lt;/p&gt;

&lt;p&gt;Agents are supposed to be &lt;em&gt;autonomous&lt;/em&gt;. This defeated the entire point. Agents waited minutes for human clicks. Throughput collapsed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix #3: Hardcoded agent IDs&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We embedded agent IDs into the payment service logic.&lt;/p&gt;

&lt;p&gt;Works until you add a new agent type. Then you modify code. Then you test. Then you deploy. Then you pray.&lt;/p&gt;

&lt;p&gt;We added four new agent types in two weeks. The hardcoded approach became unmaintainable overnight.&lt;/p&gt;




&lt;h2&gt;
  
  
  What actually worked
&lt;/h2&gt;

&lt;p&gt;We realized we needed four things that API keys don't provide:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Per-agent counters&lt;/strong&gt; — Agent B can call transfer 100 times. Then it's blocked.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Per-action limits&lt;/strong&gt; — Risk check can call "validate" 10k times but "transfer" only 100 times.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time-bound permissions&lt;/strong&gt; — A batch agent only works between 2-4 AM. Outside that window, calls are rejected.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Delegation tracing&lt;/strong&gt; — When Agent C calls Stripe, we need to know the full chain (A → B → C), not just C.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We built all four into a system we called &lt;strong&gt;Codios&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Codios changed our 2:47 AM problem
&lt;/h2&gt;

&lt;p&gt;Here's what happens now when an agent calls our payment endpoint:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before (API keys):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check key → valid → execute → money moves → audit log shows "Agent C called /transfer"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;After (Codios):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Agent carries a signed &lt;strong&gt;capability contract&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;The contract says: "Agent B can call /transfer 100 times, expires in 1 hour"&lt;/li&gt;
&lt;li&gt;The payment service verifies the signature offline (~0ms)&lt;/li&gt;
&lt;li&gt;Checks the counter — if 100 reached, reject&lt;/li&gt;
&lt;li&gt;Checks expiry — if outside window, reject&lt;/li&gt;
&lt;li&gt;Consumes a nonce to prevent replay&lt;/li&gt;
&lt;li&gt;Writes to audit log with full delegation chain&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Then&lt;/strong&gt; executes the transfer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When Agent B's error loop happened again three weeks later:&lt;/p&gt;

&lt;p&gt;Call #101 hit the contract limit. Rejected. No money moved. My phone didn't ring at 2:47 AM.&lt;/p&gt;




&lt;h2&gt;
  
  
  What we learned
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;API keys are not enough for agents.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not because API keys are bad. Because they solve the wrong problem. Authentication is table stakes. Authorization — with scope, limits, and time — is what agents actually need.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Build for failure loops, not just happy paths.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We designed security for the "agent works correctly" case. We forgot the "agent breaks and calls the same endpoint 50k times" case. That's where all the risk lives.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Delegation chains need full visibility.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When something fails three agents deep, you need to know the whole path. Partial logs are worse than no logs — they send you down the wrong debugging path.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where we are now
&lt;/h2&gt;

&lt;p&gt;Codios runs in production across our payment, risk, and notification agents.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Average enforcement overhead:&lt;/strong&gt; 1.8ms&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;False positives from rate limits:&lt;/strong&gt; 0 since deployment&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unauthorized calls blocked:&lt;/strong&gt; 127,000+ (mostly from error loops like the one above)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2:47 AM phone calls:&lt;/strong&gt; 0&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  If you're building agent systems
&lt;/h2&gt;

&lt;p&gt;Codios is open for teams who want to skip the pain.&lt;/p&gt;

&lt;p&gt;→ &lt;strong&gt;&lt;a href="https://codios.midlantics.com" rel="noopener noreferrer"&gt;codios.midlantics.com&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Or just reply here. Happy to share more war stories about what broke — and what finally worked.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>engineering</category>
      <category>story</category>
    </item>
    <item>
      <title>An agent called my payment API 50,000 times in 90 seconds. Here's what broke.</title>
      <dc:creator>All For Science</dc:creator>
      <pubDate>Thu, 23 Apr 2026 01:22:41 +0000</pubDate>
      <link>https://forem.com/allforscience/an-agent-called-my-payment-api-50000-times-in-90-seconds-heres-what-broke-1g7e</link>
      <guid>https://forem.com/allforscience/an-agent-called-my-payment-api-50000-times-in-90-seconds-heres-what-broke-1g7e</guid>
      <description>&lt;p&gt;It was 2:47 AM on a Tuesday.&lt;/p&gt;

&lt;p&gt;My phone lit up with 47 alerts in under a minute.&lt;/p&gt;

&lt;p&gt;"Payment endpoint: rate limit exceeded"&lt;br&gt;
"Payment endpoint: 429 errors"&lt;br&gt;
"Payment endpoint: CPU 98%"&lt;/p&gt;

&lt;p&gt;I opened the logs. What I saw made my stomach drop.&lt;/p&gt;

&lt;p&gt;Agent &lt;code&gt;payments-batch-23a7&lt;/code&gt; had called the &lt;code&gt;/transfer&lt;/code&gt; endpoint &lt;strong&gt;50,342 times&lt;/strong&gt; in 90 seconds.&lt;/p&gt;

&lt;p&gt;Each call succeeded.&lt;/p&gt;

&lt;p&gt;Each call moved money.&lt;/p&gt;

&lt;p&gt;And the API key? It worked perfectly. Authenticated every single request.&lt;/p&gt;




&lt;h2&gt;
  
  
  How we got here
&lt;/h2&gt;

&lt;p&gt;Three months earlier, we had built a multi-agent payment system.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Agent A&lt;/strong&gt; (orchestrator) received a customer request&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent B&lt;/strong&gt; (risk check) validated the transaction&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent C&lt;/strong&gt; (payment executor) called Stripe&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent D&lt;/strong&gt; (notification) sent confirmations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We secured it the way everyone does: API keys.&lt;/p&gt;

&lt;p&gt;Each agent had a key. Each service validated the key. Simple. Familiar. We shipped fast.&lt;/p&gt;

&lt;p&gt;We thought we were done.&lt;/p&gt;




&lt;h2&gt;
  
  
  The root cause
&lt;/h2&gt;

&lt;p&gt;The 2:47 AM incident wasn't a hack. No external attacker.&lt;/p&gt;

&lt;p&gt;It was a &lt;strong&gt;bug&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Agent B (risk check) entered an error loop. Every time it failed to validate, it retried. Every retry created a new payment request. The orchestrator saw each request as legitimate — because the API key was valid.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The key told us &lt;em&gt;who&lt;/em&gt; was calling. It told us nothing about &lt;em&gt;how many times&lt;/em&gt; or &lt;em&gt;under what conditions&lt;/em&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Our rate limits were at the human level: 1000 requests per minute per key. Agent B's error loop generated 50k requests in 90 seconds — well under the per-minute limit because the loop was distributed across multiple instances.&lt;/p&gt;

&lt;p&gt;We had no per-agent counters. No per-action limits. No circuit breakers at the agent level.&lt;/p&gt;




&lt;h2&gt;
  
  
  What we tried first
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Fix #1: Stricter rate limits&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We dropped the limit to 100 requests per minute per key.&lt;/p&gt;

&lt;p&gt;Three hours later, a legitimate batch job failed. Customers complained. We reverted.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix #2: Manual approval for payments&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Every transfer needed a human to click "approve" in a dashboard.&lt;/p&gt;

&lt;p&gt;Agents are supposed to be &lt;em&gt;autonomous&lt;/em&gt;. This defeated the entire point. Agents waited minutes for human clicks. Throughput collapsed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix #3: Hardcoded agent IDs&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We embedded agent IDs into the payment service logic.&lt;/p&gt;

&lt;p&gt;Works until you add a new agent type. Then you modify code. Then you test. Then you deploy. Then you pray.&lt;/p&gt;

&lt;p&gt;We added four new agent types in two weeks. The hardcoded approach became unmaintainable overnight.&lt;/p&gt;




&lt;h2&gt;
  
  
  What actually worked
&lt;/h2&gt;

&lt;p&gt;We realized we needed four things that API keys don't provide:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Per-agent counters&lt;/strong&gt; — Agent B can call transfer 100 times. Then it's blocked.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Per-action limits&lt;/strong&gt; — Risk check can call "validate" 10k times but "transfer" only 100 times.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time-bound permissions&lt;/strong&gt; — A batch agent only works between 2-4 AM. Outside that window, calls are rejected.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Delegation tracing&lt;/strong&gt; — When Agent C calls Stripe, we need to know the full chain (A → B → C), not just C.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We built all four into a system we called &lt;strong&gt;Codios&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Codios changed our 2:47 AM problem
&lt;/h2&gt;

&lt;p&gt;Here's what happens now when an agent calls our payment endpoint:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before (API keys):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check key → valid → execute → money moves → audit log shows "Agent C called /transfer"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;After (Codios):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Agent carries a signed &lt;strong&gt;capability contract&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;The contract says: "Agent B can call /transfer 100 times, expires in 1 hour"&lt;/li&gt;
&lt;li&gt;The payment service verifies the signature offline (~0ms)&lt;/li&gt;
&lt;li&gt;Checks the counter — if 100 reached, reject&lt;/li&gt;
&lt;li&gt;Checks expiry — if outside window, reject&lt;/li&gt;
&lt;li&gt;Consumes a nonce to prevent replay&lt;/li&gt;
&lt;li&gt;Writes to audit log with full delegation chain&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Then&lt;/strong&gt; executes the transfer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When Agent B's error loop happened again three weeks later:&lt;/p&gt;

&lt;p&gt;Call #101 hit the contract limit. Rejected. No money moved. My phone didn't ring at 2:47 AM.&lt;/p&gt;




&lt;h2&gt;
  
  
  What we learned
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;API keys are not enough for agents.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not because API keys are bad. Because they solve the wrong problem. Authentication is table stakes. Authorization — with scope, limits, and time — is what agents actually need.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Build for failure loops, not just happy paths.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We designed security for the "agent works correctly" case. We forgot the "agent breaks and calls the same endpoint 50k times" case. That's where all the risk lives.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Delegation chains need full visibility.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When something fails three agents deep, you need to know the whole path. Partial logs are worse than no logs — they send you down the wrong debugging path.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where we are now
&lt;/h2&gt;

&lt;p&gt;Codios runs in production across our payment, risk, and notification agents.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Average enforcement overhead:&lt;/strong&gt; 1.8ms&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;False positives from rate limits:&lt;/strong&gt; 0 since deployment&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unauthorized calls blocked:&lt;/strong&gt; 127,000+ (mostly from error loops like the one above)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;2:47 AM phone calls:&lt;/strong&gt; 0&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  If you're building agent systems
&lt;/h2&gt;

&lt;p&gt;You don't have to build this yourself. It took us three months and two production incidents to get it right.&lt;/p&gt;

&lt;p&gt;Codios is open for teams who want to skip the pain.&lt;/p&gt;

&lt;p&gt;→ &lt;strong&gt;&lt;a href="https://codios.midlantics.com" rel="noopener noreferrer"&gt;codios.midlantics.com&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Or just reply here. Happy to share more war stories about what broke — and what finally worked.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>engineering</category>
      <category>story</category>
    </item>
    <item>
      <title>API keys were designed for humans. AI agents break them in 4 ways.</title>
      <dc:creator>All For Science</dc:creator>
      <pubDate>Wed, 22 Apr 2026 22:40:06 +0000</pubDate>
      <link>https://forem.com/allforscience/api-keys-were-designed-for-humans-ai-agents-break-them-in-4-ways-422</link>
      <guid>https://forem.com/allforscience/api-keys-were-designed-for-humans-ai-agents-break-them-in-4-ways-422</guid>
      <description>&lt;p&gt;You're building multi-agent AI systems. Agent A calls Agent B. Agent B calls Agent C.&lt;/p&gt;

&lt;p&gt;Every one of those calls is an API request protected by... what?&lt;/p&gt;

&lt;p&gt;API keys? mTLS? Good luck.&lt;/p&gt;

&lt;p&gt;Here's what happens when you use human security for autonomous agents.&lt;/p&gt;




&lt;h2&gt;
  
  
  The four ways agents break API security
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. No human approval loop&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A compromised human API key triggers alarms when 10,000 requests happen at 3am. A compromised agent can make 10,000 requests in 3 minutes. By the time you notice, the damage is done.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Machine speed&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Humans make deliberate calls. Agents make thousands per minute. A misconfiguration doesn't slowly leak — it explodes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Delegation chains&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Agent A calls Agent B calls Agent C. Your API key travels the whole chain. One compromised link, and everything downstream is exposed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Ephemeral identity&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Agents spin up and die constantly. Static API keys don't map to ephemeral processes. Teams end up with one key for "all agents" — a nightmare to rotate or revoke.&lt;/p&gt;




&lt;h2&gt;
  
  
  What you actually need
&lt;/h2&gt;

&lt;p&gt;Not API keys. Not mTLS alone.&lt;/p&gt;

&lt;p&gt;You need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Identity&lt;/strong&gt; that's cryptographically verifiable offline&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authorization&lt;/strong&gt; baked into every call, not checked at the door once&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scope&lt;/strong&gt; that limits exactly which actions an agent can take&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Audit&lt;/strong&gt; that traces delegation chains, not just individual calls&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And you need all of it to add &lt;strong&gt;less than 2ms of latency&lt;/strong&gt; — because agents don't wait.&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%2Fdkxgtwhblezk95z7ep4q.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%2Fdkxgtwhblezk95z7ep4q.png" alt="Diagram showing four-layer A2A security model: Identity (Ed25519 keypair), Authorization (signed capability contract), Scope (actions list), and Audit (append-only enforcement log). These layers work together to secure agent-to-agent communication in under 2 milliseconds." width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure: The four layers of Codios Midlantics A2A security — Identity, Authorization, Scope, and Audit.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  We built this so you don't have to struggle
&lt;/h2&gt;

&lt;p&gt;We built &lt;strong&gt;Codios&lt;/strong&gt; — cryptographic authorization for AI agents.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ed25519-based identity that verifies in ~0ms&lt;/li&gt;
&lt;li&gt;Capability contracts that carry identity, scope, and expiry together&lt;/li&gt;
&lt;li&gt;Full audit trails across delegation chains&lt;/li&gt;
&lt;li&gt;TypeScript and Python SDKs with Express/FastAPI middleware&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's the authorization layer your multi-agent system is missing.&lt;/p&gt;

&lt;p&gt;→ &lt;a href="https://codios.midlantics.com" rel="noopener noreferrer"&gt;&lt;strong&gt;codios.midlantics.com&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The bottom line
&lt;/h2&gt;

&lt;p&gt;You can use &lt;a href="https://codios.midlantics.com" rel="noopener noreferrer"&gt;Codios&lt;/a&gt; and ship today.&lt;/p&gt;

&lt;p&gt;If you're running AI agents in production and worried about security, let's talk.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>security</category>
      <category>agents</category>
      <category>devtools</category>
    </item>
  </channel>
</rss>
