Metadata-Version: 2.4
Name: aso-security
Version: 0.1.0
Summary: Security orchestration library for AI agents, memory, tools, and secrets
Author: ASO Contributors
License: Apache-2.0
Project-URL: Homepage, https://github.com/AyoubArdem/ASO
Project-URL: Repository, https://github.com/AyoubArdem/ASO
Project-URL: Documentation, https://github.com/AyoubArdem/ASO/tree/main/docs
Project-URL: Issues, https://github.com/AyoubArdem/ASO/issues
Keywords: ai,security,agents,orchestration,memory,tools,secrets,guardrail,llm
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: cryptography>=42
Provides-Extra: openai
Requires-Dist: openai>=1.0.0; extra == "openai"
Requires-Dist: langchain-openai>=0.2.0; extra == "openai"
Provides-Extra: google
Requires-Dist: google-genai>=0.1.0; extra == "google"
Requires-Dist: langchain-google-genai>=2.0.0; extra == "google"
Provides-Extra: huggingface
Requires-Dist: transformers>=4.0.0; extra == "huggingface"
Requires-Dist: langchain-huggingface>=0.1.0; extra == "huggingface"
Provides-Extra: ollama
Requires-Dist: langchain-ollama>=0.2.0; extra == "ollama"
Provides-Extra: langchain
Requires-Dist: langchain-core>=0.2.0; extra == "langchain"
Provides-Extra: all
Requires-Dist: openai>=1.0.0; extra == "all"
Requires-Dist: langchain-openai>=0.2.0; extra == "all"
Requires-Dist: google-genai>=0.1.0; extra == "all"
Requires-Dist: langchain-google-genai>=2.0.0; extra == "all"
Requires-Dist: transformers>=4.0.0; extra == "all"
Requires-Dist: langchain-huggingface>=0.1.0; extra == "all"
Requires-Dist: langchain-ollama>=0.2.0; extra == "all"
Requires-Dist: langchain-core>=0.2.0; extra == "all"
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: ruff>=0.6.0; extra == "dev"
Requires-Dist: mypy>=1.11.0; extra == "dev"
Requires-Dist: build>=1.2.0; extra == "dev"
Requires-Dist: twine>=5.1.0; extra == "dev"
Dynamic: license-file

# ASO Security: Fail-Closed Protection for AI Agents

ASO is a Python security orchestration library for AI agents, memory systems, tool execution, and secrets. It gives developers a structured, fail-closed boundary for protecting agent workloads before they reach privileged resources.

ASO is designed for projects where an agent can read/write memory, call tools, and access credentials. In those environments, a single prompt classifier is not enough. ASO adds an explicit decision layer that inspects intent, validates context, authorizes access, and quarantines suspicious activity before execution continues.

