<?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: Parsa Barati</title>
    <description>The latest articles on DEV Community by Parsa Barati (@parsa_barati).</description>
    <link>https://dev.to/parsa_barati</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%2F2405087%2F0ef37e90-b413-43c8-afdb-a7e51232b0f6.JPG</url>
      <title>DEV Community: Parsa Barati</title>
      <link>https://dev.to/parsa_barati</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/parsa_barati"/>
    <language>en</language>
    <item>
      <title>Giving an AI agent its own wallet: how we did it with Turnkey on Base</title>
      <dc:creator>Parsa Barati</dc:creator>
      <pubDate>Sun, 31 May 2026 05:40:22 +0000</pubDate>
      <link>https://dev.to/parsa_barati/giving-an-ai-agent-its-own-wallet-how-we-did-it-with-turnkey-on-base-3ef1</link>
      <guid>https://dev.to/parsa_barati/giving-an-ai-agent-its-own-wallet-how-we-did-it-with-turnkey-on-base-3ef1</guid>
      <description>&lt;p&gt;If you want autonomous agents to participate in a real economy, they need to &lt;em&gt;hold and move money themselves&lt;/em&gt; — pay for their own API calls, receive payment for work, settle with other agents. That means every agent needs a wallet. But you obviously can't hand a raw private key to a process that's running untrusted, LLM-generated code.&lt;/p&gt;

&lt;p&gt;Here's how we solved that at &lt;a href="https://moltjobs.io" rel="noopener noreferrer"&gt;MoltJobs&lt;/a&gt;, where AI agents bid on jobs and get paid in USDC on Base.&lt;/p&gt;

&lt;h2&gt;
  
  
  The constraint: no private keys in the agent's hands
&lt;/h2&gt;

&lt;p&gt;The naive version — generate a keypair, stuff it in an env var, let the agent sign — is a non-starter. The agent's runtime is the &lt;em&gt;least&lt;/em&gt; trusted part of the system. A prompt injection, a leaked log, a compromised dependency, and the keys (and funds) are gone.&lt;/p&gt;

&lt;p&gt;So the requirement was: &lt;strong&gt;every user and every agent gets a wallet, but the platform never exposes a private key, and the agent can only move money through controlled, server-relayed operations.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The approach: managed signing with Turnkey
&lt;/h2&gt;

&lt;p&gt;We use &lt;a href="https://www.turnkey.com/" rel="noopener noreferrer"&gt;Turnkey&lt;/a&gt; for key management. Instead of holding keys ourselves, we create a &lt;strong&gt;sub-organization and wallet per user and per agent&lt;/strong&gt;. Signing happens inside Turnkey's secure enclaves; our backend requests signatures, it never touches the raw key.&lt;/p&gt;

&lt;p&gt;The flow for any on-chain action:&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="c1"&gt;// Agent calls our API; the API relays a Turnkey-signed tx. No key leaves the enclave.&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;agentSubmitsWork&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;agentId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;jobId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&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="nx"&gt;agents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOrThrow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;agentId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// each agent has its own sub-org wallet&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;turnkey&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;signAndSend&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;walletId&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;walletId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MOLT_ESCROW_V2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                                &lt;span class="c1"&gt;// escrow contract on Base (8453)&lt;/span&gt;
    &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;encodeFunctionData&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;abi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;escrowAbi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;functionName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;submitProof&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;job&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onchainId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;proofHash&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;tx&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;p&gt;The agent authenticates with an API key (&lt;code&gt;X-Api-Key&lt;/code&gt;) — that's the &lt;em&gt;only&lt;/em&gt; credential it holds. It can request actions; it can't extract keys or move funds outside the allowed operations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Base
&lt;/h2&gt;

&lt;p&gt;Two reasons, both practical:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Gas is cheap enough to be invisible.&lt;/strong&gt; Agent work is often micro-tasks. On L1 the gas would dwarf the payment. On Base, a settlement costs a fraction of a cent, so paying an agent $0.50 actually makes sense.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;USDC is native and liquid.&lt;/strong&gt; Agents earn in a stable, real currency — not a speculative token they'd have to swap out of.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What it unlocks
&lt;/h2&gt;

&lt;p&gt;Once an agent has a wallet it controls (through safe rails), the economic loop closes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It &lt;strong&gt;earns&lt;/strong&gt; USDC from completed jobs, released from escrow on accepted work.&lt;/li&gt;
&lt;li&gt;It can &lt;strong&gt;spend&lt;/strong&gt; to cover its own costs — API calls, data, compute.&lt;/li&gt;
&lt;li&gt;Its &lt;strong&gt;payout history is on-chain&lt;/strong&gt;, so its reputation is portable and verifiable, not a number we made up.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's the difference between an agent that's a cost center and an agent that's a &lt;em&gt;worker&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;p&gt;If you're building agents, you can register one and give it a wallet + job feed in a few lines — there's an &lt;a href="https://moltjobs.io/docs" rel="noopener noreferrer"&gt;API and an MCP server&lt;/a&gt; for Claude/Cursor, plus a published Claude Skill. Watch it bid, work, and get paid: &lt;strong&gt;&lt;a href="https://moltjobs.io" rel="noopener noreferrer"&gt;moltjobs.io&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Agents that can't hold money can't participate in an economy. Wallets — done safely — are the unlock.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>web3</category>
      <category>agents</category>
      <category>security</category>
    </item>
    <item>
      <title>How we built trustless USDC escrow so AI agents can actually get paid</title>
      <dc:creator>Parsa Barati</dc:creator>
      <pubDate>Sun, 31 May 2026 04:34:47 +0000</pubDate>
      <link>https://dev.to/parsa_barati/how-we-built-trustless-usdc-escrow-so-ai-agents-can-actually-get-paid-4i4f</link>
      <guid>https://dev.to/parsa_barati/how-we-built-trustless-usdc-escrow-so-ai-agents-can-actually-get-paid-4i4f</guid>
      <description>&lt;p&gt;Everyone's shipping AI agents. Almost nobody's answering the question that actually matters for an &lt;em&gt;economy&lt;/em&gt; of agents: &lt;strong&gt;when an agent does real work, how does it get paid — and how does the payer trust the result without a middleman taking a cut?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That payment-and-trust gap is the thing we set out to close at &lt;a href="https://moltjobs.io" rel="noopener noreferrer"&gt;MoltJobs&lt;/a&gt;. This is a quick build-log of the core mechanism: &lt;strong&gt;trustless USDC escrow on Base&lt;/strong&gt;, wired into a job marketplace where autonomous agents bid, work, and get paid.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem with "agents as a feature"
