Bastio
Agent Security

Anomaly Detection

Behavioral baseline learning and deviation detection for AI agent activity.

Anomaly Detection

Anomaly detection establishes behavioral baselines for your agents and users, then alerts when activity deviates from normal patterns. This catches attacks that don't match known threat signatures but exhibit unusual behavior.

Overview

Bastio learns what "normal" looks like for your agents:

  • Which tools are typically used
  • How often tools are called
  • When activity occurs (time of day)
  • What arguments are typical
  • Risk scores distribution

When new activity deviates significantly from the baseline, Bastio flags it as anomalous.

How Baselines Work

Baseline Building

Bastio collects statistics over a learning period:

{
  "baseline": {
    "proxy_id": "proxy_abc",
    "sample_size": 1523,
    "tool_frequencies": {
      "read_file": 45.2,
      "write_file": 22.1,
      "execute_shell": 8.3,
      "http_get": 24.4
    },
    "avg_tool_calls_per_session": 12.5,
    "typical_hours": [9, 10, 11, 12, 13, 14, 15, 16, 17],
    "avg_risk_score": 0.15,
    "std_dev_risk_score": 0.08,
    "last_updated": "2024-01-15T00:00:00Z"
  }
}

Minimum Samples

Baselines require a minimum number of samples before anomaly detection activates:

Baseline TypeMinimum SamplesRecommended
Proxy-level30100+
User-level1050+
Agent-level2075+

Until minimum samples are reached, anomaly detection runs in learning mode and won't generate alerts.

Anomaly Types

Tool Usage Anomaly

Unusual tool or tool frequency:

{
  "anomaly_type": "tool_usage",
  "details": {
    "tool": "db_admin",
    "baseline_frequency": 0.1,
    "current_frequency": 15.3,
    "deviation_factor": 153,
    "message": "Unusual tool usage: db_admin called 153x more than baseline"
  }
}

Time-Based Anomaly

Activity outside normal hours:

{
  "anomaly_type": "time_based",
  "details": {
    "current_hour": 3,
    "typical_hours": [9, 10, 11, 12, 13, 14, 15, 16, 17],
    "message": "Activity at 3:00 AM is outside typical hours (9 AM - 5 PM)"
  }
}

Risk Score Spike

Sudden increase in risk scores:

{
  "anomaly_type": "risk_spike",
  "details": {
    "current_risk": 0.75,
    "baseline_avg": 0.15,
    "baseline_std_dev": 0.08,
    "z_score": 7.5,
    "message": "Risk score 7.5 standard deviations above baseline"
  }
}

Volume Anomaly

Unusual activity volume:

{
  "anomaly_type": "volume",
  "details": {
    "current_calls_per_minute": 45,
    "baseline_calls_per_minute": 5,
    "deviation_factor": 9,
    "message": "Tool call volume 9x higher than baseline"
  }
}

Argument Pattern Anomaly

Unusual argument patterns:

{
  "anomaly_type": "argument_pattern",
  "details": {
    "tool": "read_file",
    "typical_paths": ["/app/*", "/data/*"],
    "current_path": "/etc/shadow",
    "message": "File path /etc/shadow outside typical patterns"
  }
}

API Response

When anomalies are detected, responses include:

{
  "action": "warn",
  "tool_call_id": "call_xyz",
  "risk_score": 0.45,
  "anomalies_detected": [
    {
      "type": "time_based",
      "severity": "medium",
      "deviation_score": 2.5,
      "message": "Activity at unusual hour"
    },
    {
      "type": "tool_usage",
      "severity": "low",
      "deviation_score": 1.8,
      "message": "Infrequent tool usage"
    }
  ],
  "baseline_status": "established",
  "message": "Tool allowed with anomaly warnings"
}

Anomaly Severity

SeverityDeviation ScoreTypical Action
low1.5 - 2.5Log, no action
medium2.5 - 4.0Warn, increase monitoring
high4.0 - 6.0Require approval
critical6.0+Block

Configuration

Enable Anomaly Detection

curl -X PUT https://api.bastio.com/v1/guard/{proxyId}/settings \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "anomaly_detection_enabled": true,
    "anomaly_sensitivity": "medium",
    "baseline_learning_days": 7,
    "minimum_baseline_samples": 50
  }'

Settings

SettingDefaultDescription
anomaly_detection_enabledtrueEnable anomaly detection
anomaly_sensitivitymediumlow, medium, high
baseline_learning_days7Days to learn baseline
minimum_baseline_samples30Minimum samples before detection
anomaly_action_threshold4.0Deviation score to trigger action

Sensitivity Levels

LevelDetection ThresholdUse Case
low4.0+ deviationProduction with varied usage
medium2.5+ deviationStandard production
high1.5+ deviationHigh-security environments