Source code: [ASO on GitHub](https://github.com/AyoubArdem/ASO)

## Why ASO exists

Modern AI agents often need to:

- read and write memory
- call external tools
- retrieve credentials and tokens
- work with multi-step task flows
- operate in enterprise or production contexts

Without a hardened security boundary, these operations can be abused by prompt injection, unsafe tool invocation, model misalignment, or untrusted memory content.

ASO helps by enforcing a clear policy:

- inspect the request
- validate trusted host context
- authorize the requested resource
- execute only through guarded gateways
- deny or quarantine when the request is suspicious

## Core idea

ASO separates concerns into different application layers:

- Prompt inspection and intent analysis
- Central orchestration and decision handling
- Memory protection
- Tool execution protection
- Secret and credential access control

This design keeps security decisions auditable and avoids trusting agent-controlled request data as proof of authorization.

## Installation

```bash
pip install aso-security
```

Optional integrations:

```bash
pip install "aso-security[openai]"
pip install "aso-security[google]"
pip install "aso-security[huggingface]"
pip install "aso-security[langchain]"
```

## Quick start

```python
from MemoryGuard.config import SecurityContext, StoreConfig, MemoryRequest, Operation
from MemoryGuard.memory_access_layer import StoreRegistry
from DecisionEngine.aso_core import AgentSecurityOrchestrator
from ToolGuard.tool_guard import ToolGuard, ToolRegistry, ToolDefinition
from SecretGuard.config import SecretAccessRequest, SecretSecurityContext, SecretPermissions
from SecretGuard.secret_gateway import SecretBroker

# 1. Memory setup
registry = StoreRegistry()
registry.register(StoreConfig(
    store_id="agent-profile",
    store_type="sqlite",
    provider="sqlite",
    adapter=SQLITE(database_path="agent_memory.db"),
    memory_types=frozenset({"profile"}),
    capabilities=frozenset({"read", "write", "update", "delete"}),
))

memory_context = SecurityContext(
    agent_id="agent-42",
    tenant_id="tenant-7",
    allowed_stores=frozenset({"agent-profile"}),
    permissions=frozenset({"read", "write"}),
    session_id="session-100",
)

# 2. Tool setup

def lookup_ticket(ticket_id: str) -> dict:
    return {"ticket_id": ticket_id, "status": "open"}


tool_registry = ToolRegistry()
tool_registry.register(
    ToolDefinition(
        tool_id="lookup_ticket",
        name="Lookup ticket",
        description="Read a ticket status.",
        purpose="Check the status of a ticket requested by the user.",
        operations=frozenset({"lookup"}),
        allowed_resources=frozenset({"T-100"}),
        output_schema={"type": "object"},
    ),
    lookup_ticket,
)

tool_context = ToolSecurityContext(
    agent_id="agent-42",
    session_id="session-100",
    authorized_tools=frozenset({"lookup_ticket"}),
)

# 3. Secret setup
secret_repo = SecretRepository("secret_guard.db")
secret_vault = SecretVault(secret_repo, LocalDevelopmentKeyManager())
secret_broker = SecretBroker(secret_repo, secret_vault, permissions=SecretPermissions())

secret_context = SecretSecurityContext(
    tenant_id="tenant-7",
    requester="service-account",
    agent_id="agent-42",
    session_id="session-100",
    authorized_tools=frozenset({"lookup_ticket"}),
)

# 4. Orchestrator
orchestrator = AgentSecurityOrchestrator(
    framework=Framework.LANGCHAIN,
    llm="security-model",
    prompt_template="Follow the ASO security policy.",
    M_Definition=memory_context,
    T_Definition=None,
    S_Definition=None,
    memory_access_layer=GuardedMemoryAccessLayer(registry),
    tool_guard=ToolGuard(registry=tool_registry, trusted_context=tool_context),
    secret_broker=secret_broker,
    tool_context=tool_context,
    secret_context=secret_context,
    agent_name="support-agent",
    developer_name="Example Engineering",
    agent_description="Handles support requests using guarded memory, tools, and secrets.",
)

# The orchestrator creates its framework agent during initialization.
agent = orchestrator.agent

# Create another agent explicitly when the application needs one.
another_agent = orchestrator.create_agent(
    agent_name="billing-agent",
    model_name="security-model",
    developer_name="Example Engineering",
    description="Handles billing questions.",
)

# 5. Memory request
memory_result = orchestrator.process(
    MemoryRequest(
        agent_id="agent-42",
        operation=Operation.WRITE,
        store_id="agent-profile",
        payload={"preference": "concise answers"},
        memory_type="profile",
        metadata={"memory_id": "answer-style"},
    ),
    context=memory_context,
)
print(memory_result.decision)

# 6. Tool request
result = orchestrator.process(
    ToolRequest(
        request_id="req-tool-1",
        agent_id="agent-42",
        session_id="session-100",
        task_id="task-1",
        tool_id="lookup_ticket",
        purpose="Read the status of ticket T-100.",
        reason="The user asked for the status of a valid ticket.",
        arguments={"operation": "lookup", "ticket_id": "T-100"},
    ),
    context=tool_context,
)
print(result.decision)
```

## Main library entry points

### `AgentSecurityOrchestrator.process(...)`

This is the primary unified entry point for the ASO runtime. It accepts a typed request and dispatches it to the appropriate guard based on the request type.

Supported request types:

- `MemoryRequest`
- `ToolRequest`
- `SecretAccessRequest`

The orchestrator validates prompt content and trusted host context before dispatching. If the request is suspicious, it returns a deny or quarantine result instead of continuing execution.

### Creating the framework agent

`AgentSecurityOrchestrator` creates its initial framework agent during initialization and exposes it as `orchestrator.agent`. Set `agent_name`, `developer_name`, and `agent_description` to provide its metadata; if omitted, ASO generates a name and uses default metadata. The required `llm` argument supplies the model identifier used to create the framework agent.

Call `orchestrator.create_agent(agent_name, model_name, developer_name, description)` to create an additional agent explicitly. It returns the framework-specific agent and records its metadata. This method does not register tools; register tools separately through `ToolGuard` and provide trusted context for guarded calls.

### `GuardedMemoryAccessLayer.execute(...)`

This is the memory-specific gateway. It ensures:

- the store is known and enabled
- the agent identity matches the trusted context
- the requested memory scope is permitted
- the operation is allowed by both the context and the store configuration
- post-read inspection checks retrieved memory

### `ToolGuard.execute(...)`

This gate protects external tool execution. It verifies:

- the tool is registered
- the request is from a trusted agent/session/tool context
- the operation is declared in the tool definition
- the tool usage is in scope
- the tool result itself is safe before returning it to the agent

### `SecretBroker`

This is the secret/credential gateway. It enforces:

- tenant and agent identity matching
- allowed secret type and destination checks
- purpose-based access policy
- read-only or bounded secret callbacks
- encrypted storage and metadata-only request handling

## Trust boundaries matter

ASO deliberately requires trusted host-created context. This is not a library that trusts the agent to say, "I am authorized". Instead, the application creates and provides the authenticated security context.

Examples of host-controlled values:

- agent ID
- tenant ID
- session ID
- authorized tools
- allowed memory stores
- secret policy metadata

Agent-controlled text is never treated as authorization.

## Guard behavior

ASO uses a fail-closed style of enforcement:

- if prompt inspection fails, the request is blocked
- if the trusted context is missing or mismatched, execution is denied
- if the tool result is suspicious, it is quarantined
- if a secret operation breaks policy, it is denied

A quarantine result means the app should notify a human operator or incident system, because the request or output was not accepted for normal execution.

## Example: memory protection

```python
from MemoryGuard.config import SecurityContext, MemoryRequest, Operation
from MemoryGuard.memory_gateway import GuardedMemoryAccessLayer

context = SecurityContext(
    agent_id="agent-42",
    tenant_id="tenant-7",
    allowed_stores=frozenset({"agent-profile"}),
    permissions=frozenset({"read", "write"}),
    session_id="session-1",
)

request = MemoryRequest(
    agent_id="agent-42",
    operation=Operation.WRITE,
    store_id="agent-profile",
    payload={"preference": "be concise"},
    memory_type="profile",
)

result = GuardedMemoryAccessLayer(registry).execute(request, context)
print(result.decision)
```

## Example: tool protection

```python
from ToolGuard.config import ToolRequest, ToolSecurityContext
from ToolGuard.tool_guard import ToolGuard, ToolRegistry, ToolDefinition

registry = ToolRegistry()


def get_status(ticket_id: str) -> dict:
    return {"ticket_id": ticket_id, "status": "open"}

registry.register(
    ToolDefinition(
        tool_id="get_status",
        name="Status lookup",
        description="Fetch ticket status",
        purpose="Check the user's requested ticket status.",
        operations=frozenset({"lookup"}),
        allowed_resources=frozenset({"T-100"}),
        output_schema={"type": "object"},
    ),
    get_status,
)

context = ToolSecurityContext(
    agent_id="agent-42",
    session_id="session-1",
    authorized_tools=frozenset({"get_status"}),
)

request = ToolRequest(
    request_id="tool-1",
    agent_id="agent-42",
    session_id="session-1",
    task_id="task-1",
    tool_id="get_status",
    purpose="Check the status of the user's ticket.",
    reason="This is required to answer the user request.",
    arguments={"operation": "lookup", "ticket_id": "T-100"},
)

result = ToolGuard(registry=registry, trusted_context=context).execute(request, context)
print(result.decision)
```

## Example: secret protection

```python
from SecretGuard.config import SecretAccessRequest, SecretSecurityContext, SecretPermissions
from SecretGuard.secret_gateway import SecretBroker

context = SecretSecurityContext(
    tenant_id="tenant-7",
    requester="service-account",
    agent_id="agent-42",
    session_id="session-2",
    authorized_tools=frozenset({"get_status"}),
)

request = SecretAccessRequest(
    request_id="secret-1",
    secret_id="secret-abc",
    tenant_id="tenant-7",
    requester="service-account",
    agent_id="agent-42",
    session_id="session-2",
    tool_id="get_status",
    purpose="Run the API call needed for the current user request.",
    operation="read",
    destination="external-api",
)

result = secret_broker.execute_with_secret(
    request,
    context,
    lambda value: "token-ok",
)
print(result)
```

## Production guidance

For production deployment, ASO should be used with:

- authenticated host-side identity
- KMS-backed secret management
- explicit tool registry policies
- explicit tenant/session scoping
- activity logs and audit review
- alerting for quarantined events
- tested security policy defaults

## License

ASO is licensed under the Apache License 2.0.

## Links

- GitHub: https://github.com/AyoubArdem/ASO
- Repository: https://github.com/AyoubArdem/ASO
- PyPI: https://pypi.org/project/aso-security/
