Catalog PyPI
Back to packageRELEASE DETAILS

0.2.0

PyPI

agent-tooltrust

A pre-execution, deterministic policy decision point for tool-using AI agents. Evaluate every proposed tool call against declarative policy and return allow / audit / escalate / deny.

agentaiauthorizationgovernancellmmcppolicyrisksafetysecuritytool-use
Published15 Aug 2026
Direct dependencies29
Transitive dependenciesNot calculated

README

Version 0.2.0 documentation

Agent ToolTrust

CI License: MIT Python 3.11+ PyPI Ruff Type checked Coverage Contributor Covenant OpenSSF Best Practices

Contextual risk and permission engine for tool-using AI agents. Allow, audit, escalate, or deny — with explainable, deterministic, auditable policy.

[!NOTE] Status: v0.2.0 shipped and published to PyPI · pip install agent-tooltrust License: MIT


Why

Giving an agent a tool is easy. Defining when it should be allowed to use it, in which environment, on what data, and under what approval model is the real problem.

Most teams manage agent tool permissions with flat allow-lists: this tool is allowed, that tool is denied. But the same tool is harmless in staging and dangerous in production. A read query over public docs is not equivalent to a query over customer-PII. Flat allow-lists are a reachability control, not an authorization decision. Agent ToolTrust replaces them with a contextual, deterministic, auditable risk engine.

Research backing: <18% of MCP server deployments scope tool permissions. ~80% of orgs report agent actions beyond intended scope. OWASP Agentic AI Top 10 classifies tool misuse as a first-class risk. ToolTrust implements the Policy Decision Point (PDP) pattern converged on by Permit0, Microsoft AGT, the OPA ecosystem, and OWASP guidance.


What It Is

The Decision Pipeline

 Tool Call → NORMALIZE → SCORE → DECIDE → EXPLAIN → AUDIT

Agent ToolTrust scores every tool invocation across five risk dimensions and returns one of four decisions:

DecisionMeaningWhen
AllowExecute normallyLow risk (read-only in staging, public data)
AuditAllow + enhanced loggingElevated risk (read on sensitive data, write in staging)
EscalateHuman approval requiredHigh risk (write in production, sensitive data mutation)
DenyBlocked with reasonCritical risk (delete in production, PII access, destructive ops)

Risk Dimensions

DimensionExamplesDefault weight
Tool categoryfs, shell, http, db, git, email, cloud, secrets, iam, payment1.0 (domain-dependent)
Action classread (weight 0), write (3), delete (10), grant (10)1.0
Environmentstaging (0.1), production (0.8), pre-prod (0.6)1.0 (org-configurable)
Data sensitivitypublic (0.0), internal (0.3), restricted (0.7), customer-PII (1.0)1.0 (org-configurable)
Agent classci-bot, support-bot, admin-bot, untrusted1.0 (configurable)

Starter Action Taxonomy (13 domains, 60+ verbs)

DomainVerbsBaseline risk
fs (filesystem)read, write, delete, list, movelow→high
shellexec, pipehigh
httpget, post, put, delete, patchlow→med
db (database)query, execute, migrate, droplow→critical
git (version control)status, diff, log, commit, push, force_pushlow→critical
emailread, send, delete, searchlow→high
cloud (infra)list, describe, create, update, delete, scalelow→critical
secretsread, write, rotate, revokecritical
iam (identity)read_role, assign_role, revoke_role, create_keyhigh→critical
paymentread, refund, transfer, chargemed→critical
approvalread, approve, deny, delegatemed→critical
searchquery, index, delete_indexlow→med
notifysend_slack, send_teams, send_webhook, pagelow→high

Policy Posture Presets (never a blank slate)

tooltrust init --posture balanced  # Recommended default
tooltrust init --posture strict    # Prod fleets, compliance
tooltrust init --posture permissive # Local dev, sandboxes

Delivery Modes

ModeHowBest for
Python librarypip install agent-tooltrust; engine.evaluate(...) in-processZero infra, 15-line integration
MCP client wrapperProxies tools/call through the engineAgents using MCP tool servers
MCP serverToolTrust exposes evaluate + explain + authorize_data_source as MCP toolsAny MCP agent queries authorization
HTTP PDPPOST /authorize returns Decision JSON — language-agnosticNon-Python fleets, gateways
CLItooltrust evaluate, audit, analytics sessions, calibrate report, baseline check, pack listShell, CI gates
OPAL syncDistributed policy propagation to all PDP nodesMulti-instance fleets
Framework adaptersDecorators/guards for LangGraph, PydanticAI, OpenAI Agents SDK, CrewAIFramework-native integration

