Local-first AI agent safety engine with Thompson Sampling. Score tool calls, learn from corrections, zero cloud dependency.
Project description
sansin-core
Local-first AI agent safety engine. Score tool calls, learn from corrections, zero cloud dependency.
Thompson Sampling + context-aware heuristics. Ships with pre-trained priors so it works out of the box. Runs anywhere Python runs, stdlib only, no API keys.
pip install sansin-core
Quick Start
from sansin_core import SansinLocal
gate = SansinLocal()
# Score a tool call
decision = gate.check("send_email", {"recipients": 500, "irreversible": True})
print(decision.allow) # False
print(decision.risk_score) # 0.9
print(decision.reason) # "deny"
# Override to teach the engine
gate.override(decision.id, "allow", "approved by admin")
# Next time, the engine remembers
decision = gate.check("send_email", {"recipients": 500})
# risk_score is now lower — it learned
How It Works
Every tool call gets a risk score from 0.0 (safe) to 1.0 (dangerous).
Heuristics classify tools by keyword. read_file starts low-risk. delete_database starts high-risk. Context modifiers like {"recipients": 500} or {"irreversible": True} push scores higher.
Thompson Sampling learns from your corrections. Override a blocked call with "allow" and the engine updates its Beta distribution for that tool. After ~10 overrides per tool, learned behavior starts blending with heuristics. After ~50, the engine mostly trusts what it learned from you.
Community priors ship with the package (15 common tools, ~20-override quality each). New installs aren't starting from zero.
MCP Safety Proxy
Drop-in firewall between any MCP client and upstream server. The agent never knows Sansin exists.
pip install sansin-core[mcp]
sansin-mcp-proxy --upstream stdio://npx -y @modelcontextprotocol/server-filesystem /tmp
Point your MCP client at the proxy instead of the upstream server. Every tool call is scored before forwarding. High-risk calls are blocked with an explanation.
The proxy exposes three management tools (configurable prefix, default sansin_):
sansin_override— override a blocked decisionsansin_status— view engine statistics and per-tool priorssansin_decisions— list recent decisions for auditing
# Custom prefix to avoid collisions
sansin-mcp-proxy --upstream stdio:///path/to/server --prefix safety_
# Fail-closed mode for regulated environments
sansin-mcp-proxy --upstream stdio:///path/to/server --fail-closed
Interactive Demo
See the learning engine in action with 50 simulated decisions:
sansin-demo
Watches Thompson Sampling learn in real-time with ASCII confidence bars.
API Reference
SansinLocal(db_path, fail_closed, load_community)
| Parameter | Default | Description |
|---|---|---|
db_path |
~/.sansin/decisions.db |
SQLite database path |
fail_closed |
False |
Block on internal errors instead of allowing |
load_community |
True |
Load pre-trained community priors on first run |
gate.check(tool_name, context) -> Decision
Score a tool call. Returns immediately.
decision = gate.check("delete_file", {"path": "/etc/passwd"})
decision.allow # bool — should the call proceed?
decision.risk_score # float 0.0-1.0
decision.safe_probability # float — P(safe) from Thompson Sampling
decision.certainty # float — how confident the engine is
decision.reason # str — "allow", "escalate", or "deny"
decision.id # str — UUID for override reference
gate.override(decision_id, correct_action, reason) -> bool
Teach the engine. correct_action must be "allow" or "block".
gate.status() -> dict
Engine statistics: decision counts, per-tool priors (alpha, beta, override count).
gate.export_priors(path) / gate.import_priors(path)
Export/import learned priors as JSON. Share across machines or teams.
Design Decisions
Fail-open by default. A safety product that breaks your agent's workflow gets uninstalled. Fail-closed mode is available for regulated environments.
Context-aware keywords. "write" is medium-risk by default. It only escalates to high-risk when combined with blast radius modifiers like "all", "every", "bulk", "batch", "mass" in the context.
SQLite WAL mode. Thread-safe, handles concurrent reads with a single writer. Good for <50 tool calls/second, which covers every local agent use case.
Zero required dependencies. The core engine uses only Python stdlib. MCP proxy is an optional extra (pip install sansin-core[mcp]).
Requirements
- Python 3.10+
- No required dependencies (stdlib only)
- Optional:
mcp>=1.2.0for MCP proxy
License
MIT. See LICENSE.
Links
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sansin_core-0.1.0.tar.gz.
File metadata
- Download URL: sansin_core-0.1.0.tar.gz
- Upload date:
- Size: 25.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7f75f7ad8789aca8f732216c349e49c8be647735e4764bb8ab68bb90a197eefa
|
|
| MD5 |
e922132a3d646f0c31519c16be01bdbd
|
|
| BLAKE2b-256 |
6c9126914e4e7e46f770cc437011a1ab5507f4953150fc5a2271cad79d135775
|
Provenance
The following attestation bundles were made for sansin_core-0.1.0.tar.gz:
Publisher:
ci.yml on choongylol/sansin-core
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sansin_core-0.1.0.tar.gz -
Subject digest:
7f75f7ad8789aca8f732216c349e49c8be647735e4764bb8ab68bb90a197eefa - Sigstore transparency entry: 1237135078
- Sigstore integration time:
-
Permalink:
choongylol/sansin-core@06ef3d161000e25b123cd4e17587ba38f5a2b633 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/choongylol
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@06ef3d161000e25b123cd4e17587ba38f5a2b633 -
Trigger Event:
push
-
Statement type:
File details
Details for the file sansin_core-0.1.0-py3-none-any.whl.
File metadata
- Download URL: sansin_core-0.1.0-py3-none-any.whl
- Upload date:
- Size: 22.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fd93c263557ad59434b5c7742074d2dbaf33cd30997f0adb8a7b56c7cc37c2bf
|
|
| MD5 |
b145f3d81d404800dc28d32afe5d2990
|
|
| BLAKE2b-256 |
2a69824b86bcf191c63f706098320c8ad327aad0d865bfbdebb02abac86ae180
|
Provenance
The following attestation bundles were made for sansin_core-0.1.0-py3-none-any.whl:
Publisher:
ci.yml on choongylol/sansin-core
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sansin_core-0.1.0-py3-none-any.whl -
Subject digest:
fd93c263557ad59434b5c7742074d2dbaf33cd30997f0adb8a7b56c7cc37c2bf - Sigstore transparency entry: 1237135108
- Sigstore integration time:
-
Permalink:
choongylol/sansin-core@06ef3d161000e25b123cd4e17587ba38f5a2b633 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/choongylol
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@06ef3d161000e25b123cd4e17587ba38f5a2b633 -
Trigger Event:
push
-
Statement type: