Skip to main content

🧀 Qise

AI-First Runtime Security Framework for AI Agents

Python 3.11+ License: CC BY-NC-SA 4.0 Tests: 461+ passed Guards: 14 Adapters: 5 Desktop: Tauri 2

English | 中文


Overview

Qise (pronounced "Cheese" 🧀) is an open-source runtime security framework that protects AI agents from both directions:

  • World → Agent: Stops prompt injection, tool poisoning, memory/KB tampering, and supply chain attacks
  • Agent → World: Stops dangerous commands, path traversal, SSRF, data exfiltration, and policy violations

Unlike rule-only solutions that are easily bypassed, Qise uses layered AI models (SLM fast-screen + LLM deep analysis) to understand attack intent, with deterministic rules as fast-path and fallback — never fail-open.

System Architecture

Agent (Claude Code / Codex / Gemini CLI / Custom)
    │
    │ API Request (OpenAI-compatible format)
    ▼
┌─────────────────────────────────────────────────────────┐
│                Tauri 2 Desktop App                       │
│  ┌───────────────────────────────────────────────────┐  │
│  │  System Tray │ Guard Dashboard │ Config Editor    │  │
│  │  Agent Panel │ Event Log (WS)  │ Stats Bar        │  │
│  └───────────────────────────────────────────────────┘  │
├─────────────────────────────────────────────────────────┤
│  Rust Proxy (axum, port 8822)                           │
│  • Request/Response interception                        │
│  • SSE streaming passthrough                            │
│  • Guard pipeline integration                           │
│  • Proxy Takeover (env + config file)                   │
├─────────────────────────────────────────────────────────┤
│  Python Bridge (aiohttp, port 8823)                     │
│  • Guard Pipeline execution                             │
│  • SLM/LLM inference (httpx)                            │
│  • WebSocket event push (/v1/bridge/events/stream)      │
│  • 7 HTTP endpoints + 1 WS endpoint                     │
├─────────────────────────────────────────────────────────┤
│  Guard Pipeline (14 Guards)                             │
│  Ingress: Prompt → ToolSanity → Context → SupplyChain  │
│  Egress:  Command → FS → Network → Exfil → Resource    │
│  Output:  Credential → Audit → Output                   │
│  Soft:    SecurityContextProvider + ReasoningGuard       │
├─────────────────────────────────────────────────────────┤
│  Model Layer                                            │
│  SLM: Ollama qwen3:4b (local, <2s)                     │
│  LLM: Cloud API (Claude/GPT/Qwen, <5s)                  │
│  Rules: Deterministic fallback (<1ms)                    │
└─────────────────────────────────────────────────────────┘
    │
    │ Forwarded Request
    ▼
  Upstream LLM API

Quick Start

1. Install Python Engine

# Clone and install
git clone https://github.com/morinop/qise.git
cd qise
pip install -e ".[dev]"

2. One-Command Setup

# Generate default config
qise init

# Check a tool call
qise check bash '{"command": "rm -rf /"}'
# → {"verdict": "block", "blocked_by": "command", ...}

qise check bash '{"command": "ls"}'
# → {"verdict": "pass", "blocked_by": null, "warnings": []}

# List all guards and their modes
qise guards

3. Setup Local SLM (Recommended)

Qise works out-of-the-box with rules only, but AI-first guards need an SLM. Local Ollama gives <2s latency:

# One-click: install Ollama + pull qwen3:4b (~2.4GB)
chmod +x scripts/setup_slm.sh
./scripts/setup_slm.sh

Or manually:

curl -fsSL https://ollama.com/install.sh | sh
ollama pull qwen3:4b
ollama serve

Then configure shield.yaml:

models:
  slm:
    base_url: "http://localhost:11434/v1"
    model: "qwen3:4b"
    timeout_ms: 5000

4. Zero-Code: Proxy Mode

Start a local HTTP proxy that intercepts all Agent↔LLM traffic:

# Start proxy server
qise proxy start --port 8822 --upstream https://api.openai.com

# Point your agent at the proxy
export OPENAI_API_BASE="http://localhost:8822/v1"

The proxy intercepts requests/responses in real-time, running all 14 guards on tool calls, injection attempts, and output leaks — with SSE streaming support for zero-latency text passthrough.

5. Desktop App (One-Click Security)

The Qise desktop app provides a one-click security toggle with real-time monitoring:

# Prerequisites: Node.js + Rust
cd src-tauri && cargo tauri dev

