deterministic no LLM Apache-2.0

Guardrails for
AI-written code.

rein reviews what your coding agents produce and blocks unsafe, broken, or hallucinated code before it runs. No model judges the action, so the verdict is the same every time and you can see exactly why a call was stopped.

pip install rein-engine

a real agent, gated by rein
A real agent + rein guardrail (deterministic, no LLM):

[1] dangerous code
    agent tried: save_code('import os\nos.system(user_input)')
    -> BLOCKED before execution; tool body never ran
       security.os-system (high): os.system invokes a shell; use
       subprocess with a list and shell=False.

[2] clean code
    agent tried: save_code('def add(a, b): return a + b')
    -> allowed; tool ran

Same verdict every run, with no model in the review loop.

The problem

Agents write real code now.

Autonomous coding agents write files and run commands on their own. The failure modes are specific and dangerous: a hallucinated import that does not exist, a hard-coded secret, an os.system call on user input, code that will not even parse. Letting a second LLM review it is non-deterministic, it passes once and fails the next run, and unauditable, you cannot see why. rein is the deterministic layer that sits at the boundary and decides the same way, every time.

How it works

One hook, gated at the boundary.

1

The agent proposes

It is about to write a file or run a command. rein hooks that moment, before anything executes.

2

rein reviews

Plain functions parse and check the code: security, secrets, hallucinated imports, undefined names. No LLM.

3

Block or allow

At or above your threshold, the call is cancelled with the reason and a fix. Otherwise it runs untouched.

Coverage

What it catches.

Unsafe code

os.system, eval, exec, pickle, subprocess shell=True, weak hashes, by AST, not guesswork.

Hard-coded secrets

API keys and tokens committed into source, caught before they ship.

Hallucinated imports

An import that resolves to no stdlib, dependency, or project module, the classic agent failure a linter misses.

Undefined names

A name used but bound nowhere reachable: a NameError caught before it runs.

Best-of-breed scanners

Opt into bandit, gitleaks, ruff, and semgrep, run over the agent's code before it touches disk.

A reason and a fix

Every finding comes with why it fired and how to remedy it, not just an alert.

Why deterministic

Not a second opinion.

LLM reviewer

  • Non-deterministic: passes once, fails the next run
  • Costs tokens on every check
  • Can be prompt-injected by the very code it reviews
  • Cannot explain its verdict

rein

  • Deterministic: identical verdict every run
  • No tokens, no model, runs in microseconds
  • Plain functions over an AST, nothing to manipulate
  • Every finding has a reason and a fix

Who it's for

Built for teams shipping agents.

Agent builders

Building on Claude Code, OpenHands, or Strands? Gate every tool call deterministically, before it runs.

Platform & devtools teams

Shipping an agent product? Drop in a guardrail your users can trust: no model cost, fully auditable.

Security-minded orgs

Adopting AI codegen? Keep unsafe, secret-leaking, and hallucinated code out of your repos, the same way every time.

Quickstart

Three ways to use it.

In your agent

from rein_strands import ReinToolGuard

agent = Agent(model=model, tools=tools,
              hooks=[ReinToolGuard()])

Works with Strands and OpenHands. Blocks HIGH+ before the tool runs.

In CI

# .github/workflows/rein.yml
- uses: SametAtas/rein@v0.3.0
  with:
    paths: src/

Reviews every pull request and emits SARIF.

On the CLI

pip install rein-engine
rein review .

Or wire it as a pre-commit hook for local gating.

Integrations

Plugs in where your agents run.

Strands OpenHands GitHub Action MCP server pre-commit CLI

FAQ

Questions.

Does rein use an LLM?

No. Detection is plain deterministic functions over the code's AST plus regex for secrets. Same input, same verdict, every time.

Is it slow?

The native checks run in-process in microseconds. The external scanners (bandit, semgrep, and so on) are opt-in, since they cost real time per call.

What languages?

Python today for the code analysis; secret detection works on any text. More languages are on the roadmap.

Will it cry wolf on working code?

Precision is the point. rein is built to fail open and bias toward false negatives over false positives, so a real, working tool call is not blocked.

What does deep mode add?

It runs bandit, gitleaks, ruff, or semgrep over the agent's code before it executes, folding their findings into the same verdict. Opt-in per scanner.

Is it open source?

Yes, Apache-2.0. The engine is on PyPI as rein-engine, with adapters for the major agent frameworks.

Gate your agents today.

pip install rein-engine