The boundary pattern
import os
from openai import OpenAI
from weckr import Weckr
openai_client = OpenAI()
wk = Weckr(api_key=os.environ["WECKR_API_KEY"], plans={"free": 0, "pro": 29})
# wherever your LangChain code ultimately makes the call, route it
# through wk.chat() with the user attached:
def tracked_llm_call(messages, user):
return wk.chat(openai_client, {
"model": "gpt-5.4-mini",
"messages": messages,
"user_id": user.id,
"feature": "research-chain",
"plan": user.plan,
})The full working setup for typical chain and agent architectures, including where this boundary naturally sits, is in the dedicated docs page: docs/integrations/langchain. The principle is the one constant: the framework orchestrates, but the provider call happens somewhere you control, and that somewhere is where attribution belongs.
Why chains make attribution more valuable, not less
- Steps multiply cost: a chain that reasons, retrieves, and summarizes is several round trips per user action, each resending context, the compounding described in the conversation math applied per step. Per call logging shows the true cost of the chain, not the last step.
- Agents are the runaway risk profile: a LangChain agent stuck re-planning is the canonical loop, and boundary wrapped calls feed velocity detection so the 2am loop pages you in minutes.
- Caps hold mid chain: the pre call check runs on every wrapped step, so a user over budget gets blocked or downgraded even inside a long chain, per the enforcement guide.
What you skip by not building the callback route
Callbacks hand you token counts; the distance from token counts to margin is the whole pipeline: current prices with cache rates (the cost methodology), the join to what each user pays, storage and rollups, and enforcement. That distance is exactly the build versus buy tail, and the boundary wrap is how you buy it in two lines.
FAQ
How do I track LangChain costs per user?
Wrap at the boundary: the place where your LangChain code ultimately calls the provider client. Instead of instrumenting LangChain’s callback system, pass the underlying OpenAI client through wk.chat() with your user_id, feature, and plan at the call site you control. Every chain round trip logs with cost recomputed server side and lands in one per user margin view.
Why wrap the client instead of using LangChain callbacks?
Callbacks report token usage but leave you the rest of the pipeline: joining usage to your users, pricing it correctly with cache rates, keeping prices current, and enforcement. Wrapping the boundary gives all of that from one integration point, and it is robust to LangChain’s internal changes since it touches only the client handoff you already own.
Do multi step chains and agents get attributed correctly?
Yes, that is the point of boundary wrapping: every round trip a chain or agent triggers goes through wk.chat(), so a five step chain logs five calls, each with the user and feature attached. Multi step LangChain agents are exactly where context compounds and costs multiply, which makes per call attribution more valuable there, not less.
Does this work with spending caps and loop detection?
Fully. The cap check runs before each wrapped call, so a user over budget gets blocked or downgraded mid chain like anywhere else, and velocity detection watches the same stream, an agent chain stuck in a loop is precisely the runaway pattern the 50,000 tokens in 5 minutes default catches.
Where is the full LangChain integration documented?
The docs have a dedicated LangChain integration page with the complete Python code, including where the boundary sits in typical chain and agent setups: useweckr.com/docs/integrations/langchain. The pattern is the same two lines as everywhere else, applied at the client handoff.
Keep reading
Your chains, priced per user, from one wrap
Full code in the LangChain integration docs, free for 50,000 requests a month, and the per user view your chains will fill is on the demo right now.