惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

P
Proofpoint News Feed
Blog — PlanetScale
Blog — PlanetScale
GbyAI
GbyAI
C
Check Point Blog
腾讯CDC
Stack Overflow Blog
Stack Overflow Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
The GitHub Blog
The GitHub Blog
A
About on SuperTechFans
Recent Announcements
Recent Announcements
L
LangChain Blog
Microsoft Azure Blog
Microsoft Azure Blog
小众软件
小众软件
J
Java Code Geeks
博客园_首页
Jina AI
Jina AI
美团技术团队
H
Help Net Security
MyScale Blog
MyScale Blog
Engineering at Meta
Engineering at Meta
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
人人都是产品经理
人人都是产品经理
Y
Y Combinator Blog
S
SegmentFault 最新的问题

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
Building AI Agents That Interact With Blockchain: A Deep ...
Fahad Arif · 2026-06-22 · via DEV Community

Most tutorials on AI agents stop at chat interfaces and RAG pipelines. This one doesn't.
This guide walks through building a production-grade AI agent that can read on-chain data, interact with smart contracts, and execute DeFi operations — using LangChain's agent framework, ethers.js, and a set of custom tools you'll write from scratch.
By the end, you'll have an agent that can:

  • Query wallet balances and token holdings
  • Read state from any smart contract via ABI
  • Simulate and execute token swaps on a DEX
  • Monitor on-chain events and trigger actions autonomously Stack
  • LangChain (TypeScript) — agent framework
  • ethers.js v6 — blockchain interaction
  • OpenAI GPT-4o — LLM backbone
  • Alchemy — RPC provider
  • Hardhat — local fork for safe testing

1. Project Setup

mkdir ai-blockchain-agent && cd ai-blockchain-agent
npm init -y
npm install langchain @langchain/openai @langchain/core ethers dotenv
npm install -D typescript ts-node @types/node hardhat
npx tsc --init

.env:

OPENAI_API_KEY=your_openai_key
ALCHEMY_RPC_URL=https://eth-mainnet.g.alchemy.com/v2/your_key
PRIVATE_KEY=your_wallet_private_key

2. Initializing the Provider and Signer

// src/provider.ts
import { ethers } from "ethers";
import * as dotenv from "dotenv";
dotenv.config();

export const provider = new ethers.JsonRpcProvider(process.env.ALCHEMY_RPC_URL);

export const signer = new ethers.Wallet(
  process.env.PRIVATE_KEY!,
  provider
);

3. Building Custom Blockchain Tools

LangChain agents are only as powerful as their tools. Every on-chain operation becomes a tool the agent can call. Each tool needs a name, description (the LLM reads this to decide when to use it), and a func.

Tool 1 — Get ETH Balance

// src/tools/getBalance.ts
import { DynamicTool } from "@langchain/core/tools";
import { provider } from "../provider";
import { ethers } from "ethers";

export const getBalanceTool = new DynamicTool({
  name: "get_eth_balance",
  description:
    "Get the ETH balance of a wallet address. Input should be a valid Ethereum address.",
  func: async (address: string) => {
    try {
      const balance = await provider.getBalance(address);
      return `Balance: ${ethers.formatEther(balance)} ETH`;
    } catch (err) {
      return `Error fetching balance: ${err}`;
    }
  },
});

Tool 2 — Read ERC-20 Token Balance

// src/tools/getTokenBalance.ts
import { DynamicStructuredTool } from "@langchain/core/tools";
import { z } from "zod";
import { ethers } from "ethers";
import { provider } from "../provider";

const ERC20_ABI = [
  "function balanceOf(address owner) view returns (uint256)",
  "function decimals() view returns (uint8)",
  "function symbol() view returns (string)",
];

export const getTokenBalanceTool = new DynamicStructuredTool({
  name: "get_token_balance",
  description:
    "Get the ERC-20 token balance for a wallet. Provide the token contract address and wallet address.",
  schema: z.object({
    tokenAddress: z.string().describe("ERC-20 token contract address"),
    walletAddress: z.string().describe("Wallet address to check"),
  }),
  func: async ({ tokenAddress, walletAddress }) => {
    try {
      const contract = new ethers.Contract(tokenAddress, ERC20_ABI, provider);
      const [balance, decimals, symbol] = await Promise.all([
        contract.balanceOf(walletAddress),
        contract.decimals(),
        contract.symbol(),
      ]);
      const formatted = ethers.formatUnits(balance, decimals);
      return `${formatted} ${symbol}`;
    } catch (err) {
      return `Error: ${err}`;
    }
  },
});

Tool 3 — Read Arbitrary Contract State

This is where it gets powerful — the agent can query any contract if you give it an ABI.

// src/tools/readContract.ts
import { DynamicStructuredTool } from "@langchain/core/tools";
import { z } from "zod";
import { ethers } from "ethers";
import { provider } from "../provider";

export const readContractTool = new DynamicStructuredTool({
  name: "read_contract",
  description:
    "Call a read-only function on any smart contract. Provide the contract address, ABI as a JSON string, function name, and arguments array.",
  schema: z.object({
    contractAddress: z.string(),
    abi: z.string().describe("JSON string of the contract ABI"),
    functionName: z.string(),
    args: z.array(z.string()).default([]),
  }),
  func: async ({ contractAddress, abi, functionName, args }) => {
    try {
      const parsedAbi = JSON.parse(abi);
      const contract = new ethers.Contract(contractAddress, parsedAbi, provider);
      const result = await contract[functionName](...args);
      return `Result: ${result.toString()}`;
    } catch (err) {
      return `Error: ${err}`;
    }
  },
});

Tool 4 — Get Gas Price and Estimate

// src/tools/getGasPrice.ts
import { DynamicTool } from "@langchain/core/tools";
import { provider } from "../provider";
import { ethers } from "ethers";

export const getGasPriceTool = new DynamicTool({
  name: "get_gas_price",
  description: "Get the current gas price on Ethereum mainnet in Gwei.",
  func: async () => {
    try {
      const feeData = await provider.getFeeData();
      const gasPriceGwei = ethers.formatUnits(feeData.gasPrice!, "gwei");
      const maxFeeGwei = ethers.formatUnits(feeData.maxFeePerGas!, "gwei");
      return `Base gas price: ${parseFloat(gasPriceGwei).toFixed(2)} Gwei | Max fee: ${parseFloat(maxFeeGwei).toFixed(2)} Gwei`;
    } catch (err) {
      return `Error: ${err}`;
    }
  },
});

Tool 5 — Simulate a Uniswap V3 Swap (Quote Only)

// src/tools/getSwapQuote.ts
import { DynamicStructuredTool } from "@langchain/core/tools";
import { z } from "zod";
import { ethers } from "ethers";
import { provider } from "../provider";

// Uniswap V3 Quoter contract on mainnet
const QUOTER_ADDRESS = "0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6";
const QUOTER_ABI = [
  "function quoteExactInputSingle(address tokenIn, address tokenOut, uint24 fee, uint256 amountIn, uint160 sqrtPriceLimitX96) external returns (uint256 amountOut)",
];

export const getSwapQuoteTool = new DynamicStructuredTool({
  name: "get_swap_quote",
  description:
    "Get a Uniswap V3 swap quote. Returns how many tokens you'd receive for a given input amount.",
  schema: z.object({
    tokenIn: z.string().describe("Input token contract address"),
    tokenOut: z.string().describe("Output token contract address"),
    fee: z.number().describe("Pool fee tier: 500, 3000, or 10000"),
    amountIn: z.string().describe("Amount in (human-readable, e.g. '1.5')"),
    decimalsIn: z.number().default(18),
    decimalsOut: z.number().default(18),
  }),
  func: async ({ tokenIn, tokenOut, fee, amountIn, decimalsIn, decimalsOut }) => {
    try {
      const quoter = new ethers.Contract(QUOTER_ADDRESS, QUOTER_ABI, provider);
      const amountInWei = ethers.parseUnits(amountIn, decimalsIn);
      const amountOut = await quoter.quoteExactInputSingle.staticCall(
        tokenIn,
        tokenOut,
        fee,
        amountInWei,
        0
      );
      const formatted = ethers.formatUnits(amountOut, decimalsOut);
      return `You would receive approximately ${formatted} tokens for ${amountIn} input tokens.`;
    } catch (err) {
      return `Error getting quote: ${err}`;
    }
  },
});

4. Assembling the Agent