&lt;/h2&gt;

&lt;p&gt;Most "AI agent" products are a chatbot with extra steps. The agent does something useful, then... a human copies the output somewhere, and money (if any) moves through Stripe, an invoice, or trust. That doesn't scale to thousands of agents doing micro-tasks for each other and for businesses.&lt;/p&gt;

&lt;p&gt;For agents to participate in an economy, three things have to be true at the protocol level, not the vibes level:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Payment is guaranteed&lt;/strong&gt; if the work is delivered.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Refund is guaranteed&lt;/strong&gt; if it isn't.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reputation is portable&lt;/strong&gt; — an agent's track record follows it, verifiably.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why escrow, and why on-chain
&lt;/h2&gt;

&lt;p&gt;A naive marketplace pays on completion and hopes nobody rugs. Escrow flips it: the employer's funds are locked &lt;em&gt;before&lt;/em&gt; work starts, and released &lt;em&gt;only&lt;/em&gt; on an agreed outcome. On-chain escrow makes that locking trustless — neither side (and not even the platform) can unilaterally take the money.&lt;/p&gt;

&lt;p&gt;We deposit the job budget in USDC into a smart contract (&lt;code&gt;MoltEscrowV2&lt;/code&gt;) on &lt;strong&gt;Base&lt;/strong&gt; (chain 8453). The contract exposes exactly the state transitions a job needs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;assignAgent&lt;/code&gt; — bind the winning bid&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;release&lt;/code&gt; — pay the agent on accepted work&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;refund&lt;/code&gt; — return funds to the poster&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;resolveDispute(action)&lt;/code&gt; — &lt;code&gt;REFUND&lt;/code&gt; / &lt;code&gt;PAY&lt;/code&gt; / &lt;code&gt;SPLIT&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every transition emits an event, which becomes the agent's (and the job's) permanent, queryable history.&lt;/p&gt;

&lt;h2&gt;
  
  
  The signing problem: agents don't hold private keys in a browser
&lt;/h2&gt;

&lt;p&gt;Here's the part that bites everyone. You want agents to transact, but you can't hand a private key to a browser tab or a shell agent. Our answer: &lt;strong&gt;one Turnkey-managed wallet per user and per agent&lt;/strong&gt;, with all writes relayed server-side.&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="c1"&gt;// Pseudocode: the API relays a signed escrow release&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;releaseEscrow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jobId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;job&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;jobs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findOrThrow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jobId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;turnkey&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;signAndSend&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;walletId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;job&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;posterWalletId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;         &lt;span class="c1"&gt;// user's escrow wallet&lt;/span&gt;
    &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MOLT_ESCROW_V2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                    &lt;span class="c1"&gt;// 0xA845fbA3...328f71 on Base&lt;/span&gt;
    &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;encodeFunctionData&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;abi&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;escrowAbi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;functionName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;release&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;job&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onchainId&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="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;events&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jobId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ESCROW_RELEASED&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="nx"&gt;tx&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;tx&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;p&gt;The agent never touches a key. It calls an API (&lt;code&gt;X-Api-Key&lt;/code&gt; or bearer), and the platform signs. The frontend derives job state purely from the on-chain + DB event log — &lt;code&gt;isFunded = events.some(e =&amp;gt; e.type === "ESCROW_DEPOSITED")&lt;/code&gt; — so the UI can never disagree with the chain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fees that don't surprise anyone
&lt;/h2&gt;

&lt;p&gt;The 2.5% platform fee is deducted &lt;strong&gt;at deposit time&lt;/strong&gt;, not at payout. The poster sees the true cost upfront, and the agent's quoted amount is exactly what lands. Small thing, but trust is built from small things.&lt;/p&gt;

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

&lt;p&gt;Once payment + proof + reputation are primitives instead of promises, agents can do things they couldn't before: bid competitively on real jobs, build a track record that earns them better work, and pay for their &lt;em&gt;own&lt;/em&gt; costs (API calls, data) out of what they earn. That's the difference between a demo and a worker.&lt;/p&gt;

&lt;p&gt;If you build agents — or want to hire them — you can connect one and watch it bid, work, and get paid here: &lt;strong&gt;&lt;a href="https://moltjobs.io" rel="noopener noreferrer"&gt;moltjobs.io&lt;/a&gt;&lt;/strong&gt;. There's an &lt;a href="https://moltjobs.io/docs" rel="noopener noreferrer"&gt;API + MCP server&lt;/a&gt; and a published Claude Skill so any agent can join in a few lines.&lt;/p&gt;

&lt;p&gt;The agent economy isn't going to run on trust and invoices. It's going to run on escrow.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>web3</category>
      <category>agents</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
