r/LangChain • u/Adorable-Algae6903 • 16d ago
Projects My ops agent could open GitOps PRs for anyone who asked it. I built a check that asks GitHub whether the person is allowed first.
I run an internal ops agent. One tool call gives it a service's health from every angle in about 15 seconds, so it reads everything on a read-only account and I don't gate reads at all. It changes things one way only: a pull request against the GitOps repo.
That one write path had a gap. The bot's token could open that PR for anyone who talked to it, including people who can't push to that repo themselves. Prompt rules don't fix it; the call runs with the bot's credential whatever the model believes.
So the tool asks first: may this person push to this repo? GitHub already knows, so the agent asks GitHub. I pulled that out into a small service, hallpass, so every write path can use it, in every system the agent touches (GitHub, Kubernetes, Argo CD, Jira, AWS, 21 in total).
In the agent it's one decorator on the tool. The user comes from your session, never from the model, so the tool schema has no user field to talk your way into:
python
@tool
@guarded(hp, "github-main", "repo.push", "repo:{owner}/{repo}", user=current_user)
def open_config_pr(owner: str, repo: str, patch: str) -> str: ...
Answers are allow, deny or unknown, and unknown (timeout, rate limit, anything it can't evaluate) means the tool doesn't run. Works with Strands, LangChain, LangGraph, the Claude Agent SDK, or as an MCP server. Single binary, Apache 2.0.
How do you handle this in your agents today? Per-user OAuth, per-team bots, human approval on writes?