pytrustful-ai
Offline-first, multilingual content moderation for AI agents — exposed as a Model Context Protocol server with named presets and runtime-extensible custom checks.
pip install pytrustful-ai and you get a working moderation MCP with the model
already bundled. No API keys, no first-run downloads, no network calls at
runtime.
Why
Most moderation options for agents fall into one of three traps:
- API-only (OpenAI Moderation, etc.) — requires a key, phones home, per-request cost.
- Blacklist-only — fast but blind to paraphrase, sarcasm, and non-English.
- Heavy classifier — accurate but a 500 MB model you can't ship inside a wheel.
pytrustful-ai splits the job into layers:
- Keyword layer — runs on every request. Backed by
profanity_check(English, fast) orglin-profanity(25+ languages) if installed. - Semantic layer — a quantized Model2Vec static embedding (~62 MB) compared against safe/toxic anchors. Fires only when the keyword layer passes.
Result: sub-20 ms typical latency, English + many other languages, zero network dependency once installed.
Install
pip install pytrustful-ai
Optional multilingual keyword backend:
pip install pytrustful-ai[glin]
Use as an MCP server
Add to your MCP client config (Claude Desktop, Cursor, Windsurf, etc.):
{
"mcpServers": {
"pytrustful-ai": {
"command": "pytrustful-ai"
}
}
}
The server exposes one tool:
moderate(text: str, preset: str = "strict", custom_presets: dict | None = None)
Use as a Python library
from pytrustful_ai import run_check
result = run_check("you absolute idiot", preset="strict")
# {
# "allowed": False,
# "preset": "strict",
# "triggered": [{"layer": "semantic", "toxic_probability": 0.9805}],
# "reason": "Preset 'strict' triggered",
# }
Presets
| Preset | Layers | Threshold | Use when |
|---|---|---|---|
profanity |
keyword only | — | You only want a fast block on hard profanity |
toxicity |
keyword + semantic | 0.60 | Balanced: catches subtle insults without overblocking |
strict |
keyword + semantic | 0.40 | Public-facing agents, minors, compliance contexts |
run_check returns allowed: True or False, plus a triggered array you can
log, route to human review, or use to explain the decision to the user.
Custom presets
You do not have to edit the package to add rules. Pass presets at call time:
run_check(
text="internal salary figures attached",
preset="paranoid",
custom_presets={
"paranoid": {"fast_only": False, "threshold": 0.15},
},
)
Custom presets merge over the defaults — pass strict with a different
threshold to override it, or a new key to add one. Pass custom_presets={} to
use only the built-ins.
Preset schema
Each preset is a small dict:
{
"fast_only": bool, # True = run keyword layer only, skip the semantic model
"threshold": float, # Semantic-layer cutoff in [0.0, 1.0]. Ignored if fast_only.
}
Offline guarantee
The quantized model (int8) and tokenizer are installed inside the wheel under
pytrustful_ai/models/vtx-mod-1/. StaticModel.from_pretrained() loads from
that local path and does not contact Hugging Face.
To prove it after install:
python - <<'PY'
from pytrustful_ai import run_check
print(run_check("hello", "strict"))
PY
Run that on a machine with the network disconnected — it will still print a result.
Configuration
| Env var | Default | Meaning |
|---|---|---|
PYTRUSTFUL_MODEL_ID |
VTXAI/VTX-MOD-1 |
Model ID used by scripts/bundle_model.py |
PYTRUSTFUL_QUANTIZATION |
int8 |
int8, float16, or "" (skip) |
These affect the bundle step. At runtime the bundled files are used directly and env vars are ignored.
Development
git clone https://github.com/<you>/pytrustful-ai
cd pytrustful-ai
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
python scripts/bundle_model.py # downloads + quantizes the model
pytest -v
Rebuild artifacts:
rm -rf dist/ build/ src/*.egg-info
python -m build
ls -lh dist/
Both artifacts must stay under 100 MB — PyPI's per-file limit. The CI workflow enforces this with a guard step.
Publishing
Tagging v* triggers .github/workflows/workflow.yml, which runs:
test— pytest with fake engine, no model downloadbuild— bundle model, build wheel, verify size + contentspublish-to-pypi— Trusted Publishing via OIDC
First-time setup: add a pending publisher on https://pypi.org/manage/account/publishing/ with:
- Owner: your GitHub user/org
- Repository:
pytrustful-ai - Workflow:
workflow.yml - Environment:
pypi
Model attribution
The bundled model is VTX-MOD-1
by VTXAI, redistributed under its model license. See src/pytrustful_ai/models/vtx-mod-1/README.md
for the original card.
Limitations
- English-leaning keyword layer by default.
profanity_checkis trained on English. Install[glin]for 25+ language coverage. - Thresholds are heuristics. 0.4 / 0.6 are starting points. Tune
custom_presetsfor your domain. - No image or audio moderation. Text only.
- Quantization trades a little accuracy for size. If you need fp32, run
PYTRUSTFUL_QUANTIZATION="" python scripts/bundle_model.pyand expect a ~150 MB wheel — over PyPI's limit, so host it elsewhere.
License
MIT
Metadata
Release files for pytrustful-ai 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| pytrustful_ai-0.1.0.tar.gz | 40.3 MB | With provenance | Details for pytrustful_ai-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| pytrustful_ai-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for pytrustful_ai-0.1.0-py3-none-any.whl |
Total release size: 80.7 MB
Release files / pytrustful_ai-0.1.0.tar.gz
| Download URL | pytrustful_ai-0.1.0.tar.gz |
|---|---|
| Size | 40.3 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
97c4f8d03da9ed79070e806990975c91c78208fb553a3b2fd3fc630b22fe3724
|
|
BLAKE2b-256 checksum How to use checksums |
a80c85c61a0bb257a70998f3466ed837c2572a2d810b4504bc3761689bcf378a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 5, 2026.
Transparency logRelease files / pytrustful_ai-0.1.0-py3-none-any.whl
| Download URL | pytrustful_ai-0.1.0-py3-none-any.whl |
|---|---|
| Size | 40.4 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
54e3e21a6fb059584fd1ea9759587f02cb1ce82885fc71952b9397ab3e2e99c6
|
|
BLAKE2b-256 checksum How to use checksums |
713442b346452aadca312abcef60c06d01e0ccccfff94c31e7a581f66588ceaa
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 5, 2026.
Transparency logSecurity for pytrustful-ai 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for pytrustful_ai-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 5, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.