Now plug all tools into a LangChain agent with memory and a system prompt that defines its behavior.

// src/agent.ts
import { ChatOpenAI } from "@langchain/openai";
import { AgentExecutor, createOpenAIFunctionsAgent } from "langchain/agents";
import { ChatPromptTemplate, MessagesPlaceholder } from "@langchain/core/prompts";
import { BufferMemory } from "langchain/memory";

import { getBalanceTool } from "./tools/getBalance";
import { getTokenBalanceTool } from "./tools/getTokenBalance";
import { readContractTool } from "./tools/readContract";
import { getGasPriceTool } from "./tools/getGasPrice";
import { getSwapQuoteTool } from "./tools/getSwapQuote";

const tools = [
  getBalanceTool,
  getTokenBalanceTool,
  readContractTool,
  getGasPriceTool,
  getSwapQuoteTool,
];

const llm = new ChatOpenAI({
  modelName: "gpt-4o",
  temperature: 0,
  openAIApiKey: process.env.OPENAI_API_KEY,
});

const prompt = ChatPromptTemplate.fromMessages([
  [
    "system",
    `You are a DeFi-native AI agent with direct access to the Ethereum blockchain.
You can read wallet balances, token holdings, smart contract state, gas prices, and DEX swap quotes.
Always verify addresses before acting. When providing numbers, format them clearly with appropriate units.
Never guess on-chain data — always use your tools to fetch it.
If a user asks you to perform a transaction, confirm all parameters before proceeding.`,
  ],
  new MessagesPlaceholder("chat_history"),
  ["human", "{input}"],
  new MessagesPlaceholder("agent_scratchpad"),
]);

const memory = new BufferMemory({
  memoryKey: "chat_history",
  returnMessages: true,
});

export async function createBlockchainAgent() {
  const agent = await createOpenAIFunctionsAgent({ llm, tools, prompt });

  return new AgentExecutor({
    agent,
    tools,
    memory,
    verbose: true,
    maxIterations: 10,
  });
}

5. Running the Agent

// src/index.ts
import { createBlockchainAgent } from "./agent";
import * as dotenv from "dotenv";
dotenv.config();

async function main() {
  const agent = await createBlockchainAgent();

  const queries = [
    "What is the ETH balance of 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045?",
    "What's the current gas price on Ethereum?",
    "How much USDC would I get if I swap 1 ETH on Uniswap V3? USDC address is 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48, WETH is 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2, use the 500 fee tier.",
  ];

  for (const query of queries) {
    console.log(`\n🧠 Query: ${query}`);
    const result = await agent.invoke({ input: query });
    console.log(`✅ Response: ${result.output}`);
  }
}

main().catch(console.error);

Run it:
npx ts-node src/index.ts

6. Testing Safely With a Hardhat Mainnet Fork

Never test write operations on mainnet directly. Fork it locally:
npm install -D hardhat @nomicfoundation/hardhat-toolbox
npx hardhat node --fork https://eth-mainnet.g.alchemy.com/v2/your_key

Then in .env, point your ALCHEMY_RPC_URL to http://127.0.0.1:8545 for local testing. Your agent will interact with a real state snapshot without risking real funds.

7. Where to Take This Further

This agent is a foundation. Production extensions include:

  • Event listeners — watch for on-chain events (liquidations, large swaps) and trigger agent actions autonomously
  • Multi-agent architecture — one agent monitors, another executes, a third validates
  • Write operations — extend tools to sign and broadcast transactions (use Hardhat fork to test first)
  • Cross-chain support — swap the provider per chain; the agent architecture stays identical
  • On-chain memory — store agent state in a smart contract instead of in-memory buffer

Closing Thoughts

The gap between AI agents and blockchain infrastructure is closing fast. LangChain's tool abstraction makes it straightforward to expose any on-chain operation as a callable function — the agent handles reasoning, sequencing, and decision-making on top.
The architecture above is minimal by design. The real complexity in production systems isn't wiring the tools — it's designing safe execution boundaries, handling RPC failures gracefully, and making sure the agent can't be prompted into signing something it shouldn't.
Build the guardrails before you build the features.
I'm Fahad Arif — Blockchain Developer, Smart Contract Auditor, and DeFi Consultant. I build and secure production Web3 systems across EVM chains and Solana. More at my website.