<?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: send21</title>
    <description>The latest articles on DEV Community by send21 (@send21).</description>
    <link>https://dev.to/send21</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%2F4110329%2Fb0b3815d-426c-4464-8642-58bb609c606d.png</url>
      <title>DEV Community: send21</title>
      <link>https://dev.to/send21</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/send21"/>
    <language>en</language>
    <item>
      <title>An agent creates a payment draft; a human signs</title>
      <dc:creator>send21</dc:creator>
      <pubDate>Sun, 06 Sep 2026 05:26:25 +0000</pubDate>
      <link>https://dev.to/send21/an-agent-creates-a-payment-draft-a-human-signs-2oe7</link>
      <guid>https://dev.to/send21/an-agent-creates-a-payment-draft-a-human-signs-2oe7</guid>
      <description>&lt;p&gt;If you are building an AI agent that needs to move money, you have a custody problem the moment the agent can sign.&lt;/p&gt;

&lt;p&gt;That is the quiet part of most "agent payments" demos. The agent can create an invoice. The agent can call an API. The agent can even assemble a transaction. Then someone asks the only question that matters:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where do the keys live?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If the answer is "in the agent," you did not build a payment agent. You built a hot wallet with a chat UI.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Agents are good at structured work: create a draft, attach a memo, lock a rate, wait for a webhook, book the order. They are terrible at being custodians.&lt;/p&gt;

&lt;p&gt;A model can be jailbroken. A tool loop can be tricked into calling the wrong endpoint. A compromised server can dump process memory. A "scoped assistant" that still holds a seed is not scoped at all — it is a custodian that also writes poetry.&lt;/p&gt;

&lt;p&gt;So the product question is not "can an agent pay?"&lt;/p&gt;

&lt;p&gt;The product question is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can an agent prepare a payment without ever being able to spend?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That single constraint changes the architecture. It also changes what you are allowed to claim in marketing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrong patterns (keys in the agent)
&lt;/h2&gt;

&lt;p&gt;A few patterns show up again and again.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Seed or private key in the agent runtime
&lt;/h3&gt;

&lt;p&gt;The agent "pays" by signing. It is convenient in a demo. It is catastrophic in production. Anyone who can prompt the model, call its tools, or exfiltrate the process can spend.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Hot wallet behind the agent with broad spend rights
&lt;/h3&gt;

&lt;p&gt;Same failure mode with an extra hop. The agent does not hold the key itself; it holds the ability to move funds. That is still custody by another name.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. "The agent pays by itself" as a feature
&lt;/h3&gt;

&lt;p&gt;Auto-debit sounds magical until you need an audit trail, a human review step, or a recovery story after a bad tool call. If the agent can broadcast, the blast radius is the balance.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Treating "non-custodial" as a promise
&lt;/h3&gt;

&lt;p&gt;Marketing that says "we never steal your funds" while the server can sign is a &lt;strong&gt;promise&lt;/strong&gt;. Structure would mean the server cannot sign — even when compromised, even when an engineer is wrong, even when an agent is clever.&lt;/p&gt;

&lt;p&gt;If your architecture needs the agent to hold keys, sign, or broadcast, you are not solving agent payments. You are moving a wallet into a less trustworthy process.&lt;/p&gt;

&lt;h2&gt;
  
  
  The right pattern: instructions only
&lt;/h2&gt;

&lt;p&gt;A cleaner split looks like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;An agent (or a human) creates a &lt;strong&gt;payment draft&lt;/strong&gt; — receiver address, amount (exact or fiat-pegged), network, memo.&lt;/li&gt;
&lt;li&gt;The sender's own wallet funds and signs.&lt;/li&gt;
&lt;li&gt;The sender's own node or wallet broadcasts.&lt;/li&gt;
&lt;li&gt;Your backend watches the chain and fires signed webhooks when the payment is seen and confirmed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In that model, software prepares &lt;strong&gt;instructions&lt;/strong&gt;. Wallets do the paying.&lt;/p&gt;

&lt;p&gt;That is what &lt;a href="https://send21.io" rel="noopener noreferrer"&gt;send21&lt;/a&gt; is built for.&lt;/p&gt;

&lt;p&gt;send21 creates clean, verifiable payment instructions for BTC, USDC, USDT, and EURC. Funds move from the sender's own wallet to the receiver.&lt;/p&gt;

