Observed since 20 Oct, 21:27 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
agent-action-guard
Runtime classifier for screening AI agent actions as safe, harmful, or unethical.
Framework to block harmful AI agent actions before they cause harm — lightweight, real-time, easy-to-use.
Python package support: Python 3.8 through Python 3.14.
pip install agent-action-guard
# or
uv add agent-action-guard
For embedding backend options and configuration details—including zero-config ONNX embeddings, custom local ONNX models, OpenAI-compatible embedding APIs, environment variables, and backend precedence—read USAGE.md. The installed packages also provide
aag-classifyfor direct JSON, JSON arrays, and JSONL batch classification.
Want to run the evaluation benchmark too?
pip install "agent-action-guard[harmactionseval]"
# or
uv add "agent-action-guard[harmactionseval]"
python -m agent_action_guard.harmactionseval
The repository also ships an npm package in typescript/package.json for screening agent actions in Node.js.
npm install agent-action-guard
If you use pnpm, the equivalent commands are:
pnpm install agent-action-guard
HarmActionsEval benchmark proved that AI agents with harmful tools will use them — even today's most capable LLMs. 80% of the LLMs tested executed actions at the first attempt for over 95% of the harmful prompts.
| Model | SafeActions@1 |
|---|---|
| Claude Haiku 4.5 | 0.00% |
| Phi 4 Mini Instruct | 0.00% |
| Granite 4-H-Tiny | 0.00% |
| GPT-5.4 Mini | 0.71% |
| Gemini 3.1 Flash Lite | 0.71% |
| Grok 4.20 Non Reasoning | 2.13% |
| Ministral 3 (3B) | 2.13% |
| Claude Sonnet 4.6 | 2.84% |
| Phi 4 Mini Reasoning | 2.84% |
| GPT-5.3 | 12.77% |
| Qwen3.5-397b-a17b | 23.40% |
| Average | 4.54% |
These models often still respond "Sorry, I can't help with that" while executing the harmful action anyway.
Action Guard sits between the agent and its tools, blocking unsafe calls before they run — no human in the loop required.
Laya is a general-purpose local model that can also be used as an action-safety classifier similar to Agent Action Guard. The repository comparison benchmark evaluates Agent Action Guard, gpt-5.6-luna, and Laya on the same HarmActions rows. Local classifiers use CPU execution, and warm-up/model-loading time is excluded from the reported per-action latency.
python scripts/compare_laya_harmactions.py
| Model | HarmActions | Accuracy | Precision | Recall | F1 | ms/action |
|---|---|---|---|---|---|---|
| Agent Action Guard | 97.87% | 97.87% | 100.00% | 97.87% | 98.92% | 19.66 |
| gpt-5.6-luna | 90.07% | 90.07% | 100.00% | 90.07% | 94.78% | 3381.72 |
| Laya | 51.06% | 51.06% | 100.00% | 51.06% | 67.61% | 815.86 |
The benchmark uses the same HarmActions rows for all classifiers; CPU execution is forced for the local systems to make the latency comparison more consistent.
Share a quick note in Discussions — it directly shapes the project's direction and helps the AI safety community. 🙌 Waiting with excitement for feedback and discussions on how this helps you or the AI community.
⭐ Star the repo if Action Guard is useful to you — it really does help!
@article{202510.1415,
title = {{Agent Action Guard: Classifying AI Agent Actions to Ensure Safety and Reliability}},
year = 2025,
month = {October},
publisher = {Preprints},
author = {Praneeth Vadlapati},
doi = {10.20944/preprints202510.1415.v2},
url = {https://www.preprints.org/manuscript/202510.1415},
journal = {Preprints}
}
Licensed under CC BY 4.0. If you prefer not to provide attribution, send a brief acknowledgment to praneeth.vad@gmail.com with the details of your usage and the potential impact on your project.
Projects for Next-Gen AI
Download counts and popularity will appear here as the collector receives them.
| Package / target | Requirement | Relationship |
|---|---|---|
numpyEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.8",
"evaluation": "NOT_EVALUATED"
} | numpy>=1.21.6 | runtime |
onnxruntimeEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.8",
"evaluation": "NOT_EVALUATED"
} | onnxruntime<2.0.0,>=1.14.0 | runtime |
openaiEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.8",
"evaluation": "NOT_EVALUATED"
} | openai<4.0.0,>=1.0.0 | runtime |
tokenizersEnvironment{
"extras": "",
"marker": "python_version < \"3.13\"",
"requires_python": ">=3.8",
"evaluation": "NOT_EVALUATED"
} | tokenizers<1.0.0,>=0.13.3; python_version < "3.13" | runtime |
tokenizersEnvironment{
"extras": "",
"marker": "python_version >= \"3.13\"",
"requires_python": ">=3.8",
"evaluation": "NOT_EVALUATED"
} | tokenizers<1.0.0,>=0.21.0; python_version >= "3.13" | runtime |
python-dotenvEnvironment{
"extras": "",
"marker": "extra == \"harmactionseval\"",
"requires_python": ">=3.8",
"evaluation": "NOT_EVALUATED"
} | python-dotenv<2.0.0,>=0.21.0; extra == "harmactionseval" | runtime |
requestsEnvironment{
"extras": "",
"marker": "extra == \"harmactionseval\"",
"requires_python": ">=3.8",
"evaluation": "NOT_EVALUATED"
} | requests<3.0.0,>=2.28.0; extra == "harmactionseval" | runtime |
richEnvironment{
"extras": "",
"marker": "extra == \"harmactionseval\"",
"requires_python": ">=3.8",
"evaluation": "NOT_EVALUATED"
} | rich<15.0.0,>=12.0.0; extra == "harmactionseval" | runtime |
fastapiEnvironment{
"extras": "",
"marker": "extra == \"all\"",
"requires_python": ">=3.8",
"evaluation": "NOT_EVALUATED"
} | fastapi; extra == "all" | runtime |
fastembedEnvironment{
"extras": "",
"marker": "extra == \"all\"",
"requires_python": ">=3.8",
"evaluation": "NOT_EVALUATED"
} | fastembed; extra == "all" | runtime |
psutilEnvironment{
"extras": "",
"marker": "extra == \"all\"",
"requires_python": ">=3.8",
"evaluation": "NOT_EVALUATED"
} | psutil; extra == "all" | runtime |
pydanticEnvironment{
"extras": "",
"marker": "extra == \"all\"",
"requires_python": ">=3.8",
"evaluation": "NOT_EVALUATED"
} | pydantic; extra == "all" | runtime |
python-dotenvEnvironment{
"extras": "",
"marker": "extra == \"all\"",
"requires_python": ">=3.8",
"evaluation": "NOT_EVALUATED"
} | python-dotenv<2.0.0,>=0.21.0; extra == "all" | runtime |
pytzEnvironment{
"extras": "",
"marker": "extra == \"all\"",
"requires_python": ">=3.8",
"evaluation": "NOT_EVALUATED"
} | pytz; extra == "all" | runtime |
requestsEnvironment{
"extras": "",
"marker": "extra == \"all\"",
"requires_python": ">=3.8",
"evaluation": "NOT_EVALUATED"
} | requests<3.0.0,>=2.28.0; extra == "all" | runtime |
richEnvironment{
"extras": "",
"marker": "extra == \"all\"",
"requires_python": ">=3.8",
"evaluation": "NOT_EVALUATED"
} | rich<15.0.0,>=12.0.0; extra == "all" | runtime |
uvicornEnvironment{
"extras": "standard",
"marker": "extra == \"all\"",
"requires_python": ">=3.8",
"evaluation": "NOT_EVALUATED"
} | uvicorn[standard]; extra == "all" | runtime |
torchEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.8",
"evaluation": "NOT_EVALUATED"
} | torch; extra == "dev" | runtime |
onnxEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.8",
"evaluation": "NOT_EVALUATED"
} | onnx<2.0.0,>=1.14.0; extra == "dev" | runtime |
uvEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.8",
"evaluation": "NOT_EVALUATED"
} | uv; extra == "dev" | runtime |
ruffEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.8",
"evaluation": "NOT_EVALUATED"
} | ruff; extra == "dev" | runtime |
blackEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.8",
"evaluation": "NOT_EVALUATED"
} | black; extra == "dev" | runtime |
isortEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.8",
"evaluation": "NOT_EVALUATED"
} | isort; extra == "dev" | runtime |
flake8Environment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.8",
"evaluation": "NOT_EVALUATED"
} | flake8; extra == "dev" | runtime |
pylintEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.8",
"evaluation": "NOT_EVALUATED"
} | pylint; extra == "dev" | runtime |
mypyEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.8",
"evaluation": "NOT_EVALUATED"
} | mypy; extra == "dev" | runtime |
python-dotenvEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.8",
"evaluation": "NOT_EVALUATED"
} | python-dotenv<2.0.0,>=0.21.0; extra == "dev" | runtime |
requestsEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.8",
"evaluation": "NOT_EVALUATED"
} | requests<3.0.0,>=2.28.0; extra == "dev" | runtime |
richEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.8",
"evaluation": "NOT_EVALUATED"
} | rich<15.0.0,>=12.0.0; extra == "dev" | runtime |
scikit-learnEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.8",
"evaluation": "NOT_EVALUATED"
} | scikit-learn; extra == "dev" | runtime |
fastembedEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.8",
"evaluation": "NOT_EVALUATED"
} | fastembed; extra == "dev" | runtime |
psutilEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.8",
"evaluation": "NOT_EVALUATED"
} | psutil; extra == "dev" | runtime |
pytzEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.8",
"evaluation": "NOT_EVALUATED"
} | pytz; extra == "dev" | runtime |
fastapiEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.8",
"evaluation": "NOT_EVALUATED"
} | fastapi; extra == "dev" | runtime |
uvicornEnvironment{
"extras": "standard",
"marker": "extra == \"dev\"",
"requires_python": ">=3.8",
"evaluation": "NOT_EVALUATED"
} | uvicorn[standard]; extra == "dev" | runtime |
pydanticEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.8",
"evaluation": "NOT_EVALUATED"
} | pydantic; extra == "dev" | runtime |
bdist_wheel · 90.16 KB · Python py3
sdist · 95.08 KB · Python source
Shared repository data · GitHub
Observed since 20 Oct, 21:27 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package_version:be58db7cb32f248bcc3ae3758ab35724dbe07ef3801c2e5ace1f4ed0d62bc42c