Features:

  • System Tray: One-click protection toggle, status indicator, menu text auto-switches
  • Guard Dashboard: Real-time guard events, mode switching (observe/enforce/off)
  • Config Editor: Visual shield.yaml editing (SLM, LLM, Guards, Integration)
  • Agent Panel: Detect installed agents, one-click proxy takeover with crash recovery
  • Event Log: WebSocket real-time push, filter by All/Blocked/Warnings
  • Stats Bar: Blocked/warning counts, SLM status (local/cloud/unavailable), latency

Proxy Takeover: Click "Take Over" to redirect your agent's API endpoint to the Qise proxy. Original config is backed up and auto-restored on exit or crash.

Agent Method Redirect Target
Generic OpenAI OPENAI_API_BASE env var http://localhost:8822/v1
Claude Code ANTHROPIC_BASE_URL env var + ~/.claude/settings.json http://localhost:8822/v1

6. Zero-Code: MCP Mode

Add to your agent's MCP configuration:

{
  "mcpServers": {
    "qise": {
      "command": "python",
      "args": ["-m", "qise.mcp_server"]
    }
  }
}

7. SDK Mode: Framework Adapters

Nanobot:

from qise import Shield
from qise.adapters.nanobot import QiseNanobotHook

shield = Shield.from_config()
hook = QiseNanobotHook(shield)
loop = AgentLoop(hooks=[hook])

LangGraph:

from qise import Shield
from qise.adapters.langgraph import QiseLangGraphWrapper

shield = Shield.from_config()
wrapper = QiseLangGraphWrapper(shield)
safe_tools = [wrapper.wrap_tool_call(tool) for tool in my_tools]

NexAU:

from qise import Shield
from qise.adapters.nexau import QiseNexauMiddleware

shield = Shield.from_config()
middleware = QiseNexauMiddleware(shield)
agent = NexAUAgent(middlewares=[middleware])

OpenAI Agents SDK:

from qise import Shield
from qise.adapters.openai_agents import QiseOpenAIAgentsGuardrails

shield = Shield.from_config()
guardrails = QiseOpenAIAgentsGuardrails(shield)
agent = Agent(guardrails=[guardrails.input_guardrail, guardrails.output_guardrail])

Hermes:

from qise import Shield
from qise.adapters.hermes import QiseHermesPlugin

shield = Shield.from_config()
plugin = QiseHermesPlugin(shield)
plugin.register(ctx)

Why Qise

Problem Qise's Approach
Keyword rules easily bypassed AI understands attack semantics, not just pattern matching
Single model bottleneck Layered models: SLM <50ms fast-screen + LLM deep analysis
Fail-open on model errors Rule fallback — never fail-open
No exfiltration detection ExfilGuard: AI-first data exfiltration detection
No tool poisoning detection ToolSanityGuard: hash baseline + AI semantic analysis
Static safety instructions Dynamic SecurityContextProvider + Guard enforcement
Requires code changes Proxy mode / MCP mode: zero-code integration
Cloud SLM latency 14-30s Local Ollama qwen3:4b: <2s per call

Three-Layer Decision Flow

Every guard uses the same decision flow — rules first for speed, AI for semantics, rules last for safety:

  ┌──────────────────┐
  │ Rule Fast-Path   │  <1ms — deterministic BLOCK or PASS
  │ (regex, hash,    │  e.g., "rm -rf /" → BLOCK
  │  patterns)       │  For AI-first guards, only BLOCK short-circuits
  └────────┬─────────┘  (rule PASS flows to SLM for final say)
           │ uncertain or PASS (AI-first guards)
           ▼
  ┌──────────────────┐
  │ SLM Fast-Screen  │  <2s (local Ollama) — semantic classification
  │ (≤4B model)      │  e.g., obfuscated command → BLOCK
  └────────┬─────────┘  e.g., paraphrased injection → ESCALATE
           │ SLM can override low-confidence rule WARNs (<0.65)
           │ but not high-confidence ones (≥0.65)
           ▼
  ┌──────────────────┐
  │ LLM Deep Analysis│  <2s — full trajectory reasoning
  │ (8B-70B model)   │  e.g., multi-turn attack chain → BLOCK
  └────────┬─────────┘
           │ model unavailable
           ▼
  ┌──────────────────┐
  │ Rule Fallback    │  <1ms — conservative defaults
  │ (never fail-open)│  e.g., WARN on uncertain + network tool
  └──────────────────┘

Defense in Depth

  Layer 0: SecurityContextProvider  →  Agent follows voluntarily (~80%)
  Layer 1: ReasoningGuard          →  Chain-of-thought monitoring + threshold adjustment
  Layer 2: Guard Pipeline (14)     →  Rule → SLM → LLM → Rule fallback
  Layer 3: OutputGuard + CredentialGuard  →  Data leak detection

