How to Integrate LangChain for retail banking with Stripe for multi-agent systems
Combining LangChain for retail banking with Stripe gives you a clean way to build agentic banking workflows that can reason over customer context and then execute payment actions. In practice, that means an assistant can answer billing questions, trigger payment links, reconcile transactions, or route a refund request to the right agent without turning your app into a pile of brittle if/else logic.
Prerequisites
- •Python 3.10+
- •A Stripe account with:
- •
STRIPE_SECRET_KEY - •test mode enabled
- •
- •A LangChain-based retail banking stack, typically:
- •
langchain - •
langchain-openaior your model provider - •your retail-banking domain tools/prompts
- •
- •An API key for your LLM provider
- •A webhook endpoint if you want asynchronous payment confirmation
- •Basic familiarity with:
- •
langchain_core.tools.tool - •Stripe Python SDK methods like
stripe.PaymentIntent.create(),stripe.checkout.Session.create(), andstripe.Refund.create()
- •
Install the packages:
pip install langchain langchain-openai stripe python-dotenv
Integration Steps
1) Configure Stripe and your LangChain runtime
Keep secrets in environment variables. In banking systems, never hardcode keys in agent code.
import os
from dotenv import load_dotenv
import stripe
load_dotenv()
stripe.api_key = os.environ["STRIPE_SECRET_KEY"]
# Example LangChain setup
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
At this point you have two separate concerns wired up:
- •LangChain handles reasoning and tool selection.
- •Stripe handles money movement and payment objects.
2) Wrap Stripe actions as LangChain tools
Expose only the exact Stripe operations the agent needs. For retail banking, keep tools narrow: create a payment link, fetch payment status, issue a refund.
import stripe
from langchain_core.tools import tool
@tool
def create_payment_link(amount_cents: int, currency: str = "usd", customer_email: str = "") -> str:
"""Create a Stripe Checkout Session for a customer payment."""
session = stripe.checkout.Session.create(
mode="payment",
line_items=[{
"price_data": {
"currency": currency,
"product_data": {"name": "Retail Banking Payment"},
"unit_amount": amount_cents,
},
"quantity": 1,
}],
customer_email=customer_email or None,
success_url="https://example.com/success?session_id={CHECKOUT_SESSION_ID}",
cancel_url="https://example.com/cancel",
)
return session.url
@tool
def refund_payment(payment_intent_id: str, amount_cents: int | None = None) -> str:
"""Refund a successful Stripe PaymentIntent."""
kwargs = {"payment_intent": payment_intent_id}
if amount_cents is not None:
kwargs["amount"] = amount_cents
refund = stripe.Refund.create(**kwargs)
return refund.id
This pattern matters because the agent never gets raw access to your entire Stripe account surface area. It only gets the operations you explicitly expose.
3) Build the agent that routes banking intent to payment execution
Use LangChain’s tool-calling flow so the model can decide when to call Stripe. In a multi-agent system, this agent can be the “payments executor” while another agent handles customer support or compliance review.
from langchain_core.messages import HumanMessage
from langchain.agents import create_tool_calling_agent, AgentExecutor
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
tools = [create_payment_link, refund_payment]
prompt = ChatPromptTemplate.from_messages([
("system", "You are a retail banking payments assistant. Use tools for any payment action."),
("human", "{input}"),
MessagesPlaceholder(variable_name="agent_scratchpad"),
])
agent = create_tool_calling_agent(llm, tools, prompt)
executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
result = executor.invoke({
"input": "Create a $125 monthly loan repayment link for customer jane.doe@example.com"
})
print(result["output"])
For production multi-agent setups:
- •keep one agent focused on intent classification,
- •one agent on policy/compliance,
- •one agent on payments execution.
That separation reduces accidental refunds and prevents the LLM from mixing policy reasoning with money movement.
4) Add transaction verification before acting on refunds
Retail banking flows need guardrails. Before issuing a refund, query Stripe for status and require explicit approval from your orchestration layer.
@tool
def get_payment_status(payment_intent_id: str) -> str:
"""Fetch the current status of a PaymentIntent."""
pi = stripe.PaymentIntent.retrieve(payment_intent_id)
return f"{pi.id}:{pi.status}:{pi.amount_received}"
payment_intent_id = "pi_123456789"
status = get_payment_status.invoke({"payment_intent_id": payment_intent_id})
print(status)
A common pattern is:
- •Agent A identifies a refund request.
- •Agent B verifies policy eligibility.
- •Tool call only happens after both checks pass.
That keeps your system auditable.
5) Wire webhook events back into your LangChain workflow
Stripe webhooks are how you confirm asynchronous events like successful payments or failed charges. Feed those events into your orchestration layer so downstream agents can update case state or notify customers.
from flask import Flask, request, abort
app = Flask(__name__)
endpoint_secret = os.environ["STRIPE_WEBHOOK_SECRET"]
@app.route("/webhook/stripe", methods=["POST"])
def stripe_webhook():
payload = request.data
sig_header = request.headers.get("Stripe-Signature")
try:
event = stripe.Webhook.construct_event(payload, sig_header, endpoint_secret)
except Exception:
abort(400)
if event["type"] == "checkout.session.completed":
session = event["data"]["object"]
# Send this into your LangChain orchestration layer here.
print(f"Payment completed for session {session['id']}")
return "", 200
In a multi-agent bank workflow, this webhook can trigger:
- •receipt generation,
- •balance updates,
- •case closure,
- •fraud-review escalation if needed.
Testing the Integration
Run a simple end-to-end check by creating a test Checkout Session and confirming the URL is returned.
if __name__ == "__main__":
url = create_payment_link.invoke({
"amount_cents": 2500,
"currency": "usd",
"customer_email": "test.customer@example.com"
})
print(url)
Expected output:
https://checkout.stripe.com/c/pay/cs_test_...
If you want to verify the agent path instead of the raw tool call:
response = executor.invoke({
"input": "Generate a payment link for $25 USD for test.customer@example.com"
})
print(response["output"])
Expected output:
Here is your payment link: https://checkout.stripe.com/c/pay/cs_test_...
Real-World Use Cases
- •
Loan repayment assistant
- •One agent explains repayment options.
- •Another creates Stripe Checkout links for partial or full payments.
- •Webhooks update loan servicing state after completion.
- •
Dispute and refund workflow
- •Support agent collects customer complaint details.
- •Policy agent checks eligibility.
- •Payments agent calls
stripe.Refund.create()only after approval.
- •
Collections automation
- •Agent detects missed payments.
- •Generates reminder messages and secure pay-now links.
- •Escalates repeated failures to human ops with full transaction context.
Keep learning
- •The complete AI Agents Roadmap — my full 8-step breakdown
- •Free: The AI Agent Starter Kit — PDF checklist + starter code
- •Work with me — I build AI for banks and insurance companies
By Cyprian Aarons, AI Consultant at Topiax.
Want the complete 8-step roadmap?
Grab the free AI Agent Starter Kit — architecture templates, compliance checklists, and a 7-email deep-dive course.
Get the Starter Kit