AI agent security middleware — policy-enforced tool call interception
Project description
███╗ ███╗███████╗ ██████╗ ███████╗███╗ ██╗████████╗
████╗ ████║██╔════╝██╔════╝ ██╔════╝████╗ ██║╚══██╔══╝
██╔████╔██║█████╗ ██║ ███╗█████╗ ██╔██╗ ██║ ██║
██║╚██╔╝██║██╔══╝ ██║ ██║██╔══╝ ██║╚██╗██║ ██║
██║ ╚═╝ ██║███████╗╚██████╔╝███████╗██║ ╚████║ ██║
╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚══════╝╚═╝ ╚═══╝ ╚═╝
Security middleware for AI agents. One decorator. Zero blind spots.
The Problem
AI agents are calling tools. Most of those calls look harmless. But sequences don't lie.
agent.read_file("/etc/passwd") ← looks fine
agent.web_search("paste.bin upload") ← looks fine
agent.http_post("https://...") ← looks fine
# combined? that's data exfiltration.
Traditional security tools inspect calls one by one. Megent watches the sequence.
How It Works
Megent sits between your agent and its tools, running every call through three primitives:
┌─────────────────────────────────────────────────────┐
│ AGENT RUNTIME │
│ │
│ tool_call() ──► [ INTERCEPT ] ──► [ CONTEXT ] │
│ │ │
│ [ JUDGE ] │
│ │ │
│ allow / deny / modify │
└─────────────────────────────────────────────────────┘
| Primitive | Role |
|---|---|
| Intercept | Hooks into every tool invocation before execution |
| Context | Maintains a behavioral window — the sequence of recent calls |
| Judge | Evaluates the sequence against your policy rules |
Install
pip install megent
Quickstart
Drop-in decorator
import mgnt
@mgnt.guard(policy="policies/agent.yaml")
def run_agent():
agent.run("Summarize the latest reports and email them to the team.")
Wrap an existing agent
import mgnt
safe_agent = mgnt.wrap(
agent,
policy="policies/agent.yaml",
identity="reports-agent-v2"
)
safe_agent.run("Summarize the latest reports and email them.")
That's it. Megent intercepts every tool call, evaluates it against your policy, and either allows, denies, or modifies it — all without changing your agent code.
Policy Language
Policies are plain YAML. No DSL to learn.
# policies/agent.yaml
version: "1"
default: deny # deny-by-default
rules:
- name: block_data_exfiltration
description: Detect read → search → post sequences
sequence:
- tool: file_read
match: { path: "/etc/*" }
- tool: web_search
within: 5 # within 5 calls
- tool: http_post
within: 3
action: deny
alert: true
- name: mask_pii_in_emails
tool: send_email
transform:
body:
- mask: email
- mask: phone
- mask: ssn
action: allow
- name: allow_approved_tools
tools: [web_search, read_file, send_slack_message]
action: allow
AgentPassport
Every agent gets a cryptographic identity. Every call is attributed.
passport = mgnt.AgentPassport(
agent_id="reports-agent-v2",
permissions=["file_read", "web_search", "send_email"],
ttl=3600
)
safe_agent = mgnt.wrap(agent, passport=passport)
AgentPassport issues a signed JWT per session. Any call made outside the declared permissions is denied — even if the policy file would otherwise allow it.
Audit Log
Every decision is logged in structured JSON.
{
"ts": "2025-11-12T14:23:01Z",
"agent": "reports-agent-v2",
"tool": "http_post",
"sequence": ["file_read", "web_search", "http_post"],
"rule_triggered": "block_data_exfiltration",
"action": "deny",
"payload_hash": "sha256:e3b0c4..."
}
Pipe to any SIEM. Query with any log tool.
Framework-agnostic
Megent is not a plugin for LangChain, CrewAI, or any other framework. It is an independent security layer.
You build your agent on whatever platform you want. Megent wraps it.
┌──────────────────────────────────────┐
│ MEGENT │ ← security layer (this is us)
│ ┌────────────────────────────────┐ │
│ │ your agent (LangChain, │ │ ← built on any framework
│ │ CrewAI, OpenAI Agents SDK, │ │
│ │ raw Python, anything) │ │
│ └────────────────────────────────┘ │
└──────────────────────────────────────┘
Megent doesn't know or care what your agent is built on. It intercepts tool calls at the boundary — before execution — regardless of the underlying platform.
# agent built on LangChain? wrap it.
safe_agent = mgnt.wrap(langchain_agent, policy="policies/agent.yaml")
# agent built on CrewAI? wrap it.
safe_agent = mgnt.wrap(crew, policy="policies/agent.yaml")
# raw Python agent? same thing.
safe_agent = mgnt.wrap(my_agent, policy="policies/agent.yaml")
The platforms (LangChain, CrewAI, OpenAI Agents SDK, AutoGen, LlamaIndex) are where agents are built. Megent is where they are secured. These are separate concerns.
Threat Coverage
| Attack | Megent Defense |
|---|---|
| Tool call injection | Intercept layer validates call structure |
| Context poisoning | Context window detects anomalous drift |
| Prompt injection → privilege escalation | Sequence analysis flags lateral movement |
| PII leakage | Transform rules mask before execution |
| Shadow tool calls | Deny-by-default blocks undeclared tools |
Contributing
Megent is Apache 2.0 licensed and open to contributions.
git clone https://github.com/getmegent/megent
cd megent
pip install -e ".[dev]"
pytest
See CONTRIBUTING.md for guidelines.
License
Apache 2.0 — free to use, modify, and distribute.
Built for production AI. Designed for developers who ship.
Project details
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 megent-0.1.4.tar.gz.
File metadata
- Download URL: megent-0.1.4.tar.gz
- Upload date:
- Size: 24.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
63fb9e429513d84fa9fd78b3dec9a0843de93ba774208cdfdc9bb541636ad4cc
|
|
| MD5 |
e25ff4ce7c82c492c87278b5b63b4347
|
|
| BLAKE2b-256 |
c6bbc5ff5d4908db1349cbd47be05215c044c4da235514e91d95c157197834e8
|
File details
Details for the file megent-0.1.4-py3-none-any.whl.
File metadata
- Download URL: megent-0.1.4-py3-none-any.whl
- Upload date:
- Size: 22.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
56a737b8f5642b46c4dca1f09e1fdc61193759620989ad84c6664b110b603282
|
|
| MD5 |
0adfa9f23a0735dc4a52877c6d8f92b9
|
|
| BLAKE2b-256 |
ee39cc0763129275457965c7a0941beaafbe2b7d9c11b6776b65c6fe427f8038
|