What you will build

A Python research agent that takes a question like "What were the Q1 2026 revenue figures for the top five Indian private banks and what did analysts say about them?", calls a mix of free and paid data APIs, and returns a structured answer with citations. When free sources suffice, it pays nothing. When premium sources are needed, the agent pays in USDC through a MoltPe wallet with strict daily and per-transaction caps.

The agent is a standard LangChain ReAct agent. The only unusual piece is that a few of its tools happen to cost money — and the payment handling is completely invisible to the agent's reasoning loop. It just gets JSON back.

Prerequisites

Step 1 — Create the research agent wallet

Mint a dedicated wallet for this agent. Give it a name that ties back to its purpose — your transaction history is a lot more readable when wallets are named after jobs.

curl -X POST https://api.moltpe.com/v1/agents/create \
  -H "Authorization: Bearer $MOLTPE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "market-research-agent", "network": "polygon" }'
{
  "agent_id": "ag_01JMTRE2K8X4PV7N9B3CQZDYEH",
  "wallet_address": "0xD7B0A1E8c5F6d9A3b2C7e0D4f8A1B5c9E2F4A6B8",
  "network": "polygon"
}

Fund it with a small starting amount, say 50 USDC, from your treasury. This is the total exposure for this agent — you cannot lose more than this even in a worst case.

Step 2 — Set budget guardrails

The spending policy is the safety net. MoltPe enforces it at signature time, so even a prompt injection or a broken loop cannot blow through it. Set conservative initial values; you can always raise them once you know the workload.

curl -X POST https://api.moltpe.com/v1/agents/ag_01JMTRE2K8X4PV7N9B3CQZDYEH/policy \
  -H "Authorization: Bearer $MOLTPE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "daily_cap": "10.00",
    "per_tx_cap": "1.00",
    "allowlist": [
      "0x9F1d3B5a7C9e1F3b5A7c9E1f3B5a7C9e1F3b5A7c",
      "0x2B5a7C9e1F3b5A7c9E1f3B5a7C9e1F3b5A7c9E1f"
    ]
  }'

The allowlist restricts payments to two approved data providers. Anything else gets rejected before it reaches the chain. This is the difference between a wallet and a trust boundary.

Step 3 — Wrap paid APIs as LangChain tools

Install the packages and build a tool per data source. The MoltPe Python SDK exposes an x402-aware HTTP client; you call it like requests but it transparently handles payment.

pip install langchain langchain-openai moltpe redis
# research_agent.py — LangChain agent with paid data tools behind a MoltPe wallet.
import os, hashlib, json
from langchain.agents import AgentExecutor, create_react_agent
from langchain_openai import ChatOpenAI
from langchain.tools import Tool
from langchain import hub
from moltpe import X402Client
import redis

AGENT_ID = "ag_01JMTRE2K8X4PV7N9B3CQZDYEH"
cache = redis.Redis(host="localhost", port=6379, decode_responses=True)

moltpe = X402Client(
    api_key=os.environ["MOLTPE_API_KEY"],
    agent_id=AGENT_ID,
    max_payment_usd="1.00",
)

def cached_paid_call(url: str, query: dict, ttl: int) -> dict:
    """Run a paid x402 call, but only if the cache misses."""
    key = f"paid:{hashlib.sha256(f'{url}:{json.dumps(query, sort_keys=True)}'.encode()).hexdigest()}"
    hit = cache.get(key)
    if hit:
        return json.loads(hit)
    resp = moltpe.post(url, json=query).json()
    cache.setex(key, ttl, json.dumps(resp))
    return resp

def market_data_tool(query: str) -> str:
    """Premium market data. 0.05 USDC per call, cached 60s."""
    data = cached_paid_call(
        "https://premiumdata.example.com/quotes",
        {"q": query},
        ttl=60,
    )
    return json.dumps(data)

def legal_db_tool(query: str) -> str:
    """Paid legal filings. 0.50 USDC per call, cached 24h."""
    data = cached_paid_call(
        "https://legaldb.example.com/search",
        {"q": query},
        ttl=86400,
    )
    return json.dumps(data)

Step 4 — Add caching and free fallbacks

The tool list should put free tools first. The agent picks them by default — LangChain tools are ordered — and only escalates to paid tools when free returns are empty or thin. In practice this drops cost by 60% or more on typical research runs.

import requests

def free_web_search(query: str) -> str:
    """Free web search — try this before paid sources."""
    resp = requests.get("https://api.duckduckgo.com/", params={"q": query, "format": "json"})
    return resp.text[:4000]

def budget_remaining() -> float:
    """Return daily cap minus today's spend, in USDC."""
    info = moltpe.get(f"https://api.moltpe.com/v1/agents/{AGENT_ID}/spend-today").json()
    return float(info["remaining"])

tools = [
    Tool(name="free_web_search", func=free_web_search, description="Free web search. Use FIRST."),
    Tool(name="market_data", func=market_data_tool, description="Premium market quotes. Costs 0.05 USDC."),
    Tool(name="legal_db", func=legal_db_tool, description="Legal filings DB. Costs 0.50 USDC. Use sparingly."),
]

llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
prompt = hub.pull("hwchase17/react")
agent = create_react_agent(llm, tools, prompt)
executor = AgentExecutor(agent=agent, tools=tools, verbose=True, max_iterations=8)

Step 5 — Run a research task

Before invoking, check budget. If the remaining cap is too low, short-circuit with a friendly message instead of letting the agent try and fail.

question = "Summarize Q1 2026 revenue for the top 5 Indian private banks with analyst commentary."

remaining = budget_remaining()
if remaining < 1.0:
    print(f"Budget too low (${remaining:.2f} left today). Try tomorrow.")
else:
    result = executor.invoke({"input": question})
    print(result["output"])

# Expected console output (trimmed):
# > free_web_search: Q1 2026 Indian bank results ...
# > market_data: { "HDFCBANK": {...}, "ICICIBANK": {...} }
# Final: HDFC Bank reported revenue of ...  ICICI Bank ...

Testing the agent

Run the agent twice with the same question. The first run pays for premium lookups; the second run should cost zero because the cache is warm. Confirm this by checking the MoltPe dashboard transactions panel or calling the API:

curl "https://api.moltpe.com/v1/transactions?agent_id=ag_01JMTRE2K8X4PV7N9B3CQZDYEH&since=today" \
  -H "Authorization: Bearer $MOLTPE_API_KEY"

You should see a handful of 0.05 and 0.50 USDC outgoing payments on run 1, and an empty or near-empty list on run 2. That is the caching doing its job. For deeper testing, deliberately trip the per-tx cap by setting it to 0.01 and running the agent — you should see the middleware reject the market-data call with POLICY_VIOLATION and the agent gracefully fall back to the free source.

Production checklist