&lt;p&gt;We never touch keys. We never touch coins.&lt;/p&gt;

&lt;p&gt;Non-custodial by structure, not by promise: no hot wallets, no private keys stored, no signing code in the product path. A full server compromise cannot move a single satoshi, because there is nothing to move with.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scoped API keys that cannot spend
&lt;/h2&gt;

&lt;p&gt;Agents talk to send21 over REST — the same surface a human uses in the UI. Everything a human does in the product, an agent can do with an API key. The difference is what that key is allowed to do.&lt;/p&gt;

&lt;p&gt;Grant only what the agent needs, for example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;drafts:write&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;drafts:read&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;webhooks:manage&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;No scope can ever move funds.&lt;/strong&gt; Nobody can. That is the point.&lt;/p&gt;

&lt;p&gt;So the agent can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;create a draft&lt;/li&gt;
&lt;li&gt;fetch a transaction template&lt;/li&gt;
&lt;li&gt;track status&lt;/li&gt;
&lt;li&gt;receive &lt;code&gt;draft.seen&lt;/code&gt; / &lt;code&gt;draft.confirmed&lt;/code&gt; webhooks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The agent cannot:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;sign&lt;/li&gt;
&lt;li&gt;broadcast&lt;/li&gt;
&lt;li&gt;empty a wallet&lt;/li&gt;
&lt;li&gt;"just send it"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The human — or the wallet / HSM that holds the keys — remains the only party that can authorize value transfer.&lt;/p&gt;

&lt;p&gt;A typical flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;agent → create draft → fetch tx template → fund &amp;amp; sign in own wallet → broadcast → webhook: draft.confirmed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Idempotent creation (retry-safe &lt;code&gt;Idempotency-Key&lt;/code&gt;), locked rates for fiat-priced drafts, and HMAC-SHA256 signed webhooks make that loop machine-readable without turning the agent into a custodian.&lt;/p&gt;

&lt;h2&gt;
  
  
  Payment drafts vs pay links
&lt;/h2&gt;

&lt;p&gt;Same non-custodial idea. Different wallet shape.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Payment drafts (Bitcoin multi-output / PSBT path)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Need a PSBT-capable wallet such as Bitcoin Core, Sparrow, or Electrum. The sender reviews every output — including any transparent platform fee output — then signs locally.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Checkout pay links / QR&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Single-transfer pay links with a standard QR (&lt;code&gt;bitcoin:&lt;/code&gt; / Solana / Ethereum URI). Any wallet that can scan a QR and send an exact amount works. Useful for shops and "any screen" checkouts — phone, tablet, kiosk — without a branded terminal in the middle.&lt;/p&gt;

&lt;p&gt;Either way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;instructions first&lt;/li&gt;
&lt;li&gt;signature in the user's wallet&lt;/li&gt;
&lt;li&gt;confirmation on-chain&lt;/li&gt;
&lt;li&gt;webhook to book the order&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Agents that prepare &lt;strong&gt;drafts&lt;/strong&gt; stay on the draft API with spend-impossible scopes. Shop and stall checkouts use &lt;strong&gt;payment requests / pay links / QR&lt;/strong&gt;. Do not collapse those into "the agent paid."&lt;/p&gt;

&lt;h2&gt;
  
  
  When send21 fits
&lt;/h2&gt;

&lt;p&gt;send21 fits when you want:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Agents that prepare payments without spending rights&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Humans in the loop&lt;/strong&gt; for signing and broadcast&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fiat-priced drafts or pay links&lt;/strong&gt; with a locked rate, paid in BTC / USDC / USDT / EURC&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Direct wallet-to-wallet settlement&lt;/strong&gt; with no platform custody&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Webhook-first reconciliation&lt;/strong&gt; for shops, agents, and backends&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is less of a fit when you need a full self-hosted store stack, Lightning as a processor product, fiat payout rails, or an agent that auto-debits without a human signature. Those are different problems — and some of them already have strong tools. Use those tools when they fit. send21 is for the slice where the agent must prepare money movement without ever being able to do it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The short version
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;An agent creates a payment draft. A human signs.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That is how you get automation without handing the keys to the model.&lt;/p&gt;

&lt;p&gt;Direct. Non-custodial. Yours.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://send21.io" rel="noopener noreferrer"&gt;https://send21.io&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>bitcoin</category>
    </item>
  </channel>
</rss>
