How to Integrate LangGraph for payments with LangSmith for RAG
If you’re building an agent that can answer questions from internal docs and also trigger payment flows, you need two things: a control plane for the money movement and a trace layer for the retrieval path. LangGraph gives you the stateful orchestration for payment steps, while LangSmith gives you visibility into the RAG side so you can debug retrieval quality, prompt behavior, and tool usage.
The useful pattern here is simple: use LangGraph to route and validate payment actions, and use LangSmith to instrument the retrieval chain that feeds those decisions. That gives you auditable payment execution plus traceable answer generation in one system.
Prerequisites
- •Python 3.10+
- •
langgraph - •
langchain - •
langsmith - •A vector store or retriever source for RAG
- •API keys configured:
- •
LANGSMITH_API_KEY - •
LANGSMITH_TRACING=true - •
OPENAI_API_KEYor another LLM provider key
- •
- •A payments backend or sandbox API you can call from a tool function
- •Basic familiarity with:
- •
StateGraphin LangGraph - •LangChain retrievers
- •LangSmith tracing
- •
Install the core packages:
pip install langgraph langchain langsmith langchain-openai
Integration Steps
- •
Set up LangSmith tracing for your RAG pipeline
Start by enabling tracing so every retrieval and generation step is visible in LangSmith. This is what lets you inspect which documents were retrieved before the agent decided whether a payment action was needed.
import os
os.environ["LANGSMITH_TRACING"] = "true"
os.environ["LANGSMITH_API_KEY"] = "lsv2_your_key_here"
os.environ["LANGCHAIN_PROJECT"] = "payments-rag-agent"
If you build your chain with LangChain components, traces will show up automatically once tracing is enabled.
- •
Build a retriever-backed RAG chain
Use a retriever to ground the agent in policy docs, invoice rules, or payment approval procedures. In production, this should be pointed at your internal knowledge base.
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.documents import Document
from langchain_core.vectorstores import InMemoryVectorStore
from langchain_openai import OpenAIEmbeddings
docs = [
Document(page_content="Payments above $10,000 require manager approval."),
Document(page_content="Refunds must reference an original transaction ID."),
]
vectorstore = InMemoryVectorStore.from_documents(docs, OpenAIEmbeddings())
retriever = vectorstore.as_retriever(search_kwargs={"k": 2})
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
prompt = ChatPromptTemplate.from_messages([
("system", "Answer using only the provided context."),
("human", "Question: {question}\n\nContext:\n{context}")
])
def format_docs(documents):
return "\n\n".join(d.page_content for d in documents)
def rag_answer(question: str) -> str:
retrieved_docs = retriever.invoke(question)
context = format_docs(retrieved_docs)
messages = prompt.format_messages(question=question, context=context)
return llm.invoke(messages).content
Once this runs under LangSmith tracing, you’ll see retriever calls and model outputs in the trace UI.
- •
Create a LangGraph workflow for payment decisions
Now model the payment flow as a graph. The graph should decide whether to approve, reject, or escalate based on retrieved policy context.
from typing import TypedDict, List
from langgraph.graph import StateGraph, END
class PaymentState(TypedDict):
question: str
context: str
decision: str
result: str
def retrieve_policy(state: PaymentState) -> PaymentState:
docs = retriever.invoke(state["question"])
state["context"] = format_docs(docs)
return state
def decide_payment(state: PaymentState) -> PaymentState:
prompt_text = f"""
You are a payments policy engine.
Question: {state['question']}
Context: {state['context']}
Return one of: approve, reject, escalate.
"""
decision = llm.invoke(prompt_text).content.strip().lower()
state["decision"] = decision
return state
def execute_payment(state: PaymentState) -> PaymentState:
if state["decision"] == "approve":
state["result"] = "Payment approved and queued for execution."
elif state["decision"] == "reject":
state["result"] = "Payment rejected due to policy."
else:
state["result"] = "Payment escalated for manual review."
return state
graph = StateGraph(PaymentState)
graph.add_node("retrieve_policy", retrieve_policy)
graph.add_node("decide_payment", decide_payment)
graph.add_node("execute_payment", execute_payment)
graph.set_entry_point("retrieve_policy")
graph.add_edge("retrieve_policy", "decide_payment")
graph.add_edge("decide_payment", "execute_payment")
graph.add_edge("execute_payment", END)
app = graph.compile()
This is the core integration point. LangGraph handles the branching and state transitions; LangSmith captures what happened inside each node if tracing is enabled.
- •
Connect RAG output to payment execution
Your agent should not send money just because an LLM said so. The safer pattern is to let RAG provide policy evidence, then use deterministic code for execution against your payment provider or internal ledger service.
def process_payment_request(question: str):
initial_state: PaymentState = {
"question": question,
"context": "",
"decision": "",
"result": ""
}
final_state = app.invoke(initial_state)
return {
"decision": final_state["decision"],
"result": final_state["result"],
"policy_context": final_state["context"],
}
response = process_payment_request(
"Can we approve a $12,500 vendor payment for invoice INV-1042?"
)
print(response)
In a real system, replace execute_payment() with a tool call to Stripe, Adyen, an ERP API, or your bank’s internal settlement service. Keep execution separate from reasoning.
- •
Add explicit LangSmith traces around custom logic
For custom functions outside standard LCEL chains, wrap them in spans so debugging stays clean. This matters when you need to inspect why a payment was escalated or why retrieval missed a policy doc.
from langsmith import traceable
@traceable(name="payment_request_handler")
def traced_process_payment_request(question: str):
initial_state: PaymentState = {
"question": question,
"context": "",
"decision": "",
"result": ""
}
final_state = app.invoke(initial_state)
return final_state
result = traced_process_payment_request(
"Approve refund for transaction TXN-8831?"
)
print(result["decision"], result["result"])
Testing the Integration
Run one request through the graph and verify that both retrieval and decisioning are visible in LangSmith.
test_question = "Approve a $15,000 supplier payout?"
outcome = process_payment_request(test_question)
print("Decision:", outcome["decision"])
print("Result:", outcome["result"])
print("Context:", outcome["policy_context"])
Expected output:
Decision: escalate
Result: Payment escalated for manual review.
Context: Payments above $10,000 require manager approval.
If tracing is configured correctly, you should also see:
- •A retriever span in LangSmith
- •A model invocation span for policy decisioning
- •A graph execution trace showing node order and final state
Real-World Use Cases
- •
Invoice approval agents
- •Retrieve approval thresholds from policy docs with RAG.
- •Use LangGraph to route low-risk invoices automatically and escalate exceptions.
- •
Refund assistants
- •Pull refund rules from support documentation.
- •Validate transaction IDs before calling refund APIs through a controlled graph step.
- •
Treasury operations copilots
- •Answer questions about disbursement policies.
- •Trigger secure payment workflows only after policy evidence is retrieved and logged.
The production pattern here is not “LLM decides payments.” It’s “RAG explains policy, LangGraph controls execution, and LangSmith proves what happened.” That’s the setup you want when money movement and auditability are both non-negotiable.
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