https://github.com/shamspias/reins
A lightweight agent harness you bolt onto your app so an LLM can operate it — safely, and cheaply.
https://github.com/shamspias/reins
agent-framework agent-harness agent-memory agent-orchestration agent-skills agentic-ai agentic-workflow harness harness-engineering harness-framework reins
Last synced: about 13 hours ago
JSON representation
A lightweight agent harness you bolt onto your app so an LLM can operate it — safely, and cheaply.
- Host: GitHub
- URL: https://github.com/shamspias/reins
- Owner: shamspias
- License: mit
- Created: 2023-04-09T14:12:26.000Z (about 3 years ago)
- Default Branch: main
- Last Pushed: 2026-06-29T07:16:49.000Z (3 days ago)
- Last Synced: 2026-06-29T09:13:24.283Z (3 days ago)
- Topics: agent-framework, agent-harness, agent-memory, agent-orchestration, agent-skills, agentic-ai, agentic-workflow, harness, harness-engineering, harness-framework, reins
- Language: Python
- Homepage:
- Size: 1.36 MB
- Stars: 90
- Watchers: 5
- Forks: 15
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
Awesome Lists containing this project
README
# Reins
**A lightweight agent harness you bolt onto your app so an LLM can operate it — safely and cheaply.**
[](LICENSE)
[](https://www.python.org/)
[](#status)
Point Reins at functions you already have — or your ORM models — and hand it a goal in
plain language. It works out which of your operations to call and in what order, runs
them **through your own code (never raw SQL by default)**, and returns the result, with
near-zero token overhead and safe-by-default writes. There is no graph to draw: you
expose your app, and the agent operates it.
> **The wedge: Reins gives the model your _verbs_, not your _tables_.**
> Intent-named functions like `refund_order` carry the meaning that raw schemas and
> OpenAPI specs strip away — which is exactly where text-to-SQL and auto-generated tool
> layers lose their reliability.
## Example
```python
from reins import Agent, capability
@capability
def find_orders(status: str) -> list[dict]:
"""Find orders by their current status."""
return store.orders(status=status) # your existing code
@capability
def refund_order(order_id: int) -> dict:
"""Refund a customer's order by its public order number."""
return payments.refund(order_id) # your existing code
agent = Agent(capabilities=[find_orders, refund_order])
# ask() is read-only: it can never call a write capability.
result = agent.ask("how many orders are stuck in processing?")
print(result.output.text)
# run() may write: writes are gated before they execute.
agent.run("refund order 8842")
```
The model is read from your environment (`ANTHROPIC_API_KEY`), or pass one explicitly
with `Agent(model="anthropic:claude-...")`.
## Why Reins
- **Your verbs, not your tables.** The model sees intent-named operations with real
descriptions and types — not opaque columns or hand-written JSON schemas.
- **Safe by default.** `ask()` is read-only and can never write; writes are opt-in and
gated. Beginners cannot cause damage, and the boundary is enforced in code, not in a
prompt the model can reason around.
- **You hold the reins.** Reins runs *your* functions, so it inherits your existing
validation, authorization, and business rules. No raw SQL against your database.
- **Tiny and transparent.** The core is a small, readable loop you own — no hidden
graph, no framework internals to reverse-engineer when you hit a ceiling.
- **Provider-agnostic.** Bring any model through a thin adapter; Anthropic ships in the
box.
## How it works
1. **Register.** Decorate the functions you want to expose. Reins reads their type hints
and docstrings to derive a schema and classify each as read or write.
2. **Discover.** The agent is shown your intent-named operations and the goal.
3. **Plan.** It decides which operations to call, and in what order, to reach the goal.
4. **Govern.** Reads run freely; writes pass through policy, approval, and audit before
anything touches your data.
5. **Return.** Only results cross back to the model, and every decision and call is
traceable.
## Installation
Reins requires **Python 3.11+**.
```bash
pip install reins # core (first PyPI release coming soon)
pip install "reins[anthropic]" # with the Anthropic model backend
```
Until the first published release, install from source:
```bash
git clone https://github.com/shamspias/reins
pip install -e "reins/packages/python[anthropic]"
export ANTHROPIC_API_KEY=sk-...
```
## The two verbs
Reins has exactly two entry points, and they *are* the safety model:
- **`ask(goal)`** — the agent may only read. It never writes, never blocks, and never
prompts. Use it for dashboards, search, analytics, and "what is…".
- **`run(goal)`** — the agent may read and write. Writes are detected automatically and
gated for approval. Use it for "do something": create, update, refund, send.
Read/write classification is automatic and errs toward "write" when a name is ambiguous,
so a wrong guess only ever adds a needless approval — it can never let a write slip
through as a read. Override it explicitly when you know better:
```python
@capability(reads=True)
def export_report(month: str) -> bytes: ...
@capability(destructive=True, confirm=True)
def deactivate_user(user_id: int) -> None: ...
```
## Reins vs. graph frameworks
| Aspect | Graph frameworks (LangChain / LangGraph) | Reins |
| ------------------- | ---------------------------------------- | ------------------------------------------------ |
| Mental model | You draw a graph of nodes and edges | You expose functions; the agent finds the path |
| Control flow | Predefined by you | Decided by the model, within your guardrails |
| Adding it to an app | Wrap logic in framework primitives | Decorate functions you already have |
| CRUD on a database | Often raw SQL tools, or custom nodes | Calls your typed methods, inheriting your auth |
| Debuggability | Debug the framework's internals | Debug your own small loop and your own functions |
| Languages | Python-first | Python today; Go and TypeScript planned |
## Status
Reins is in **early development**, Python first. The core works today: typed capabilities
derived from your functions, the agent loop, the `ask()` / `run()` safety boundary, and
pluggable model backends. APIs may change before `1.0`.
### Roadmap
- [x] Typed capabilities from your functions — schema and read/write classification
- [x] The agent loop with `ask()` / `run()` and a strict read-only boundary
- [x] Provider-agnostic model backends (Anthropic included)
- [ ] Policy, human approval, and audit for writes
- [ ] ORM auto-exposure (SQLAlchemy, Django) and a zero-code `reins chat `
- [ ] Code-mode execution and on-demand capability/schema discovery
- [ ] Row-level security and identity propagation
- [ ] Go and TypeScript packages, verified against one shared conformance suite
## Development
```bash
make setup # create a local venv, install the package and dev tools, set up pre-commit
make check # the gate: ruff + mypy --strict + tests + conformance
```
The Python package lives in `packages/python`. See [CONTRIBUTING.md](CONTRIBUTING.md) for
the workflow and conventions.
## License
[MIT](LICENSE)