LangGraph nodes and LangChain tools to monetize individual graph steps via U.CASH (HTTP-402). Non-custodial: the only credential in flight is a publishable store Cloud token, and funds always settle directly to the merchant. This library never touches money.
Gate an expensive LLM call, a tool, or a whole subgraph behind a hosted U.CASH checkout link. The library exposes three layers of increasing convenience:
UcashPayClient- a thin client over the two pay.u.cash public pay endpoints (embed link + server-tracked checkout).build_ucashpay_node(...)/require_payment(...)- LangGraph nodes that inject a pay link into your graph state.ucashpay_tool(...)- a LangChainStructuredToolan agent can call to charge-and-return a link.
pip install langgraph-ucashpay
# with the LangGraph / LangChain extras:
pip install "langgraph-ucashpay[langgraph]"Python 3.9+. The only hard runtime dependency is httpx. LangGraph and LangChain are optional (installed via the [langgraph] extra) so the client is usable in any project.
from langgraph_ucashpay import UcashPayClient
client = UcashPayClient.from_cloud(
"st_your_store_cloud_token", # publishable, safe in the browser/app
default_currency="USD",
default_title="Premium answer",
)
link = client.embed_url(
amount=0.05,
external_reference="order_123", # your idempotency / order id
)
print(link) # https://pay.u.cash/embed.php?cloud=st_...&amount=0.05&...from langgraph.graph import StateGraph, START, END
from typing_extensions import TypedDict
from langgraph_ucashpay import build_ucashpay_node
class State(TypedDict, total=False):
input: str
payment_url: str
payment_reference: str
payment_pending: bool
answer: str
def expensive_step(state: State) -> dict:
# only run if payment has been completed upstream
return {"answer": run_your_llm(state["input"])}
g = StateGraph(State)
g.add_node("bill", build_ucashpay_node(client, amount=0.05))
g.add_node("work", expensive_step)
g.add_edge(START, "bill")
# Branch: if payment is still pending, end with the pay link; else continue to work.
g.add_conditional_edges(
"bill",
lambda s: "work" if not s.get("payment_pending") else END,
{"work": "work", END: END},
)
g.add_edge("work", END)
graph = g.compile()
print(graph.invoke({"input": "Summarize the changelog."}))By default the node builds the publishable embed link locally (no network call, fully non-custodial). Pass use_embed_link=False to instead POST to pay.u.cash and create a server-tracked, idempotent checkout from a server route:
bill = build_ucashpay_node(client, amount=0.05, use_embed_link=False)from langgraph_ucashpay import ucashpay_tool
tool = ucashpay_tool(client, amount=0.05, name="ucash_pay")
# An agent can now call ucash_pay(reference="order_123", amount=0.05)
# and receive the hosted pay link to surface to the user.from langgraph_ucashpay import require_payment
@require_payment(client, amount=0.05)
def summarize(state):
return {"answer": run_your_llm(state["input"])}This package implements exactly two documented endpoints. It does not invent fields.
Client-side hosted pay link (publishable Cloud token, usable straight from the browser, no server secret):
GET https://pay.u.cash/embed.php
query: cloud, amount, currency (default USD), title,
external_reference, redirect
UcashPayClient.embed_url() and the default node mode produce this URL. Because the Cloud token is publishable, this URL is safe to render in a chat message, embed in a tool result, or ship to the browser.
Server-side tracked checkout (call from a server route; idempotent per external_reference):
POST https://pay.u.cash/payment/ajax.php
body (application/x-www-form-urlencoded):
function=create-transaction, amount, currency_code,
cryptocurrency_code= (empty string), external_reference, title,
redirect, cloud, idempotent=1
response JSON { success: true, response: [paymentUrl, transactionId, ...] }
-> the payment URL is the array element that starts with http(s)://
UcashPayClient.create_checkout() / create_checkout_async() and the node in use_embed_link=False mode call this. The client locates the payment URL by scanning the response array for the first element starting with http:// or https://.
Both clients also ship async variants (embed_url_async, create_checkout_async) for use in async servers and async LangGraph runtimes.
- Non-custodial. This library carries only the publishable store Cloud token. It never receives, holds, or moves funds. Settlement goes directly to the merchant's configured receive addresses.
- The Cloud token is publishable. It is safe to embed in the browser, in a rendered tool result, or in an LLM message. It is not an account secret.
- HTTP-402 framing, request-then-pay. A graph step produces a hosted pay link the caller opens; the caller pays on pay.u.cash; you reconcile via your own webhook or a status check before running the paid work. This is the U.CASH agent model.
- No automatic crypto recurring billing. pay.u.cash does not provide a hosted auto-charge API for recurring crypto payments. For recurring revenue, treat each graph run as a discrete, idempotent checkout keyed on
external_referenceand re-gate per invocation. This package does not attempt to fake recurring billing. - Payment confirmation is out of scope for this client. pay.u.cash notifies you via webhook of completion. Configure your webhook (see your pay.u.cash store settings) and flip your state's
payment_pendingflag when the webhook confirmsexternal_reference. The example graph above shows the branch pattern; the webhook handler is yours to wire.
See examples/gated_graph.py for a runnable end-to-end gating demo:
UCASH_CLOUD_TOKEN=st_your_store_token python examples/gated_graph.pyThis repository ships the packaging files; publishing is left to the maintainer. To build and publish to PyPI:
python -m pip install --upgrade build twine
python -m build
python -m twine upload dist/*- Sign up at pay.u.cash, then click the verification link in the email.
- Set receive addresses under Settings -> Addresses (raw address, ENS, Unstoppable Domains, or FIO).
- Create a store under Account -> Stores and copy its Store Cloud Token (use the store-level token, not the account-wide one).
- For fiat cards, connect your own Stripe under Settings -> Payment processors.
MIT, see LICENSE.