Quickstart

pip install agent-tooltrust
tooltrust init --posture balanced
from agent_tooltrust import Engine

engine = Engine()

# Safe read in staging
result = engine.evaluate(
    tool="query_logs", action="read",
    environment="staging", data_class="internal",
    agent_id="debug-bot",
)
print(result.decision)    # "allow"
print(result.explanation) # "Read-only log query in staging: low risk. Proceeding."

# Write in production on sensitive data
result = engine.evaluate(
    tool="deploy_service", action="write",
    environment="production", data_class="restricted",
    agent_id="release-bot",
)
print(result.decision)    # "escalate"
print(result.explanation) # "Write action in production on sensitive data requires approval."

# Destructive operation — blocked
result = engine.evaluate(
    tool="drop_database", action="delete",
    environment="production", data_class="customer_pii",
    agent_id="release-bot",
)
print(result.decision)    # "deny"
print(result.explanation) # "Delete action in production on customer PII is blocked."

# Framework integration — pick your adapter
from agent_tooltrust.adapters.langgraph import ToolTrustToolNode
node = ToolTrustToolNode(tools, engine=engine)

Framework Support

FrameworkAdapterIntegration point
Raw Python@engine.guard decorator / with engine.session():Function wrappers
MCP clientToolTrustMCPWrapper(mcp_client, engine)tools/call proxy
LangGraphToolTrustToolNode(tools, engine)ToolNode pre-call interceptor
PydanticAI@tooltrust_guard(engine) on @agent.toolTool decorator
OpenAI Agents SDKtooltrust_guardrail(engine) → @tool_input_guardrailNative guardrail API
CrewAIwrap_tool(tool, engine)Tool _run() wrapper
SWE-benchSWEBenchGuard(engine) / tooltrust swebenchCoding-agent benchmark wrapper + per-task decision trace

Security Compliance Baseline

ToolTrust targets three concrete, audit-level security baselines:

Baselinev0.1v0.2v0.3
OWASP Agentic AI Top 105/10 covered10/10 covered10/10 full
OpenSSF Best PracticesSilverSilver+Gold aspirational
ToolTrust Security BaselineEssentialHardened (15/15 checks)Certified

See SECURITY.md for the full OWASP mapping and SECURITY_BASELINE.md for the tier-by-tier checklist. Verify your posture locally with tooltrust baseline check essential.


Documentation

DocumentContent
PRDProduct requirements: why, what, 11 CUJs, 92+ features
ArchitectureSystem design, 5-stage pipeline, components, data model
Design Decisions14 recorded design decisions with rationale
API ReferenceEngine API, CLI, MCP tools, framework adapters, SWE-bench integration, error codes
Release Notes v0.2.0What shipped in v0.2.0, quality gates, known limitations, roadmap
CHANGELOGKeep a Changelog–formatted history of all releases
Demo Scenario5-call narrative: allow→audit→escalate→deny→replan
Demo Agent ExampleRunnable demo agent + adversarial variant, with captured output
DB SchemaPostgres + SQLite audit tables, JSONL format
WBS6 files, 18 milestones across v0.1-v0.4
CONTRIBUTING.mdDevelopment setup and guidelines
SECURITY.mdVulnerability reporting, OWASP 10/10 coverage, OpenSSF status
Security BaselineEssential + Hardened tier checklist + tooltrust baseline check
GOVERNANCE.mdProject decision-making and releases
Fleet Deployment GuideMulti-node PDP, OPAL sync, nginx LB, rollback
PDP + MCP-Data Design/authorize endpoint and MCP-Data connector architecture
Session Analytics DesignCross-session deny→allow transition detection
Audit Redaction DesignPII/secret redaction in audit log
Score Calibration DesignCounterfactual thresholds, false rates, shadow mode
Stale-Credential DesignDistinct audit tag for credential-rejected calls
Field Test Report v0.2.0Plan A 83/83 (100%), Plan B 116/123 (94%), replan 8/8, 4-model comparison, observations + lessons
Release Checklist17-step release checklist for v0.2.0

Milestones

VersionScopeShip target
v0.1.0Core engine, 6 adapters, MCP server, 3 posture presets, YAML+OPA/Rego dual backend, audit (JSONL/SQLite/Postgres), CLI, field tests (10 agents, 300 assertions), demo agent, OpenSSF Silver, OWASP 5/10, SWE-bench wrapper✅ Shipped
v0.2.0Session replay + audit replay, PDP /authorize service, MCP-Data connector, session analytics, audit redaction, stale-credential tagging, score calibration, OPAL sync, policy packs catalog, fleet deployment guide, hardened security baseline (15/15), OWASP 10/10, 91% coverage✅ Shipped
v0.3.0Output inspection, dispatcher safety, child delegation, tamper-evident audit, policy packs catalog, OWASP 10/10, Certified baselineTBD
v0.4.0Governance reports, distributed policy sync, OpenSSF Gold aspirationalTBD

