Getting Started with Guard

Runtime security for AI agents. In-process inspection of every message, tool call, and response. Free on all plans.

Onboarding— check off each step as you go
0/4
Most engineers get their first finding in under 4 minutes. Check "Install" to start the clock.
Guard Playground — Live Detection
No install required · runs in-browser
Type a prompt above or click an attack example to see findings appear in real time. Guard detects 12 categories across 67 patterns.
Attack Pattern Library
Click any attack to load it into the detector above
8 examples
Sign in to auto-fill your API key in all code snippets below.Sign in →
Integration Wizard3 questions → your exact code
1
2
3
What SDK are you using?
python-6+9
1 from openai import OpenAI
2
3+from scandar_guard import Guard
4client = OpenAI()
5
6response = client.chat.completions.create(
7+client = OpenAI()
8 model="gpt-4o",
9+guard = Guard(api_key="sk-your-key")
10 messages=[{"role": "user", "content": user_input}],
11+
12)
13+guard.inspect_message(role="user", content=user_input)
14+response = client.chat.completions.create(
15+ model="gpt-4o",
16+ messages=[{"role": "user", "content": user_input}],
17+)
Adding Guard is 2 lines — no changes to your existing LLM calls.

Step-by-step integration

1

Install the SDK

pip install scandar-guard

The SDK is free on all plans and has zero required dependencies. Python ≥ 3.9, Node ≥ 18, Go ≥ 1.21.

2

Wrap your LLM client

Create a Guard instance and pass it your API key. The Guard wraps your existing LLM client — no changes to your model calls required.

from scandar_guard import Guard

guard = Guard(api_key="sk-your-key-here")

# Inspect an incoming user message
result = guard.inspect_message(role="user", content=user_input)

if result.should_block:
    raise ValueError("Injection attempt detected")
3

Inspect every message in your loop

Place Guard calls at every entry point: user messages, tool results, and assistant responses. The session tracker builds context across turns to detect split attacks.

# Full agent loop pattern
session_id = "sess_" + user_id

for turn in conversation:
    # Inspect user message
    result = guard.inspect_message(
        role=turn["role"],
        content=turn["content"],
        session_id=session_id,
    )

    if result.threat_score >= 50:
        log_and_alert(result)
    if result.should_block:
        return {"error": "Request blocked", "findings": result.findings}

    # Call your LLM
    response = llm.chat(turn)

    # Inspect assistant response
    resp_result = guard.inspect_message(
        role="assistant",
        content=response.content,
        session_id=session_id,
    )
4

Inspect tool calls

Tool calls are the #1 runtime injection vector. Guard inspects both the tool name and all arguments before execution.

# Before executing any tool call
tool_result = guard.inspect_tool_call(
    tool_name=tool_name,
    args=tool_args,
    session_id=session_id,
)

if tool_result.should_block:
    return {"error": f"Blocked tool call: {tool_name}"}

# After getting the tool result, inspect the response too
result_check = guard.inspect_tool_result(
    tool_name=tool_name,
    result=tool_output,
    session_id=session_id,
)
Warning
Always inspect tool results from external sources — files, URLs, databases — before feeding them back to the model. Indirect prompt injection via tool results is the most common real-world attack vector.
5

Enable session tracking

Pass a consistent session_id across all calls in a conversation. Guard's multi-turn tracker accumulates context across turns to detect split injection attacks — payloads distributed across multiple messages.

# Use a stable session ID per conversation
guard = Guard(api_key="sk-...", session_id="sess_" + user_id)

# Or pass per-call
result = guard.inspect_message(
    role="user",
    content=message,
    session_id="sess_" + conversation_id,
)

# Access the threat score
print(result.threat_score)         # 0-100
print(result.classification)       # safe | elevated | high | critical
print(result.findings)             # list of findings
print(result.should_block)         # True if any blockOn severity triggered

Advanced Configuration

Custom patterns

Add your own regex patterns to catch domain-specific threats. Custom patterns run alongside all built-in detections.

guard = Guard(
    api_key="sk-...",
    custom_patterns=[
        {
            "pattern": r"internal-system-\d+",
            "severity": "high",
            "category": "INTERNAL_SYSTEM_REF",
            "title": "Internal system reference detected",
            "confidence": 0.85,
        }
    ],
)

Semantic analysis

Enable probabilistic intent scoring to catch obfuscated attacks that evade regex patterns. Semantic analysis runs on the full message and scores intent, not just syntax.

guard = Guard(
    api_key="sk-...",
    semantic_analysis=True,      # adds ~50-100ms per message
    semantic_threshold=0.7,      # flag messages with intent score ≥ 0.7
)

Multi-turn detection

Guard tracks up to 12 messages per session. Split injection attacks — where fragments are spread across turns to evade single-message detection — are caught by combining signals across the session window.

# Multi-turn is automatic when you pass session_id
# The tracker maintains a sliding window of 12 messages

# You can also configure blocking on multi-turn findings
guard = Guard(
    api_key="sk-...",
    block_on=["critical", "high"],     # block if any finding is high+
)
FindingTriggerDefault severity
SPLIT_INJECTIONInjection fragments across ≥2 messageshigh
SOCIAL_ENGINEERING_ESCALATIONReferences prior model output + action requestmedium
LOW_AND_SLOW_EXFIL3+ source calls + 3+ sink calls in 10 minhigh
TOOL_CALL_VOLUME_SPIKERecent rate > 3× session averagemedium
Previousscandar-scanNextOverwatch