Keep humans holding the reins.
Reins is a tiny, dependency-free Python framework for building AI agents that propose, explain, and wait, instead of acting first and apologizing later. The agent does the legwork. A human makes every consequential call. And every decision the two of you make gets written to a ledger you own.
Technology should serve humans, not the other way around.
PROPOSED email_partner (risk: HIGH)
WHY We need the partner's blessing, but I shouldn't speak for them uninvited.
ARGS to = 'youth-center@example.org'
subject = 'Mural workshop, Jan dates?'
──────────────────────────────────────────────────────────────
[a]pprove [e]dit [r]eject [w]hy [q]uit >
Most "autonomous" agents are built to ask for forgiveness, not permission. They sprint ahead, take irreversible actions, and bury their reasoning in a black box. That's fine when the stakes are a typo. It's not fine when the agent is spending your money, emailing in your name, deleting your files, or speaking for your community.
Reins flips the default. Human judgment is a feature, not a fallback. The agent is genuinely useful, it drafts, plans, and handles the safe, reversible busywork on its own, but it physically cannot do anything that matters without a person looking up and saying yes, change this, or no.
The whole thing is ~400 lines of standard-library Python. You can read it in one sitting. That's on purpose: if you can't see how your agent makes decisions, you don't really own it.
Every Reins agent does the same four things for every step it wants to take:
| move | what it means | |
|---|---|---|
| 1 | plan | decide what to do, and why |
| 2 | surface | say that intention and its reasoning out loud |
| 3 | defer | if the step is consequential, wait for a human verdict |
| 4 | record | write what happened to a ledger the human owns |
Step 3 is the entire point. It's where freedom of human decision actually lives.
No dependencies. No API key. Just Python 3.9+.
git clone https://github.com/thehotpath/reins.git
cd reins
python examples/mural_planner.py # interactive, you hold the reins
python tests/test_reins.py # 9 tests, runs without pytestWant a coding-flavored demo instead? python examples/repo_janitor.py.
Want the auto-playing tour (great for a screen recording)? python record_demo.py.
from reins import Agent, Action, ConsoleGate, MockPlanner, Policy, Risk
# 1. What the agent is ALLOWED to do. Capability is opt-in.
def draft_note(text): return f"drafted: {text}"
def send_email(to): return f"sent to {to}"
# 2. How it plans (swap MockPlanner for any LLM, see below).
planner = MockPlanner([
("draft_note", {"text": "hello"}, "drafting is safe and reversible"),
("send_email", {"to": "ada@example.com"}, "sending speaks in your name"),
])
# 3. Wire it up. ConsoleGate = a real human at the terminal.
agent = Agent(planner=planner, gate=ConsoleGate(), policy=Policy())
agent.register(Action("draft_note", draft_note, Risk.LOW))
agent.register(Action("send_email", send_email, Risk.HIGH, reversible=False))
ledger = agent.run("Reach out to Ada about the workshop.")
print(ledger.render()) # the full, honest record of what happenedThe agent drafts the note on its own (low risk, reversible). It stops and asks before sending the email (high risk, speaks for you). You stay in command without micromanaging.
You decide how much rope the agent gets. One setting, three presets:
Policy(autonomy=Autonomy.COPILOT) # ask before EVERY step
Policy(autonomy=Autonomy.COLLABORATOR) # do low-risk; ask about medium + high (default)
Policy(autonomy=Autonomy.TRUSTED) # only stop for high-risk, irreversible steps…plus per-action overrides for the things you never want automated, no matter what:
Policy(autonomy=Autonomy.TRUSTED,
always_ask=("publish_post", "send_money"), # always a human, period
never_ask=("read_file",)) # you've pre-cleared this| verdict | what happens |
|---|---|
| approve | run it as proposed |
| edit | change the arguments, then run it |
| reject | skip this step |
| why | make the agent explain its reasoning before you decide |
| quit | stop the whole run, you'll take it from here |
Every one of these is logged.
Closed systems keep their reasoning hidden. Reins keeps yours in a notebook you
can read, save (ledger.save("run.jsonl")), and audit:
✗ [rejected] email_partner(to='youth-center@example.org', ...)
↳ note: I'll reach out personally first, relationships matter
↳ skipped by human
✎ [ edited] book_venue(venue='Lamb Library community room', date='Jan 17, 10am')
↳ note: moved to Saturday, more families can come
↳ BOOKED Lamb Library community room for Jan 17, 10am
Reins never phones home. MockPlanner keeps the framework runnable with zero
setup, but plugging in a real LLM is one small adapter, you inject the client,
Reins just asks it for a plan (and then runs every step past the human anyway):
from reins import LLMPlanner
def complete(prompt: str) -> str:
# call OpenAI / Anthropic / a local model, your choice, your keys
...
agent = Agent(planner=LLMPlanner(complete), gate=ConsoleGate())reins/
agent.py the loop that always leaves room for a human
gate.py Console / Auto / Scripted gates, where the human decides
ledger.py an append-only record the human owns
policy.py the autonomy dial: which steps need a yes
planner.py MockPlanner + a one-function LLM adapter
examples/
mural_planner.py a storyteller's agent that never speaks for the community
repo_janitor.py a coding agent that sprints, then asks before it deletes
tests/
test_reins.py 9 tests proving a human can always stop, edit, or veto
- Pluggable ledger backends (SQLite, append-only file, signed log)
- A
reinsCLI to wrap any existing agent loop in gates - Replay a ledger to understand exactly why an agent did what it did
- Adapters for popular agent frameworks
- A web gate, so approvals can happen from your phone
See CONTRIBUTING.md. Good first issues are tagged. Be kind.
MIT, see LICENSE. Open agents, open code.
Built by Jazzelle Bustos. I spent six years helping people tell their own stories, in classrooms, on prison walls, on basketball courts. Agents are the next medium, and the same rule holds: the tool should hand people a sharper pen, never take the pen away. Read the manifesto if you want the longer version.