Understanding Criticality — Risk Scenarios

ToolTrust scores every tool call across five dimensions. Here's how the risk ladder works in practice:

Risk Ladder

Risk LevelDecisionExample
LowAllowquery_logs (read) in staging on public data by a CI bot
MediumAuditread_secrets (read) in production on restricted data — allowed but logged
HighEscalatedeploy_service (write) in production on restricted data — requires human approval
CriticalDenydrop_database (delete) in production on customer PII — blocked

Scenario 1 — The CI Bot

A CI/CD pipeline bot queries application logs in staging for debugging:

  • Tool: query_logs | Action: read | Env: staging | Data: internal
  • Result: ALLOW — read-only log query in staging on internal data is low risk. All dimensions contribute minimally: action_class=0.00, environment=0.10, data=0.20.

Scenario 2 — The Support Bot Reads Customer Data

A support bot needs to read customer information to resolve a ticket:

  • Tool: read_secrets | Action: read | Env: production | Data: restricted
  • Result: AUDIT — reading sensitive data in production triggers enhanced logging. Every access recorded with full context for compliance review.

Scenario 3 — The Release Bot Deploys

A scheduled release bot pushes a deployment to production:

  • Tool: deploy_service | Action: write | Env: production | Data: restricted
  • Result: ESCALATE — write actions in production require explicit human approval. The bot cannot deploy until an on-call engineer approves the escalation.

Scenario 4 — Destructive Operation

An agent attempts to delete a production database containing customer data:

  • Tool: drop_database | Action: delete | Env: production | Data: customer_pii
  • Result: DENY — destructive operation on sensitive data is blocked outright. The explanation suggests: "Use a read-only alternative or move to a lower-risk environment."

A support bot is pre-approved to query logs in staging but tries to access production:

  • Session consent: [{tool: query_logs, env: staging, data_class: internal}]
  • Call: query_logs (read) in production on internal data
  • Result: ESCALATE — the call falls outside the session's consent scope. The scope boundary prevents the agent from silently exceeding its granted permissions.

Community


License

MIT © 2026 Debashish Ghosal

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Declared dependencies 44

