# langchain-send21: the agent creates crypto pay links, a human or your own wallet signs (no keys in the agent)

**URL:** <https://forum.langchain.com/t/langchain-send21-the-agent-creates-crypto-pay-links-a-human-or-your-own-wallet-signs-no-keys-in-the-agent/4871>\
**Category:** Talking Shop\
**Created:** [October 27, 2026, 3:53pm UTC](https://forum.langchain.com/t/langchain-send21-the-agent-creates-crypto-pay-links-a-human-or-your-own-wallet-signs-no-keys-in-the-agent/4871 "2026-10-27T15:53:02Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![send21](https://yyz1.discourse-cdn.com/flex007/user_avatar/forum.langchain.com/send21/32/3721_2.png) [@send21](https://forum.langchain.com/u/send21)\
**Post date:** [October 27, 2026, 3:53pm UTC](https://forum.langchain.com/t/langchain-send21-the-agent-creates-crypto-pay-links-a-human-or-your-own-wallet-signs-no-keys-in-the-agent/4871/1 "2026-10-27T15:53:02Z")

</div>

A few threads here (hard spending limits, “can your agent spend without permission”) come back to the same problem, so here is a small toolkit and the pattern behind it.

The split: the agent can prepare a payment, but it never holds keys or funds. It creates a pay link priced in fiat, the payer signs in their own wallet, and the agent tracks the status.

```
pip install langchain-send21
export SEND21_API_KEY=s21_... # scopes: drafts:write, drafts:read

from langchain.agents import create_agent
from langchain_send21 import PayOption, Send21Toolkit

tools = Send21Toolkit(receive_options=[
    PayOption(currency="Usdc", network="Solana", address="<your-solana-address>"),
    PayOption(currency="Btc", network="Mainnet", address="name@wallet.com", method="Lightning"),
]).get_tools()

agent = create_agent("openai:gpt-5-mini", tools=tools)
agent.invoke({"messages": [{"role": "user", "content": "Create a pay link for 40 EUR for order inv-1042."}]})

```

Two tools:

- send21\_create\_pay\_link(fiat\_amount, fiat\_currency, order\_id?, memo?, decline\_note?) returns the link, id, status and expiry.
- send21\_get\_pay\_link\_status(payment\_request\_id) returns Open / Completed / Cancelled / Expired.

Design choices that matter for the spending-limit question:

- Receiving addresses come from your code, never from the model. A prompt injection can’t redirect where money goes.
- The key’s scopes can create a link and read its status. They cannot move money, because nothing on the service side holds keys.
- Each call uses a fresh idempotency key. With an order\_id, a retry returns the open link instead of creating a second one.
- Unsupported currency/network pairs are refused before any API call (USDT only on Solana and Ethereum, for example).

If you already use MCP, langchain-mcp-adapters can load all 11 tools from the hosted MCP server directly.

This is not an official LangChain package. It’s MIT, and the source is in send21io/send21-examples on GitHub (integrations/langchain). Feedback on the tool schema is welcome, especially from anyone running human-approval flows in LangGraph.

Docs: [Crypto payments MCP server for AI agents | send21](https://send21.io/docs/mcp)

- send21 (we build it; questions to [info@send21.io](mailto:info@send21.io))
