AI Agent Action Firewall core SDK
Project description
agsec
An action firewall for AI agents. Before an agent can do anything in the real world, it must pass through agsec.
Agent wants to act --> agsec evaluates policy --> allow / block / review --> real world
The Problem
AI agents interact with the real world — shell commands, file writes, API calls, payments. Each platform handles safety differently: some have permission prompts, some have sandboxes, some have nothing. But none offer:
- Declarative, auditable policies — like AWS IAM, but for agent actions
- Consistent rules across platforms — same policies for Claude Code, Codex, or your custom agent
- Granular control — not just "allow bash" or "block bash", but "block bash commands matching this pattern when this condition is true"
- Audit trail — who did what, when, and what policy applied
Built-in controls are binary (allow/block) and platform-specific. Teams running agents in production need policy-as-code with full visibility.
The Solution
agsec is an IAM-style policy engine for agent actions. Define what's allowed, what's blocked, and what needs human review — in YAML files, like AWS IAM policies.
# policies/02_bash.yaml
version: "1.0"
default: deny
statements:
- sid: "BlockFileDelete"
effect: deny
actions: ["bash.execute"]
conditions:
params.command:
op: "regex"
value: "\\brm\\s"
reason: "Agents should not delete files"
- sid: "AllowBash"
effect: allow
actions: ["bash.execute"]
Deny always wins. Just like IAM.
Quick Start
Install
pip install agsec
1. Initialize policies
agsec init
Creates a policies/ directory with 5 default safety policies:
policies/
01_base.yaml # Default deny, allow reads
02_bash.yaml # Block rm, DROP TABLE, secret access
03_files.yaml # Block writes to .env, system dirs
04_web.yaml # Review external HTTP requests
05_git.yaml # Block force push, protected branches
2. Hook into your agent
# Claude Code
agsec install claude-code
# OpenAI Codex
agsec install codex
That's it. The firewall is active. Every tool call is checked against your policies.
3. Manage policies
# List all active policies
agsec policy list
# Add a new policy interactively
agsec policy add
# Remove a policy
agsec policy remove BlockFileDelete
# Validate policy files
agsec validate
4. View audit logs
# Recent actions
agsec audit
# Summary stats
agsec audit --stats
How It Works
Runtime Enforcement
agsec integrates at the runtime level of supported agent platforms. Every action the agent attempts — shell commands, file writes, web requests, API calls — is intercepted and evaluated against your policies before execution.
The agent cannot bypass the firewall. Enforcement happens outside the agent's control.
Supported platforms:
- Claude Code
- OpenAI Codex
- Any agent via the Python SDK
IAM-Style Policy Evaluation
Evaluation order (same as AWS IAM):
- Explicit deny always wins — if any deny rule matches, action is blocked
- Review trumps allow — if a review rule matches, action needs human approval
- Explicit allow — if an allow rule matches, action proceeds
- Default policy — if nothing matches, fall back to default (deny recommended)
Policy Format
Policies are YAML files in a policies/ directory. All files are loaded and merged automatically.
Full Schema
version: "1.0"
default: deny # deny | allow
statements:
- sid: "UniqueId" # Statement ID (for audit trail)
effect: deny # deny | allow | review
actions: # Glob patterns
- "bash.execute"
- "file.write"
- "payment.*"
- "*.delete"
conditions: # Optional — when to apply
params.amount:
op: ">"
value: 10000
context.user_role:
op: "=="
value: "admin"
match: all # all | any (condition logic)
reason: "Human-readable explanation"
Action Names
agsec uses a consistent naming scheme for actions:
| Action | What It Covers |
|---|---|
bash.execute |
Shell commands |
file.write |
File creation |
file.edit |
File modification |
file.read |
File reading |
web.fetch |
HTTP requests |
web.search |
Web searches |
file.glob |
File pattern search |
file.grep |
Content search |
agent.spawn |
Sub-agent creation |
mcp.* |
Any MCP tool calls |
Use glob patterns in policies: payment.*, *.delete, mcp.slack.*
Condition Operators
| Operator | Description | Example |
|---|---|---|
== |
Equals | value: "admin" |
!= |
Not equals | value: "guest" |
> < >= <= |
Comparison | value: 10000 |
in |
In list | value: ["US", "UK"] |
not_in |
Not in list | value: ["KP", "IR"] |
contains |
Substring match | value: ".env" |
starts_with |
Prefix match | value: "https://api." |
ends_with |
Suffix match | value: ".com" |
regex |
Regex match | value: "rm\\s+-rf" |
exists |
Field is present | (no value needed) |
not_exists |
Field is absent | (no value needed) |
Deep Nested Access
Access nested fields with dot notation:
conditions:
params.recipient.country:
op: "in"
value: ["KP", "IR", "SY"]
context.request.headers.origin:
op: "ends_with"
value: ".internal.com"
SDK Usage (Programmatic)
Use agsec directly in your Python code, without the CLI:
from agsec import ControlLayer
# Load policies from directory
control = ControlLayer(policy_dir="./policies/")
# Register actions
@control.register_action("payment.charge")
async def charge(amount, recipient):
return {"charged": amount, "to": recipient}
# Execute with policy enforcement
result = await control.execute(
"payment.charge",
{"amount": 500, "recipient": {"country": "US"}},
context={"user_role": "agent"}
)
print(result.policy.status) # PolicyStatus.ALLOW
print(result.result) # {"charged": 500, "to": {"country": "US"}}
Sync Usage
result = control.execute_sync("payment.charge", {"amount": 500, ...})
Dry Run (Check Without Executing)
# Async
policy = await control.dry_run("payment.charge", {"amount": 50000})
print(policy.status) # PolicyStatus.REVIEW
print(policy.reason) # "Large payments require review"
# Sync
policy = control.dry_run_sync("payment.charge", {"amount": 50000})
Hooks (Before/After Execution)
control = ControlLayer(policy_dir="./policies/")
@control.before_hook
def log_action(action, params, context):
print(f"About to execute: {action}")
@control.after_hook
def log_result(exec_result):
print(f"Result: {exec_result.result}")
Policy Engine Direct Access
from agsec.policy import PolicyEngine
engine = PolicyEngine()
engine.load_from_directory("./policies/")
# Evaluate
result = engine.evaluate("bash.execute", {"command": "rm -rf /"})
print(result.status) # PolicyStatus.BLOCK
print(result.reason) # "Agents should not delete files"
print(result.metadata["sid"]) # "BlockFileDelete"
print(result.metadata["matched_by"]) # "explicit_deny"
# Validate policies without loading
issues = engine.validate_directory("./policies/")
Audit Store
from agsec.audit import AuditStore
audit = AuditStore("./audit.db")
# Query logs
executions = audit.get_executions(action="payment.charge", limit=50)
# Get stats
stats = audit.get_execution_stats()
# {"total_executions": 142, "allowed": 100, "blocked": 30, "reviewed": 12, "errors": 0}
# Export
audit.export_to_json("audit_export.json")
CLI Reference
| Command | Description |
|---|---|
agsec init |
Create policies/ with default safety policies |
agsec policy list |
List all active policy statements |
agsec policy add |
Add a new policy (interactive) |
agsec policy remove <sid> |
Remove a policy by statement ID |
agsec validate [path] |
Validate policy files for errors |
agsec install claude-code |
Activate firewall for Claude Code |
agsec install codex |
Activate firewall for OpenAI Codex |
agsec audit |
View recent audit logs |
agsec audit --stats |
View summary statistics |
Default Policies
agsec init ships with these out of the box:
01_base.yaml - Default deny. Allow read operations and agent spawning.
02_bash.yaml - Block rm (all forms), DROP TABLE, TRUNCATE, secret access via cat .env, data exfiltration via curl --data. Allow other bash.
03_files.yaml - Block writes to .env, credentials.json, secrets.yaml, .ssh/, .aws/credentials, system directories (/etc/, /usr/). Allow other writes.
04_web.yaml - Review all external HTTP fetches. Allow localhost. Allow web search.
05_git.yaml - Block git push --force, push to main/master/production, git reset --hard, git clean -f.
Contributing
git clone https://github.com/riyandhiman14/Agent-Sec.git
cd agsec
pip install -e ".[dev]"
pytest
License
Apache 2.0 — see LICENSE for details.
Project details
Release history Release notifications | RSS feed
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 agsec-0.1.4.tar.gz.
File metadata
- Download URL: agsec-0.1.4.tar.gz
- Upload date:
- Size: 43.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ef03364dc60bf0a29601ab0fff8e5b2aafc6a74dd6ddfe53093d534dce5bf1a2
|
|
| MD5 |
63a709db7ab6d0c3e091239ef65d69d8
|
|
| BLAKE2b-256 |
49451d011e08d721552c8270ee77d02991dcee826226169e8ac2b3330978e841
|
File details
Details for the file agsec-0.1.4-py3-none-any.whl.
File metadata
- Download URL: agsec-0.1.4-py3-none-any.whl
- Upload date:
- Size: 50.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3de005f995fcb2b7ed6167fa3897e49033a8daf3c7fc966170321acbd1e46000
|
|
| MD5 |
4122f41fe478a860256aa80f60cd3408
|
|
| BLAKE2b-256 |
fe4bc370320ab8adb2e6c32e8a6d1634c45798e3544ec463347990278b97ac3a
|