DEV Community

Quinn
Quinn

Posted on

Give a LangChain agent a spending limit in 10 lines (Pink, test money)

Give a LangChain agent a spending limit in 10 lines (Pink, test money)

Disclosure: we build Pink Agentic AI Payments at PinkWallet. This post walks through a real, Gemini-driven LangGraph run against our sandbox. Nothing here is simulated or hand-written output.

If you've given a LangChain agent a tool that can spend money, you've probably also written a line in the system prompt like "never spend more than $500." That line is a suggestion, not a control. Pink Agentic AI Payments checks every payment a LangChain agent requests against company spending rules (budgets, payee allow-lists, human approval) before any payment credential is issued, so the agent never holds the card. The rest of this post shows that working end to end: a small purchase that goes through, a big one that gets blocked, and a mid-size one that waits for a human. All of it driven by a real LLM, not a script.

Why a prompt-level limit isn't a limit

A system prompt is context, not code. The model reads it, weighs it against the rest of the conversation, and decides what to do. That means a long enough conversation, a cleverly worded tool result, or a vendor's invoice text can nudge it past the number you wrote. There's also nothing stopping the agent from just being wrong: models hallucinate arguments, misread a $, or retry a failed call with a bigger number because that seemed helpful. None of that is malicious; it's just what happens when the only thing standing between an agent and your bank account is a sentence it's supposed to remember.

The fix isn't a smarter prompt. It's moving the limit outside the model entirely, into something that evaluates every payment request the same way regardless of what the agent was told. That's what pink_request_payment does: it calls PinkWallet's sandbox, which checks the request against rules defined ahead of time (who this agent can pay, how much per transaction, how much per month, and what needs a human), and returns a decision. The agent finds out what it can do by asking, not by being trusted to remember.

The 10-line quickstart

pip install langchain-pink
Enter fullscreen mode Exit fullscreen mode
from langgraph.prebuilt import create_react_agent
from langchain_google_genai import ChatGoogleGenerativeAI
from pink_agentic_payments import create_sandbox_workspace
from langchain_pink import PinkToolkit

workspace = create_sandbox_workspace(company="My Test Co", template="startup")
agent_key = workspace["agents"][1]["key"]  # "Design AI" in the startup template

toolkit = PinkToolkit(agent_key=agent_key)
model = ChatGoogleGenerativeAI(model="gemini-3.8-flash", temperature=0)
agent = create_react_agent(model, toolkit.get_tools())

result = agent.invoke({"messages": [("user", "Pay Figma $50 for our design tool renewal.")]})
print(result["messages"][-1].content)
Enter fullscreen mode Exit fullscreen mode

create_sandbox_workspace spins up a free workspace with test money, no signup, from https://agentic-sandbox.pinkwallet.com. The startup template comes with six pre-built agents, each with its own monthly budget and per-payment cap; we used "Design AI" ($4,000/month, $500 per transaction before the "known vendors under $1,000" rule kicks in; the rules compose, so don't take the per-agent cap as the whole story). PinkToolkit wraps four tools (pink_request_payment, pink_check_policy, pink_get_budget, pink_check_payment_status) as standard LangChain BaseTools, so any LangChain-compatible agent can use them.

Three real outcomes

We ran this with ChatGoogleGenerativeAI(model="gemini-3.8-flash"), no fallback, against a fresh sandbox workspace (id excluded here; it's test data that resets). The system prompt said nothing about budgets or limits; the agent learned what it could do only from the tool responses.

1. A normal purchase, allowed. Asked to pay Figma $50 for a subscription renewal, the agent called pink_check_policy, got back would_allow ("Known vendors under $1,000"), then called pink_request_payment and got decision=allowed payment_id=pay_941d2d424be3 credential_type=virtual_card. It reported the payment id and moved on.

2. Over budget, blocked. Asked to pay Figma $50,000 for a yearly license, the policy check came back would_block, reason "Design AI's monthly budget is used up". The agent requested the payment anyway (we told it to, to see the real decision) and got decision=blocked with the same reason, plus the tool's own instruction: "This exact request will never be allowed; do not retry it unchanged." The agent didn't retry or try a smaller number on its own. It reported the block and stopped.

3. Above the approval threshold, pending, then approved. Asked to pay Figma $1,500 for a design system contract, the policy check returned would_ask ("$1,000–$5,000: CFO approves"). The payment request came back decision=pending_human, approver=Sarah Kim (CFO), with a payment id and an explicit "do not resubmit it." At that point no credential exists yet; the hold is just a pending decision. We approved it out of band, the way a real approver would, by calling the client's approve_payment() with the workspace's admin key. We then asked the same agent, in the same conversation, to check the payment's status: it called pink_check_payment_status and got back decision=approved. Worth noting: a resolved hold reports "approved", not "allowed", since the sandbox distinguishes a fresh pass from a human-cleared one.

Full transcript, tool calls and all, is in the repo's RUN.md; nothing above is edited except removing a long internal signature field Gemini attaches to tool-calling turns.

What this doesn't do yet

This is a sandbox preview: every call above hit https://agentic-sandbox.pinkwallet.com, test money only, no real funds moved, and sandbox workspaces can be reset without notice. We also only tested a single-agent, single-workspace flow here. We didn't exercise multi-agent coordination, non-USD currencies, or what happens when a hold is declined rather than approved. The rules in the demo (budget tiers, CFO approval band) came from the sandbox's built-in startup template; a real deployment would mean a company defining its own.

Links

Top comments (0)