14 Guards at a Glance

Ingress Pipeline (World → Agent)

Guard Strategy Detects
PromptGuard AI-first (80/20) Indirect injection, multi-turn attacks, context poisoning
ToolSanityGuard AI-first (80/20) Tool description poisoning, rug pulls, name shadowing
ContextGuard AI+hash (70/30) Memory/KB poisoning, data tampering, hash integrity
SupplyChainGuard AI+rules (60/40) Malicious Skills, MCP tampering, source verification

Egress Pipeline (Agent → World)

Guard Strategy Detects
ReasoningGuard * AI-only (100/0) Manipulation traces in chain-of-thought, threshold adjustment
CommandGuard Rules+AI (70/30) Shell injection, dangerous commands, privilege escalation
FilesystemGuard Rules (90/10) Path traversal, workspace violations, system dir access
NetworkGuard Rules (90/10) SSRF, forbidden domains, internal network scanning
ExfilGuard AI-first (80/20) Data exfiltration, covert channels, DNS exfil
ResourceGuard Rules+AI (60/40) Infinite loops, budget overruns, circuit breaker
ToolPolicyGuard Rules (100/0) Unauthorized tool access, deny/approval/owner-only

Output Pipeline (Audit)

Guard Strategy Detects
CredentialGuard Rules (100/0) API keys, secrets, tokens in output
AuditGuard AI+rules (50/50) Attack chain reconstruction, session risk scoring
OutputGuard AI+rules (70/30) PII exposure, KB content leaks, credential leaks

* ReasoningGuard is cross-cutting — detects manipulation in chain-of-thought and adjusts thresholds of other guards.

5 Framework Adapters

Framework Ingress Egress Output SecContext
Nanobot ✅ ✅ ✅ ✅
Hermes ✅ ✅ ✅ —
NexAU ✅ ✅ ✅ ✅
LangGraph — ✅ — ✅
OpenAI Agents ✅ ✅ ✅ —

All adapters use IngressCheckMixin + EgressCheckMixin — no monkey-patching, only official Hook/Plugin/Middleware APIs.

Configuration (shield.yaml)

version: "1.0"

integration:
  mode: proxy          # proxy | mcp | sdk
  proxy:
    port: 8822
    auto_takeover: true
    crash_recovery: true

models:
  slm:
    base_url: "http://localhost:11434/v1"   # Ollama
    model: "qwen3:4b"
    timeout_ms: 5000
  llm:
    base_url: "https://api.anthropic.com"
    model: "claude-sonnet-4-5"
    timeout_ms: 5000

guards:
  enabled: [prompt, command, credential, reasoning, filesystem, network,
            exfil, resource, audit, tool_sanity, context, output, tool_policy, supply_chain]
  config:
    prompt:
      mode: observe           # observe | enforce | off
      slm_confidence_threshold: 0.7
      skip_slm_on_rule_pass: false
    command:
      mode: enforce
    exfil:
      mode: observe
      skip_slm_on_rule_pass: true
      slm_override_rule_warn_threshold: 0.8

Environment variable overrides: QISE_SLM_BASE_URL, QISE_SLM_MODEL, QISE_SLM_API_KEY, QISE_LLM_BASE_URL, QISE_PROXY_PORT, QISE_MODE.

Performance

Operation Target Measured (p95)
Rule fast-path (single guard) <1ms ~0.02ms
Full egress pipeline (6 guards) <10ms ~0.02ms
Local SLM (Ollama qwen3:4b) <2s ~500ms-2s (M1+)
Full pipeline + local SLM <3s ~1-2s

Scripts

Script Description
scripts/setup_slm.sh Install Ollama + pull qwen3:4b (one-click local SLM)
scripts/benchmark_slm.py Compare local Ollama vs cloud SLM latency
scripts/e2e_tauri_test.py End-to-end verification: Proxy → Bridge → Guard → API

Development

pip install -e ".[dev]"     # Install with dev dependencies
pytest tests/ -v             # Run 461+ tests
ruff check .                 # Lint
ruff format .                # Format
mypy src/qise               # Type check
cd src-tauri && cargo tauri dev    # Run desktop app
cd src-tauri && cargo tauri build  # Build desktop app

Evaluation Results

R12-tuned evaluation (SLM + rules pipeline vs rules-only baseline):

Metric Rules-Only SLM + Rules Delta
Precision 0.643 1.000 +0.357
Recall 0.973 1.000 +0.027
F1 0.774 1.000 +0.226
FPR 0.400 0.000 +0.400 (lower=better)

