Catalog PyPI
PACKAGE EXPLORERView in registry

aegis-llm

PyPI

Pluggable multi-layer LLM jailbreak defense pipeline

ai-safetyguardrailsjailbreakllmsecurity
Versions collected1
Direct dependencies2From release 0.1.3
Last observed20 Oct, 20:17 UTC

README

Version 0.1.3 documentation

aegis-llm

A pluggable, multi-layer LLM jailbreak defense pipeline for Python. Drop it into any codebase — framework-agnostic, provider-agnostic, zero mandatory dependencies.

Install

pip install aegis-llm

Or from source:

git clone https://github.com/your-org/aegis-llm
cd aegis-llm
pip install -e .

Quickstart

from aegis import Decision, Request, SplitPipeline
from aegis.layers import (
    AuditLogger, InputValidation, OutputFilter,
    RateLimiter, ToolAccess,
)

pipeline = SplitPipeline(
    pre=[
        InputValidation(),
        ToolAccess(role_tool_map={
            "admin":  ["query", "create", "delete"],
            "viewer": ["query"],
        }),
        RateLimiter(max_requests=20, window_seconds=60),
    ],
    post=[
        OutputFilter(),
        AuditLogger(sink=print),
    ],
)

request = Request(user_id="u1", message="Show tasks", user_role="viewer")

# Phase 1 — before your LLM call
pre = pipeline.run_pre(request)
if pre.decision == Decision.BLOCK:
    raise Exception(pre.layer_results[-1].block_reason)

# Your LLM call — any provider
allowed_tools = pre.context.get("available_tools", [])
llm_response = your_llm(request.message, tools=allowed_tools)

# Phase 2 — after your LLM call
post = pipeline.run_post(request, llm_response, pre)
final = post.context.get("filtered_response", llm_response)

How it works

Every request flows through a Pipeline — an ordered list of Layers. The pipeline short-circuits on the first BLOCK, so nothing downstream runs on a rejected request.

Request → Layer 1 → Layer 2 → ... → PipelineResult
              ↓
           BLOCK → return immediately

SplitPipeline splits this at the LLM boundary: pre-phase layers run before your model call, post-phase layers run after. Your code owns the LLM invocation; aegis owns the gating on either side.

Built-in layers

LayerPhaseWhat it does
InputValidationpreRegex/keyword blocklist — blocks naive injection attempts
SemanticRouterpreIntent classifier gate — plug in any classifier callable
ToolAccesspreRBAC — filters the tool schema to what the user's role permits
RateLimiterpreSliding-window quota per user — pluggable backend (Redis, etc.)
OutputFilterpostScans LLM response for internal disclosure, redacts or blocks
AuditLoggerpostStructured audit record — plug in any sink (CloudWatch, Datadog, etc.)

Writing a custom layer

Subclass Layer and implement one method:

from aegis import Layer
from aegis.models import Decision, LayerResult

class TenantIsolation(Layer):
    def process(self, request, context):
        if request.metadata.get("tenant_id") != context.get("expected_tenant"):
            return LayerResult(
                decision=Decision.BLOCK,
                layer_name=self.name,
                block_reason="tenant_mismatch",
            )
        return LayerResult(decision=Decision.PASS, layer_name=self.name)

Drop it anywhere in the pipeline:

from aegis import Pipeline
from aegis.layers import InputValidation, ToolAccess

Pipeline([InputValidation(), TenantIsolation(), ToolAccess(...)])

SemanticRouter — bring your own classifier

from aegis.layers import SemanticRouter

def my_classifier(message: str) -> tuple[str, float]:
    # call sklearn, HuggingFace, an LLM, anything
    return "task_query", 0.92

SemanticRouter(
    classifier=my_classifier,
    allowed_intents=["task_query", "task_create"],
    confidence_threshold=0.75,
)

RateLimiter — pluggable backend

The default backend is in-memory. For multi-process deployments, implement RateLimitBackend:

from aegis.layers.rate_limiter import RateLimitBackend, RateLimiter

class RedisBackend(RateLimitBackend):
    def get_timestamps(self, user_id): ...
    def record_request(self, user_id, timestamp): ...
    def evict_before(self, user_id, cutoff): ...

RateLimiter(max_requests=10, window_seconds=60, backend=RedisBackend())

AuditLogger — pluggable sink

from aegis.layers import AuditLogger

# CloudWatch, Datadog, S3, database — anything callable
AuditLogger(sink=lambda record: my_logger.info(record))

Running tests

pip install -e ".[dev]"
pytest

Downloads & popularity

Awaiting observations

No metric observations yet

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

Versions 1

Collected releases
VersionPublishedDirect dependenciesOpen version
0.1.322 Jun 20262

Package advisories

0
No matching advisories collected

This describes our collected data; it is not a security assessment.

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 20:17 UTC

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

Record identity

package:c1430ad1b2e2fab2a274de9d65dcc252f872277b8a509d836bfa2ad35f237a8e