Observed since 21 Oct, 08:55 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
A lightweight safety, approval, audit, replay, and rollback layer for AI agent tools
Safety middleware for AI agent tool calls, available for Python and TypeScript.
Agents routinely execute shell commands, write files, mutate databases, and call authenticated APIs. Most tool-use stacks pass those calls directly to application code. agentwall adds a small interception layer that classifies each call, requests approval when required, emits a structured event, and registers an optional rollback.
from agentwall import Agentwall, BlockedError
wall = Agentwall()
@wall.tool("bash")
def bash(command: str) -> str:
return f"executed: {command}"
try:
bash("rm -rf /tmp/build-cache")
except BlockedError:
print("blocked")
# The destructive call runs only after terminal approval.
Python 3.9+:
pip install agentwall-sdk
Node.js 18+:
npm install agentwall-sdk
The core packages have no runtime dependencies. Framework clients are optional.

Decorate an existing tool, or execute a ToolSpec inside a rollback-capable session:
from pathlib import Path
from agentwall import Agentwall, ToolSpec
wall = Agentwall() # loads ./agentwall.yaml
def write_file(path: str, content: str) -> str:
Path(path).write_text(content)
return path
def remove_file(path: str, content: str) -> None:
Path(path).unlink(missing_ok=True)
with wall.session(agent_id="worker-1") as session:
session.call(
ToolSpec("write_file", write_file, remove_file),
path="result.txt",
content="done",
)
If the session exits with an exception, successful calls with rollback functions are compensated in reverse order. Normal exit commits the session.
Adapters accept the native OpenAI, Anthropic, and LangChain tool-call shapes:
from agentwall.integrations import (
execute_anthropic_tool_use,
execute_openai_tool_call,
wrap_langchain_tool,
)
result = execute_openai_tool_call(tool_call, tools_by_name, wall)
result = execute_anthropic_tool_use(tool_use, tools_by_name, wall)
guarded_tool = wrap_langchain_tool(langchain_tool, wall)
import { Agentwall } from "agentwall-sdk";
const wall = new Agentwall();
const guarded = wall.wrap("bash", async ({ command }) => {
return runCommand(String(command));
});
await guarded({ command: "rm -rf /tmp/build-cache" });
executeOpenAIToolCall, executeAnthropicToolUse, and wrapLangChainTool are exported from the TypeScript package.
Each call is classified as:
| Level | Typical actions | Default behavior |
|---|---|---|
safe | reads, searches, read-only SQL | execute |
cautious | file writes, unauthenticated mutations | execute and log |
destructive | destructive SQL or shell commands, authenticated mutations | require approval |
Terminal approval is fail-closed. WebhookApproval posts the tool name, arguments, and classification to an HTTP endpoint and accepts only a successful response containing {"approved": true}.
agentwall reads one agentwall.yaml from the working directory. Set AGENTWALL_CONFIG to use another YAML or JSON file.
approval:
levels: ["destructive"]
logging:
sink: file
path: .agentwall/events.jsonl
webhook:
url: null
timeout_seconds: 30
default_classification: safe
redact_keys: ["authorization", "api_key", "token", "password", "secret"]
rules:
- name: destructive-shell
classification: destructive
tool_pattern: "(?i)^(bash|shell|terminal)$"
argument_pattern: "(?i)(rm\\s+-rf|mkfs|shutdown)"
- name: file-writes
classification: cautious
tool_pattern: "(?i)(write|save|patch)_file"
Rules are evaluated in order; the first complete match wins.
| Key | Type | Default | Description |
|---|---|---|---|
approval.levels | list | ["destructive"] | Classifications requiring approval |
logging.sink | file or stdout | file | Built-in event destination |
logging.path | string | .agentwall/events.jsonl | JSONL path for the file sink |
webhook.url | string or null | null | Synchronous approval endpoint |
webhook.timeout_seconds | number | 30 | Approval request timeout |
default_classification | classification | safe | Result when no rule or built-in matches |
redact_keys | list | common credential keys | Keys recursively redacted from logs |
rules[].name | string | required | Stable rule name |
rules[].classification | classification | required | Result for a matching rule |
rules[].tool_pattern | regex | .* | Tool-name matcher |
rules[].argument_pattern | regex | unset | Matcher applied to serialized arguments |
rules[].methods | list | [] | Optional HTTP method matcher |
Environment overrides:
| Variable | Purpose |
|---|---|
AGENTWALL_CONFIG | Config file path |
AGENTWALL_APPROVAL_LEVELS | Comma-separated approval levels |
AGENTWALL_DEFAULT_CLASSIFICATION | Default classification |
AGENTWALL_LOG_SINK | file or stdout |
AGENTWALL_LOG_PATH | JSONL output path |
AGENTWALL_WEBHOOK_URL | Approval endpoint |
AGENTWALL_WEBHOOK_TIMEOUT_SECONDS | Approval timeout |
AGENTWALL_REDACT_KEYS | Comma-separated keys to redact |
The dependency-free YAML reader supports mappings, nested mappings, scalar lists, and lists of mappings. It does not support anchors, tags, or multiline scalars.
Dry-run approved, successful calls in log order:
agentwall replay .agentwall/events.jsonl
Execution replay requires an explicit ReplayRegistry containing sandbox-safe implementations:
agentwall replay .agentwall/events.jsonl --execute --module sandbox_tools
See CONTRIBUTING.md.
Apache-2.0
Download counts and popularity will appear here as the collector receives them.
| Version | Published | Direct dependencies | Open version |
|---|---|---|---|
| 0.1.0 | 7 Sept 2026 | 6 |
This describes our collected data; it is not a security assessment.
Observed since 21 Oct, 08:55 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:5d5ef3af65cee0e33fa69327c39a7e20631dcde7c4517e49236e0482dada5ef5