Architecture

qise/
├── src/qise/
│   ├── core/              # GuardContext, AIGuardBase, Pipeline, Shield, Config
│   ├── guards/            # 14 Guard implementations
│   ├── models/            # ModelRouter (httpx-based OpenAI-compatible client)
│   ├── data/              # ThreatPatternLoader + BaselineManager + SQLite
│   ├── providers/         # SecurityContextProvider (DSL template rendering)
│   ├── adapters/          # 5 Framework adapters
│   ├── proxy/             # HTTP proxy server (aiohttp + SSE)
│   ├── bridge/            # Python Bridge (7 HTTP + 1 WS endpoint)
│   └── mcp_server.py      # MCP Server (4 security check tools)
├── src-tauri/             # Desktop App (Tauri 2 + React)
│   ├── src/               #   Rust backend (proxy, bridge, takeover, 12 IPC commands)
│   └── icons/             #   App icons
├── src-ui/                # React frontend (Raycast-style dark UI)
│   └── src/components/    #   StatusIndicator, ProxyToggle, GuardList, EventLog,
│                          #   AgentPanel, ConfigPanel
├── scripts/               # setup_slm.sh, benchmark_slm.py, e2e_tauri_test.py
├── data/                  # threat_patterns/, security_contexts/, prompts/
├── tests/                 # 461+ tests
├── eval/                  # Evaluation datasets and results
└── docs/                  # Architecture, Guards, Threat Model, Integration

CLI Reference

qise check bash '{"command": "rm -rf /"}'  # Single security check
qise serve                                  # Start MCP Server
qise proxy start --port 8822                # Start Rust HTTP proxy
qise bridge start --port 8823               # Start Python Bridge
qise init                                   # Generate shield.yaml
qise guards                                 # List registered guards
qise adapters                               # List framework adapters
qise context bash                           # Get security context
qise version                                # Print version

Integration Modes

Mode Code Required Defense Depth Best For
Proxy Mode 0 lines Full (4 layers) Desktop users, non-developers
MCP Mode 0 lines Hard defense (14 guards) MCP ecosystem users
SDK Mode 1-5 lines Full (4 layers) + lowest latency Agent developers

Status

Component Status
Core engine (AIGuardBase, Pipeline, Shield) ✅ Complete
14 Guards (Ingress + Egress + Output) ✅ Complete
ModelRouter (httpx-based SLM/LLM client) ✅ Complete
Ollama SLM integration (qwen3:4b, <2s) ✅ Complete
Rust Proxy (axum + hyper + rustls, SSE streaming) ✅ Complete
Python Bridge (aiohttp, 7 HTTP + 1 WS endpoint) ✅ Complete
Desktop App (Tauri 2, System Tray, Config Editor) ✅ Complete
Proxy Takeover (env + config file + crash recovery) ✅ Complete
Real-time Frontend (GuardList, EventLog, AgentPanel, ConfigPanel) ✅ Complete
5 Framework Adapters (Nanobot, Hermes, NexAU, LangGraph, OpenAI Agents) ✅ Complete
MCP Server (4 security check tools) ✅ Complete
SecurityContextProvider (DSL template rendering) ✅ Complete
BaselineManager (SHA-256 hash + SQLite) ✅ Complete
461+ unit + integration + performance tests ✅ Complete
OpenAI Agents SDK E2E Test (10/10 passed) ✅ Complete

License

CC BY-NC-SA 4.0 — Free for personal, academic, and non-commercial use. Commercial use requires separate permission.

Metadata

Release files for qise 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for qise 0.2.0
File Size Uploaded
qise-0.2.0.tar.gz 873.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for qise 0.2.0
File Interpreter ABI Platform
qise-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 1.0 MB

Release files / qise-0.2.0.tar.gz

Download URL qise-0.2.0.tar.gz
Size 873.7 kB
Tags Source
SHA-256 checksum
How to use checksums
69a8df51dc89af7d2dc2866b004556ba7143d14921bcd24e4791dd345c55a5a3
BLAKE2b-256 checksum
How to use checksums
baac49ee4921d24e4ad1be5cc1434df98c019d3b7ff688b511568733eb6a896e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 30, 2026.

Transparency log

Release files / qise-0.2.0-py3-none-any.whl

Download URL qise-0.2.0-py3-none-any.whl
Size 138.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
15bed8b0213a2e20fe1f6424f569f36ae983d21f70a9edfb26a22fca9d499590
BLAKE2b-256 checksum
How to use checksums
52f855040fbc62bbc0f59c09b47801b7b6220bcbd835806f7311f07aa78ed169
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 30, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page