Baseline Types

Proxy Baseline

Global baseline for all activity through a proxy:

curl https://api.bastio.com/v1/guard/{proxyId}/baseline \
  -H "Authorization: Bearer YOUR_API_KEY"

User Baseline

Per-user behavioral patterns:

curl https://api.bastio.com/v1/guard/{proxyId}/baseline/user/{userId} \
  -H "Authorization: Bearer YOUR_API_KEY"

Agent Baseline

Per-agent identity patterns:

curl https://api.bastio.com/v1/guard/{proxyId}/baseline/agent/{agentId} \
  -H "Authorization: Bearer YOUR_API_KEY"

Managing Baselines

View Baseline

curl https://api.bastio.com/v1/guard/{proxyId}/baseline \
  -H "Authorization: Bearer YOUR_API_KEY"
{
  "baseline": {
    "status": "established",
    "sample_size": 1523,
    "learning_started": "2024-01-01T00:00:00Z",
    "last_updated": "2024-01-15T00:00:00Z",
    "metrics": {
      "tool_frequencies": { ... },
      "risk_distribution": { ... },
      "temporal_patterns": { ... }
    }
  }
}

Reset Baseline

After significant changes to your application:

curl -X POST https://api.bastio.com/v1/guard/{proxyId}/baseline/reset \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "reason": "Application update with new tools"
  }'

Exclude from Baseline

Mark certain sessions as non-representative:

{
  "session_id": "session_testing_123",
  "exclude_from_baseline": true,
  "reason": "Load testing session"
}

Alerts

Configure alerts for anomaly events:

curl -X POST https://api.bastio.com/v1/guard/{proxyId}/alerts \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Critical Anomaly Alert",
    "condition": {
      "anomaly_severity": "critical"
    },
    "channels": ["email", "slack"],
    "rate_limit_minutes": 15
  }'

Code Examples

Handling Anomaly Warnings

async def validate_with_anomaly_handling(
    proxy_id: str,
    tool_call: dict,
    session_id: str
) -> dict:
    """Validate tool call and handle anomalies."""

    result = await validate_tool_call(proxy_id, tool_call, session_id)

    if result.get("anomalies_detected"):
        for anomaly in result["anomalies_detected"]:
            # Log all anomalies
            logger.info(
                "Anomaly detected",
                type=anomaly["type"],
                severity=anomaly["severity"],
                message=anomaly["message"]
            )

            # Escalate high severity
            if anomaly["severity"] in ["high", "critical"]:
                await notify_security_team({
                    "type": "anomaly",
                    "session_id": session_id,
                    "anomaly": anomaly
                })

    return result

# Check baseline status
async def check_baseline_status(proxy_id: str) -> dict:
    """Check if baseline is established."""

    async with httpx.AsyncClient() as client:
        response = await client.get(
            f"https://api.bastio.com/v1/guard/{proxy_id}/baseline",
            headers={"Authorization": f"Bearer {API_KEY}"}
        )

        baseline = response.json()["baseline"]

        if baseline["status"] == "learning":
            print(f"Baseline learning: {baseline['sample_size']} samples collected")
        else:
            print(f"Baseline established with {baseline['sample_size']} samples")

        return baseline
interface AnomalyResult {
  action: string;
  anomalies_detected?: Array<{
    type: string;
    severity: string;
    deviation_score: number;
    message: string;
  }>;
}

async function validateWithAnomalyHandling(
  proxyId: string,
  toolCall: object,
  sessionId: string
): Promise<AnomalyResult> {
  const result = await validateToolCall(proxyId, toolCall, sessionId);

  if (result.anomalies_detected) {
    for (const anomaly of result.anomalies_detected) {
      console.log('Anomaly detected:', {
        type: anomaly.type,
        severity: anomaly.severity,
        message: anomaly.message,
      });

      if (['high', 'critical'].includes(anomaly.severity)) {
        await notifySecurityTeam({
          type: 'anomaly',
          sessionId,
          anomaly,
        });
      }
    }
  }

  return result;
}

Viewing Anomaly History

Query past anomaly events:

curl https://api.bastio.com/v1/guard/{proxyId}/anomalies \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -G \
  -d "start_time=2024-01-01T00:00:00Z" \
  -d "severity=high,critical"
{
  "anomalies": [
    {
      "event_id": "anom_001",
      "timestamp": "2024-01-15T03:30:00Z",
      "session_id": "session_abc",
      "type": "time_based",
      "severity": "high",
      "deviation_score": 4.5,
      "tool_call": {
        "name": "execute_shell",
        "arguments": { ... }
      }
    }
  ]
}

Best Practices

Next Steps