Native requirements
29 direct targetsNot calculated transitive count
Package / targetRequirementRelationship
cryptography
Environment
{
  "extras": "",
  "marker": null,
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
cryptography>=50.0.0runtime
opentelemetry-api
Environment
{
  "extras": "",
  "marker": null,
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
opentelemetry-api>=1.44.0runtime
opentelemetry-sdk
Environment
{
  "extras": "",
  "marker": null,
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
opentelemetry-sdk>=1.44.0runtime
pydantic
Environment
{
  "extras": "",
  "marker": null,
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
pydantic>=2.7runtime
pyyaml
Environment
{
  "extras": "",
  "marker": null,
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
pyyaml>=6.0runtime
starlette
Environment
{
  "extras": "",
  "marker": null,
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
starlette>=0.37runtime
watchfiles
Environment
{
  "extras": "",
  "marker": null,
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
watchfiles>=0.22runtime
google-adk
Environment
{
  "extras": "",
  "marker": "extra == \"adk\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
google-adk>=1.10.0; extra == "adk"runtime
autogen-agentchat
Environment
{
  "extras": "",
  "marker": "extra == \"all\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
autogen-agentchat>=0.7.5; extra == "all"runtime
autogen-ext
Environment
{
  "extras": "openai",
  "marker": "extra == \"all\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
autogen-ext[openai]>=0.7.5; extra == "all"runtime
crewai
Environment
{
  "extras": "",
  "marker": "extra == \"all\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
crewai>=1.6.1; extra == "all"runtime
fastmcp
Environment
{
  "extras": "",
  "marker": "extra == \"all\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
fastmcp>=3.4; extra == "all"runtime
google-adk
Environment
{
  "extras": "",
  "marker": "extra == \"all\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
google-adk>=1.10.0; extra == "all"runtime
langchain-core
Environment
{
  "extras": "",
  "marker": "extra == \"all\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
langchain-core>=1.5.4; extra == "all"runtime
langgraph
Environment
{
  "extras": "",
  "marker": "extra == \"all\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
langgraph>=1.2.11; extra == "all"runtime
litellm
Environment
{
  "extras": "",
  "marker": "extra == \"all\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
litellm>=1.96.2; extra == "all"runtime
llama-index-core
Environment
{
  "extras": "",
  "marker": "extra == \"all\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
llama-index-core>=0.14.23; extra == "all"runtime
llama-index-llms-openai
Environment
{
  "extras": "",
  "marker": "extra == \"all\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
llama-index-llms-openai>=0.7.10; extra == "all"runtime
mcp
Environment
{
  "extras": "",
  "marker": "extra == \"all\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
mcp>=1.28; extra == "all"runtime
openai-agents
Environment
{
  "extras": "",
  "marker": "extra == \"all\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
openai-agents>=0.20.0; extra == "all"runtime
pydantic-ai
Environment
{
  "extras": "",
  "marker": "extra == \"all\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
pydantic-ai>=2.28.0; extra == "all"runtime
smolagents
Environment
{
  "extras": "",
  "marker": "extra == \"all\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
smolagents>=1.26.0; extra == "all"runtime
autogen-agentchat
Environment
{
  "extras": "",
  "marker": "extra == \"autogen\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
autogen-agentchat>=0.7.5; extra == "autogen"runtime
autogen-ext
Environment
{
  "extras": "openai",
  "marker": "extra == \"autogen\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
autogen-ext[openai]>=0.7.5; extra == "autogen"runtime
crewai
Environment
{
  "extras": "",
  "marker": "extra == \"crewai\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
crewai>=1.6.1; extra == "crewai"runtime
asyncpg
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
asyncpg>=0.29; extra == "dev"runtime
hypothesis
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
hypothesis>=6.100; extra == "dev"runtime
mypy
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
mypy>=1.10; extra == "dev"runtime
pytest-cov
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
pytest-cov>=5.0; extra == "dev"runtime
pytest
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
pytest>=8.0; extra == "dev"runtime
ruff
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
ruff>=0.5; extra == "dev"runtime
types-pyyaml
Environment
{
  "extras": "",
  "marker": "extra == \"dev\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
types-pyyaml>=6.0; extra == "dev"runtime
langchain-core
Environment
{
  "extras": "",
  "marker": "extra == \"langgraph\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
langchain-core>=1.5.4; extra == "langgraph"runtime
langgraph
Environment
{
  "extras": "",
  "marker": "extra == \"langgraph\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
langgraph>=1.2.11; extra == "langgraph"runtime
litellm
Environment
{
  "extras": "",
  "marker": "extra == \"litellm\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
litellm>=1.96.2; extra == "litellm"runtime
llama-index-core
Environment
{
  "extras": "",
  "marker": "extra == \"llamaindex\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
llama-index-core>=0.14.23; extra == "llamaindex"runtime
llama-index-llms-openai
Environment
{
  "extras": "",
  "marker": "extra == \"llamaindex\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
llama-index-llms-openai>=0.7.10; extra == "llamaindex"runtime
openai
Environment
{
  "extras": "",
  "marker": "extra == \"llm\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
openai>=1.30; extra == "llm"runtime
fastmcp
Environment
{
  "extras": "",
  "marker": "extra == \"mcp\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
fastmcp>=3.4; extra == "mcp"runtime
mcp
Environment
{
  "extras": "",
  "marker": "extra == \"mcp\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
mcp>=1.28; extra == "mcp"runtime
openai-agents
Environment
{
  "extras": "",
  "marker": "extra == \"openai-agents\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
openai-agents>=0.20.0; extra == "openai-agents"runtime
asyncpg
Environment
{
  "extras": "",
  "marker": "extra == \"postgres\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
asyncpg>=0.29; extra == "postgres"runtime
pydantic-ai
Environment
{
  "extras": "",
  "marker": "extra == \"pydanticai\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
pydantic-ai>=2.28.0; extra == "pydanticai"runtime
smolagents
Environment
{
  "extras": "",
  "marker": "extra == \"smolagents\"",
  "requires_python": ">=3.11",
  "evaluation": "NOT_EVALUATED"
}
smolagents>=1.26.0; extra == "smolagents"runtime

Distribution files

2 collected
agent_tooltrust-0.2.0-py3-none-any.whl

bdist_wheel · 194 KB · Python py3

Source file
agent_tooltrust-0.2.0.tar.gz

sdist · 991.58 KB · Python source

Source file

Repository

PENDING
deghosal-2026/agent-tooltrust

Shared repository data · GitHub

License detected in repository
Not collected

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 23:34 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package_version:eac3c0809360397d0cafcd343d2772ba4a87b33c57ac36cfac443127ebfb4bd0

Other collected versions

View all collected versions →