{{ toast.message }}

AI Gatewell

Security Management Console

{{ loginError }}
{{ currentTabName }}

{{ currentTabName }}

{{ formatTime(new Date()) }}
{{ currentUsername }} ADMIN
GET STARTED · FIRST STEPS

Welcome to Gatewell

Your firewall is live. Complete these steps to start inspecting AI traffic — each links to the right place.

Requests
{{ animatedStats.totalRequests }}
Total · 24h
{{ deltaReq }}% no baseline vs prior 12h
Cache hit
{{ animatedStats.cacheHitRate }}%
{{ stats.cacheHits }} of {{ stats.totalRequests }}
${{ cacheDollarsSaved }} saved today
Alerts
{{ animatedStats.totalAlerts }}
Security events · 7d
{{ alerts.filter(a => a.blocked).length }} blocked
Rules
{{ animatedStats.activeRules }}
Enforcing
{{ stats.activeRules }} / {{ rules.length }} healthy
POLICY GATE · ENFORCEMENT POSTURE {{ gateStatus.worst === 'ok' ? 'Enforced' : (gateStatus.worst === 'bad' ? 'Gap' : 'Partial') }}

{{ gateHeadline }}

{{ gateStatus.online }} ONLINE / {{ gateStatus.total }} REGISTERED AGENTS → {{ gateStatus.enabledRules }} RULES → {{ providerCount }} PROVIDERS
Logged prompts · 24h shape
Gateway latency is not measured yet

Request throughput

Last 24h · gateway-wide
refreshing 30s
POSTURE

All providers operating within posted bounds. {{ stats.activeRules }} rules enforcing, {{ agents.filter(a => isAgentOnline(a)).length }} agents armed, {{ alerts.filter(a => a.blocked).length }} hostile prompts intercepted in the last 24h.

Compliance {{ posture.compliance }}%
Coverage {{ posture.coverage }}%
Health {{ posture.health }}%

Alert activity

Daily · last 7 days
BLOCKED FLAGGED

Top rules

Most triggered · 7d
View all →

No rule hits recorded yet

{{ String(i + 1).padStart(2, '0') }} {{ r.name }} {{ r.total_hits }}

Provider mix

Traffic share · 24h
{{ stats.totalRequests || 0 }}
REQUESTS
{{ p.label }} {{ p.value }}

Threat heatmap

Hour × day · 7d
NORMAL
{{ String(h).padStart(2, '0') }}
{{ day }}
low high

Recent Security Events

Time Rule Status Details
{{ formatDate(alert.created_at) }} {{ alert.rule_name }} BLOCKED FLAGGED {{ maskPreview(alert.snippet, 80) }} {{ maskCount(alert.snippet) }} masked

No alerts — all clear

STREAMING LIVE
Watching {{ stats.activeRules }} active rules · {{ alertTotal }} events match this filter
Matching
{{ alertTotal }}
Rows, all pages
Blocked
{{ alertBlockedTotal }}
Hard stops
Flagged
{{ alertFlaggedTotal }}
Allowed but logged
Top rule
{{ topAlertRule.name || '—' }}
{{ topAlertRule.pct }}% of this page
Time Provider Rule User IP Agent Dir Status Score Content

No alerts match the current filters

Nothing on this page — {{ alertTotal }} matching events exist; go back a page.

{{ alertRangeLabel }} loading…
| INC-{{ selectedIncident.id }}

BLOCKED FLAGGED {{ selectedIncident.rule_name }}

Triggered on {{ selectedIncident.direction }} at {{ formatDate(selectedIncident.created_at) }}

{{ providerLabel(selectedIncident.provider) }}

User ID

{{ selectedIncident.user_id || '—' }}

Source IP

{{ selectedIncident.ip || '—' }}

Direction

{{ selectedIncident.direction }}

Alert ID

#{{ selectedIncident.id }}

Device Agent

{{ selectedIncident.agent_id }}

Device User

{{ selectedIncident.device_user }}

AI Risk Score

{{ (selectedIncident.llm_score * 100).toFixed(0) }}
{{ scoreLabel(selectedIncident.llm_score) }}

{{ selectedIncident.llm_score_explanation }}

Rule Details

Name: {{ selectedIncident.rule.name }}
Action: {{ selectedIncident.rule.action }}
Side: {{ selectedIncident.rule.side }}
Type: {{ selectedIncident.rule.pattern_type }}

{{ selectedIncident.rule.description }}

{{ selectedIncident.rule.pattern }}

Triggered Content (Request)

AI Response

No AI response captured (request may have been blocked or streaming)

Original Request

Prompt captured at {{ formatDate(selectedIncident.matched_prompt.created_at) }} · Provider: {{ providerLabel(selectedIncident.matched_prompt.provider) }}

Original Request

No matching request found for this alert.

Other Alerts from This User

{{ selectedIncident.user_alerts.length }}
Time Provider Rule Status Content

Recent Prompts from This User

{{ selectedIncident.user_prompts.length }}
{{ formatDate(up.created_at) }} {{ providerLabel(up.provider) }}

No user ID associated with this alert — related data unavailable.

Rules
{{ rules.length }}
{{ rules.filter(r => r.enabled).length }} enforcing
Block
{{ rules.filter(r => r.action === 'block').length }}
Hard stops
Alert
{{ rules.filter(r => r.action === 'alert').length }}
Log + continue
Semantic
{{ rules.filter(r => r.pattern_type === 'semantic').length }}
AI matched

Add New Rule

Order Status Rule Name Configuration Scope Actions
{{ index + 1 }}
{{ rule.name }}
{{ rule.pattern_type }}
{{ rule.side }} {{ rule.action }}

No rules yet — add one above or use the AI Builder

CONVERSATION STREAMS
{{ sessions.length }} session{{ sessions.length === 1 ? '' : 's' }} · multi-turn + tool-call activity grouped by Claude Code SDK session id
Sessions
{{ sessions.length }}
Conversations
Total turns
{{ sessions.reduce((n, s) => n + (s.turn_count || 0), 0) }}
User prompts
Tool calls
{{ sessions.reduce((n, s) => n + (s.tool_call_count || 0), 0) }}
Round-trips
Blocked
{{ sessions.reduce((n, s) => n + (s.blocked_count || 0), 0) }}
Across all sessions
Started Session Activity User Agent Provider First Prompt Score Blocked
{{ formatDate(s.started_at) }} {{ formatSessionId(s.session_id) }} {{ s.turn_count || 0 }} turn{{ (s.turn_count || 0) === 1 ? '' : 's' }} {{ s.tool_call_count }} {{ formatUserId(s.user_id) }} {{ s.agent_id }} {{ s.device_user }} {{ s.providers || '—' }} {{ maskPreview(s.first_snippet, 90) }} {{ maskCount(s.first_snippet) }} masked {{ (s.max_llm_score * 100).toFixed(0) }} {{ s.blocked_count }}

No conversations yet. New prompts will group automatically; click "Backfill legacy" to populate old rows.

Session
{{ formatSessionId(selectedSession.session_id) }}
Activity
{{ selectedSession.turn_count || 0 }} turn{{ (selectedSession.turn_count || 0) === 1 ? '' : 's' }} · {{ selectedSession.tool_call_count }} tool call{{ selectedSession.tool_call_count === 1 ? '' : 's' }}
Started
{{ formatDate(selectedSession.started_at) }}
Ended
{{ formatDate(selectedSession.ended_at) }}
Turns
{{ sessionInsights.turns }}
{{ sessionInsights.durationLabel }} elapsed
Tool calls
{{ sessionInsights.toolCalls }}
{{ sessionInsights.distinctTools }} distinct
Files
{{ sessionInsights.files.length }}
touched
Hosts
{{ sessionInsights.hosts.length }}
contacted
Risky cmds
{{ sessionInsights.risky.length }}
flagged
Answers
{{ sessionInsights.answersCaptured }}
{{ sessionInsights.answersMissing }} not captured
Commands worth a look
{{ r.label }} {{ maskInline(r.detail) }}
What this session touched {{ sessionInsights.utilityCount }} internal {{ sessionInsights.truncatedArgs }} truncated args
{{ t.value }} ×{{ t.count }} No tool calls in this session.
{{ grp.label }} ({{ sessionInsights[grp.key].length }})
{{ maskPreview(item.value, 52) }} ×{{ item.count }} +{{ sessionInsights[grp.key].length - 24 }} more
No file, host, or command arguments were recorded for this session.
Large session ({{ sessionGraph.nodes.length }} nodes) — starting zoomed to fit. Sessions are capped at 500 rows by the API.
Nothing to graph in this session.
{{ maskInline(n.title) }} {{ (n.meta.llm_score * 100).toFixed(0) }} {{ n.type }}
{{ maskInline(n.subtitle) }}
{{ graphTime(n.meta.created_at) }}
Prompt Tool Answer
{{ graphZoomPct }}%
Prompts
{{ promptTotal }}
Logged, all pages
Scored
{{ promptRows.filter(p => p.llm_score != null).length }}
LLM evaluated, this page
High risk
{{ promptRows.filter(p => p.llm_score != null && p.llm_score >= 0.7).length }}
score ≥ 0.7, this page
With reply
{{ promptRows.filter(p => p.response_snippet).length }}
Captured, this page
Time Provider User Source IP Agent Score Prompt Content Reply

No prompts recorded yet

No prompts match “{{ promptFilterQ }}”

Nothing on this page — {{ promptTotal }} matching prompts exist; go back a page.

{{ promptRangeLabel }} loading…
| PROMPT-{{ selectedPrompt.id }}

Prompt #{{ selectedPrompt.id }}

Captured at {{ formatDate(selectedPrompt.created_at) }}

{{ providerLabel(selectedPrompt.provider) }}

User ID

{{ selectedPrompt.user_id || '—' }}

Source IP

{{ selectedPrompt.ip || '—' }}

Agent

{{ selectedPrompt.agent_id }}

Device User

{{ selectedPrompt.device_user }}

Provider

{{ selectedPrompt.provider }}

Prompt ID

#{{ selectedPrompt.id }}

AI Risk Score

{{ (selectedPrompt.llm_score * 100).toFixed(0) }}
{{ scoreLabel(selectedPrompt.llm_score) }}

{{ selectedPrompt.llm_score_explanation }}

User Prompt

AI Response

No AI response captured for this prompt

Raw Request

No raw request data captured for this prompt.

Related Alerts

{{ selectedPrompt.related_alerts.length }}
Time Rule Direction Status
{{ formatDate(ra.created_at) }} {{ ra.rule_name }} {{ ra.direction }} BLOCKED FLAGGED
Packs
{{ marketplaceStats.total }}
Curated collections
Installed
{{ marketplaceStats.installed }}
Active packs
Rules Live
{{ marketplaceStats.rulesInstalled }}
From packs
Available
{{ marketplaceStats.rulesAvailable }}
Total rules

Detection Marketplace

One-click DLP rule packs

Vendor-curated bundles of detection rules. Installing a pack adds its rules to your Rules Engine; uninstalling removes exactly those rules.

{{ pack.name }}

{{ pack.category }} Installed

{{ pack.description }}

{{ r.action }}
{{ r.name }}
{{ r.pattern_type }} · {{ r.side }}
Entries
{{ auditTotal }}
Recorded, all pages
Creates
{{ auditLogs.filter(l => l.action === 'create' || l.action === 'login_success').length }}
+New objects, this page
Updates
{{ auditLogs.filter(l => l.action === 'update' || l.action === 'reorder').length }}
Edits, this page
Destructive
{{ auditLogs.filter(l => l.action === 'delete' || l.action === 'revoke' || l.action === 'login_failed').length }}
Delete / revoke / fail, this page
Export:
Time User Action Target Changes
{{ formatDate(log.timestamp) }} {{ log.user }} {{ log.action.replace('_', ' ') }} {{ log.target_type }} {{ log.target_id }} {{ log.changes }}

No audit entries yet

No entries match “{{ auditFilterQ }}”

Nothing on this page — {{ auditTotal }} matching entries exist; go back a page.

{{ auditRangeLabel }} loading…

Test Your Rules

SIMULATE A REQUEST · NO DATA SENT TO LLM
REQUEST-SIDE
{{ (testText || '').length }} CHARS

Results

{{ testResults.length }} {{ testResults.length === 1 ? 'RULE' : 'RULES' }} TRIGGERED

No rules matched. This content would be allowed.

Rule Name Action Description
{{ match.name }} {{ match.action }} {{ match.description || '-' }}
DEPLOY · INTEGRATIONS

Connect to the Firewall

Route any AI tool through the firewall for DLP inspection, audit logging, and policy enforcement. Supports Anthropic and OpenAI-compatible formats.

ANTHROPIC :8080 → /v1/messages OPENAI :8080 → /v1/chat/completions MANAGEMENT :80
ANTHROPIC FORMAT Claude Code, Anthropic SDK, Claude API
Claude Code (CLI) Recommended

Set one environment variable before launching Claude Code.

# Set once in your shell profile
export ANTHROPIC_BASE_URL="http://<firewall-host>:8080"
claude
Python — Anthropic SDK
{{ pythonSnippet }}
Node.js — Anthropic SDK
{{ nodejsSnippet }}
Python Agent Template
{{ agentSnippet }}
OPENAI-COMPATIBLE FORMAT Cursor, Aider, Continue.dev, Groq, Together, Mistral, DeepSeek, Ollama, vLLM
Cursor IDE Popular
{{ cursorSnippet }}
Aider
{{ aiderSnippet }}
Continue.dev (VS Code)
{{ continueDevSnippet }}
Python — OpenAI SDK
{{ openaiPythonSnippet }}
Node.js — OpenAI SDK
{{ openaiNodeSnippet }}
cURL / Any OpenAI-Compatible Tool
{{ openaiCurlSnippet }}
INFRASTRUCTURE
Docker — Same Network
{{ dockerSnippet }}
Environment Variables
VariableDefaultDescription
UPSTREAM_URLhttps://api.anthropic.comAnthropic upstream endpoint
OPENAI_UPSTREAM_URLhttps://api.openai.comOpenAI-compatible upstream endpoint
MANAGEMENT_URLhttp://management:9000Management server URL
REDIS_URL-Redis for caching + rate limiting
RATE_LIMIT_RPM60Per-IP requests per minute
CACHE_TTL3600Response cache TTL (seconds)

Supported Providers

Any tool that lets you set a custom base URL can route through the firewall. The same DLP rules apply across all providers.

Anthropic

/v1/messages

OpenAI

/v1/chat/completions

Groq

OpenAI-compatible

Together

OpenAI-compatible

Mistral

OpenAI-compatible

DeepSeek

OpenAI-compatible

Ollama

OpenAI-compatible

vLLM

OpenAI-compatible

BROWSER EXTENSION Intercept ChatGPT, Claude.ai, Gemini web usage
Chrome / Edge Extension
Download .zip

Monitors AI web apps (ChatGPT, Claude.ai, Gemini, Perplexity) and enforces DLP rules before prompts are sent.

1. Download the extension zip and extract it
2. Open chrome://extensions and enable Developer Mode
3. Click "Load unpacked" and select the extracted folder
4. Click the extension icon and enter your Gatewell URL + agent credentials

Requires an extension type agent created in the Agents tab.

DEVICE AGENT Local proxy for desktop AI tools (Copilot, Claude Desktop, etc.)
Gatewell Device Agent

Runs a local proxy on localhost:8100 that routes AI traffic through the cloud firewall. Auto-configures shell env vars for Anthropic and OpenAI tools.

# Install and run
./gatewell-device-agent --install --daemon

# Or run manually
./gatewell-device-agent --daemon
Windows (.exe) macOS (.dmg) Linux (binary)

Requires a device type agent created in the Agents tab. Download binaries from the GitHub Releases page.

GATEWELL AGENT Unified binary — pair with a device code, no scripts
Download the Gatewell Agent Recommended
All releases

A single self-contained binary that replaces the legacy Python agent scripts. It monitors and (optionally) proxies desktop AI tools, and pairs with the management console using a short device code — the /pair page approves it.

1. Download the binary for your OS and make it executable
2. Run gatewell setup — it prints a device code
3. Open the /pair page and approve the device code
# After downloading — pair with this console
gatewell setup

Assets are published per-OS on each GitHub Release. If a direct link 404s, grab the matching asset from releases/latest.

Webhooks
{{ webhooks.length }}
Configured
Enabled
{{ webhooks.filter(w => w.enabled).length }}
Listening
Disabled
{{ webhooks.filter(w => !w.enabled).length }}
Off
Recent deliveries
{{ webhookDeliveries.length }}
Last seen

Add Webhook

Webhook secret (shown once)

{{ newWebhookSecret }}

Configured Webhooks

{{ webhooks.length }} total

No alert ever leaves this box

With no webhooks configured, every alert the firewall raises is written to the database and stops there — nothing is pushed to Slack, a SIEM, or on-call. You will only see incidents if someone opens this console.

{{ hook.name }} {{ hook.enabled ? 'On' : 'Off' }} {{ hook.events }}

{{ hook.url }}

Recent Deliveries
{{ d.status_code || '-' }} {{ d.error || 'OK' }} {{ formatDate(d.created_at) }}
No deliveries yet.

Payload Format

// Headers
X-Webhook-Event: alert
X-Webhook-Signature: sha256=<hmac-sha256-hex>
X-Webhook-ID: <webhook-id>

// Body
{
  "rule_id": 3,
  "rule_name": "Block: Secrets",
  "user_id": "alice",
  "blocked": true,
  "timestamp": "2026-03-12T10:00:00Z"
}
Active keys
{{ apiKeys.filter(k => !k.revoked).length }}
{{ apiKeys.length }} total
Managed
{{ apiKeys.filter(k => k.upstream_provider).length }}
Server-side credentials
Pass-through
{{ apiKeys.filter(k => !k.upstream_provider && !k.revoked).length }}
Client-supplied auth
Revoked
{{ apiKeys.filter(k => k.revoked).length }}
Invalidated

Create API Key

sk-fw-* · used by clients

Creating your first key enables enforced mode

The firewall currently runs in open mode — all requests are allowed. Generating a key switches it to enforced mode: every client (including ones already connected) must send a valid sk-fw-* key in X-API-Key or Authorization: Bearer, or it gets rejected. Update your client config with the key below right after generating it.

Encrypted at rest. Clients sending any other upstream key will get 401 (BYO disabled).

API Key (shown once — copy now!)

{{ newApiKeySecret }}

How it works: When API keys exist, all requests to the firewall must include a valid X-API-Key header (sk-fw-*). If no keys are created, the firewall runs in open mode (no key required).

Managed credentials: When you attach an Upstream Provider + credential to a key, the firewall injects that credential server-side and rejects any other API key the client sends (BYO disabled). Leave it blank for legacy pass-through behaviour.

Active Keys

{{ apiKeys.filter(k => !k.revoked).length }} active / {{ apiKeys.length }} total

The firewall is in open mode — anyone who can reach it is allowed through

With zero keys, no X-API-Key header is required and every client is accepted unauthenticated. Issuing the first key flips the firewall into enforced mode, so update your clients right after you generate it.

Name Key Prefix Status Upstream Rate Limit Last Used Actions
{{ key.name }} {{ key.key_prefix }} {{ key.revoked ? 'Revoked' : 'Active' }} {{ key.upstream_provider }} pass-through {{ key.rate_limit_rpm ? key.rate_limit_rpm + ' RPM' : 'Default' }} {{ key.last_used_at ? formatDate(key.last_used_at) : 'Never' }}
Total agents
{{ agents.length }}
All types
Online
{{ agents.filter(a => isAgentOnline(a)).length }}
Seen < 1h
Device
{{ agents.filter(a => a.agent_type === 'device').length }}
Local AI proxy
Extension
{{ agents.filter(a => a.agent_type === 'extension').length }}
Browser DLP

Deploy Agent

Deploy a device agent (local AI proxy + machine monitoring for Claude Code, Codex CLI, Cursor, Aider) or a browser extension (web DLP for ChatGPT, Claude.ai, Gemini, Perplexity). The wizard walks you through download, pairing and verification.

1

Download the {{ wizardOSLabel }} binary on the target machine

2

Run setup{{ wizardOS === 'windows' ? ' in an Administrator PowerShell' : '' }}

{{ wizardSetupCmd }}

The agent prints a short device code (e.g. ABCD-1234) and waits for approval.

3

Enter the device code to approve this agent

{{ wizardError }}

Agent created — save these credentials (shown once):

Agent ID {{ wizardAgentId }}
Secret {{ wizardSecret }}
1 Download the extension and load it in the browser (chrome://extensions → Load unpacked)
2 In the popup, enter the Server URL: {{ wizardServerUrl }} plus the Agent ID and Secret above
3 Click Connect — the extension starts monitoring AI sites

Waiting for {{ wizardName }} to connect…

Checking every 3 s — {{ wizardElapsed }}s elapsed. {{ wizardType === 'device' ? 'The agent connects once setup finishes and the service starts (usually under a minute).' : 'The extension heartbeats within ~30 s of clicking Connect.' }}

{{ wizardConnectedAgent?.name }} is online

Agent ID {{ wizardConnectedAgent?.agent_id }} · IP {{ wizardConnectedAgent?.current_ip || '—' }}

Open device page →

How it works: This tab shows all connected clients — device agents (local AI proxy + machine monitoring) and browser extensions (web DLP). Device agents heartbeat their public IP for firewall allowlisting, report MCP inventory, enforce settings policies, and (in monitor+proxy mode) run a local proxy that intercepts Claude Code, Codex CLI, Cursor, Aider, and all AI tools — applying DLP rules before forwarding. They auto-configure shell env vars and detect the logged-on OS user. Extensions intercept web AI (ChatGPT, Claude.ai, Gemini, Perplexity). Agents seen within the last hour are considered online. Blocking any agent immediately stops its access.

Uninstall an Agent

Fully removes the gatewell agent from a machine: service, running process, binary, config/state/credentials, logs, and the shell env vars it set. Shell profiles are backed up first.

{{ uninstallOS === 'windows' ? 'Run in an Administrator PowerShell.' : 'Runs with sudo; it will prompt for your password once.' }} Removing the agent here does not delete its record in the dashboard — delete that from the Registered Agents table below.

{{ uninstallScript }}

{{ uninstallOSLabel }} — your current terminal keeps the env vars until you open a new one (or unset them).

Device Groups

A group holds one device policy (agent config.toml) applied to every member device. Grouped devices receive the group's policy on their next heartbeat; ungrouped devices keep their own per-agent config.

No groups yet — create one to manage device policy at scale.

{{ g.name }}
{{ g.description }}
{{ groupModeSummary(g) }}
{{ g.member_count }} device{{ g.member_count === 1 ? '' : 's' }} rev {{ g.config_revision }}

Agent Risk Scoring

{{ agentRiskConfig.enabled ? 'Active' : 'Disabled' }}
{{ agentRiskConfig.global_threshold }}

Alert when agent score exceeds this

{{ agentRiskConfig.daily_threshold }}

Alert when daily points exceed this

Points per blocked alert

Points per warning alert

Alerts in 30min to trigger burst bonus

Alerts in 3hrs to trigger burst bonus

Score halves after this many quiet days

Registered Agents

{{ agents.filter(a => a.agent_type === 'device').length }} devices, {{ agents.filter(a => a.agent_type === 'extension').length }} extensions — {{ agents.filter(a => a.enabled).length }} active / {{ agents.length }} total

No agents registered — IP filtering is disabled

Name Type Group Upstream Current IP Status Risk Score Last Seen Actions
{{ agent.name }} Extension Device
{{ agent.current_ip || '-' }} Blocked {{ isAgentOnline(agent.last_seen_at) ? 'Online' : 'Offline' }}
{{ agent.risk_score }} BURST
{{ agent.daily_score }} today · {{ agent.monthly_alert_count }} / 30d
{{ agentTimeSince(agent.last_seen_at) }}

Risk Threshold Alerts

{{ agentRiskAlerts.length }}
Agent Type Score Threshold Time
{{ ra.agent_name }} Global Daily {{ ra.score }} {{ ra.threshold }} {{ formatDate(ra.created_at) }} {{ formatTime(ra.created_at) }}
MCP Servers
{{ mcpInventory.length }}
Reported
stdio
{{ mcpInventory.filter(m => m.transport === 'stdio').length }}
Process-based
http / sse
{{ mcpInventory.filter(m => m.transport === 'http' || m.transport === 'sse').length }}
Network-based
env keys
{{ mcpInventory.reduce((n,m) => n + (m.env_keys ? m.env_keys.length : 0), 0) }}
Secret refs

MCP Inventory

MCP servers configured across enrolled machines. Secret values are redacted by the agent — only env key names are shown.

No MCP inventory reported yet. Enable the mcp-inventory capability on an agent.
Agent Client Server Transport Command / URL Env keys Scope Probe
{{ s.agent_id }} {{ s.client }} {{ s.server_name }} {{ s.transport }} {{ s.url || ((s.command || '') + ' ' + (s.args || []).join(' ')) }} {{ k }} {{ s.scope }} {{ (s.probe_tools || []).length }} tools {{ s.probe_status }}
Hooks
{{ hookInventory.length }}
Reported
Scripts
{{ hookInventory.filter(h => h.classification === 'script').length }}
Viewable + hashed
Executables
{{ hookInventory.filter(h => h.classification === 'executable').length }}
SHA-256 only
Inline cmds
{{ hookInventory.filter(h => h.classification === 'command').length }}
Config only

Claude Code Hooks

Hooks configured in Claude Code settings across enrolled machines. Script hooks are fetched view-only and hashed; executable hooks carry a SHA-256 only; inline commands show their config.

No hook inventory reported yet. Enable the hook-inventory capability on an agent.
Agent Event Matcher Type Command Fingerprint Scope
Policies
{{ settingsPolicies.length }}
Claude Code config
Assigned
{{ settingsPolicies.reduce((n,p) => n + (p.agent_count || 0), 0) }}
Agent links
Presets
{{ Object.keys(spPresets || {}).length }}
Templates
Versions
{{ settingsPolicies.reduce((n,p) => n + (p.version_count || 0), 0) }}
Total revisions

Settings Policies

Canonical Claude Code managed-settings.json / settings.json the agent enforces on enrolled machines.

No policies yet — create one, start from a preset, or generate with AI.

Name Description Agents Versions Updated Actions
{{ p.name }} {{ p.description || '—' }} {{ p.agent_count }} {{ p.version_count }} {{ formatDate(p.updated_at) }}

{{ spForm.id ? 'Edit Policy' : 'New Policy' }}

Version History & Backups

every save is snapshotted — restore any point
No versions yet
Version Note By When Action
v{{ v.version }} (current) {{ v.note }} {{ v.created_by || '—' }} {{ formatDate(v.created_at) }} {{ formatTime(v.created_at) }}
BROWSER EXTENSION · MV3

Inspect prompts in the browser, before they leave the tab

Intercept and check AI prompts on web platforms before submission. Enforces the same DLP rules used by the API firewall.

CHATGPT CLAUDE.AI GEMINI PERPLEXITY

Extension Activity

{{ alerts.filter(a => a.provider === 'extension').length }} events
Time User Rule Status Content

No extension activity yet

Install the Extension

1

Create an Extension agent

Go to the Agents tab, select type Extension, and create. Save the Agent ID and Secret.

2

Download and load in Chrome

Download the zip, extract it, then go to chrome://extensions then enable Developer Mode and click "Load unpacked" to select the folder.

Download ai-gatewell-extension.zip
3

Connect with Agent ID + Secret

Click the extension icon, enter your server URL, Agent ID, and Agent Secret, then click Connect. No username or password needed.

4

Monitor and block from the Agents tab

The extension appears as a connected agent. Block it anytime — the user will see a full-page "Access Blocked" overlay on all AI sites within 30 seconds.

How It Works

✍️

Intercept

Hooks into the input areas and submit buttons of AI web platforms.

🔍

Check

Sends the text to Gatewell for DLP rule evaluation (regex, semantic, presets).

🛡️

Enforce

Blocks or warns before submission. All interactions logged to the audit trail.

Describe the intercept

NATURAL LANGUAGE → COMPILED RULE
CLAUDE
EXAMPLES — TAP TO TRY
WHAT SHOULD THE GATEWAY DO?
{{ (aiRuleDescription || '').length }} CHARS

Compiled rule

PREVIEW · NOT YET ADDED TO STACK
{{ aiGeneratedRules.length }} draft{{ aiGeneratedRules.length === 1 ? '' : 's' }}
Awaiting intent
DESCRIBE A RULE TO COMPILE
⟶ CLAUDE IS COMPILING
{{ s.label }}
COMPILE ERROR
{{ aiRuleError }}
{{ rule.name }}

{{ rule.description }}

TYPE · {{ (rule.pattern_type || '').toUpperCase() }} SCOPE · {{ (rule.side || '').toUpperCase() }} {{ (rule.action || '').toUpperCase() }}
PATTERN
# {{ rule.pattern_type }} · {{ (rule.side || '').toLowerCase() }}
match "{{ rule.pattern }}"
action {{ (rule.action || '').toUpperCase() }}
WHY THIS SHAPE

{{ rule.rationale }}

EXAMPLES THIS WOULD CATCH
{{ ex }}
SAVED
AI RISK SCORER

LLM-driven prompt risk scoring

Score every prompt 0.0–1.0 for malicious intent. Threshold-based alert + block.

{{ llmScoringConfig.enabled ? 'ENABLED' : 'DISABLED' }}

Scoring Configuration

{{ llmScoringConfig.enabled ? 'ENABLED' : 'DISABLED' }}

How it works

1 Every prompt longer than {{ llmScoringConfig.min_length }} characters is sent to an LLM for analysis
2 The LLM returns a risk score from 0 (safe) to 100 (malicious)
3 Score ≥ {{ (llmScoringConfig.threshold_alert * 100).toFixed(0) }} triggers an alert with AI explanation
4 Score ≥ {{ (llmScoringConfig.threshold_block * 100).toFixed(0) }} blocks the request entirely

e.g. gpt-4o-mini, gpt-4o, gpt-4-turbo e.g. claude-haiku-4-5-20251001, claude-sonnet-4-5-20241022

API key configured No API key set Manage in System tab
{{ (llmScoringConfig.threshold_alert * 100).toFixed(0) }}

Score ≥ this triggers an alert (but allows the request)

{{ (llmScoringConfig.threshold_block * 100).toFixed(0) }}

Score ≥ this blocks the request entirely

Only score prompts with ≥ this many characters

Score Ranges

0–19: Safe
20–49: Low Risk
50–79: Suspicious
80–100: Critical

Test Scoring

Try the LLM scorer with a sample prompt to see how it responds.

Scoring Failed

{{ llmScoringTestResult.error }}

{{ (llmScoringTestResult.score * 100).toFixed(0) }}
{{ scoreLabel(llmScoringTestResult.score) }}

{{ llmScoringTestResult.explanation }}

Would BLOCK this request Would ALERT on this request Would ALLOW this request
Raw API Response
HTTP {{ llmScoringTestResult.raw_status }} {{ llmScoringTestResult.provider }} / {{ llmScoringTestResult.model }}
Users
{{ mgmtUsers.length }}
Total registered
Active
{{ mgmtUsers.filter(u => !u.disabled).length }}
Login enabled
Admins
{{ mgmtUsers.filter(u => u.role === 'admin').length }}
Privileged
SSO
{{ mgmtUsers.filter(u => u.auth_source === 'sso').length }}
Azure AD

Create User

Username Role Last Login Created Enabled Actions
{{ u.username }} system SSO local blocked {{ u.role }} {{ u.last_login_at ? formatDate(u.last_login_at) : 'Never' }} {{ formatDate(u.created_at) }} Managed via env var

Delete {{ deleteUserTarget.username }}?

This removes the account permanently. Their audit log entries are kept. To keep the account but stop them signing in, use Block instead.

Reset Password for {{ resetPasswordUser.username }}

SYSTEM · INFRASTRUCTURE

Gateway settings & integrations

Configure upstreams, SSO, password policy, and review version + diagnostics.

ARMED

System Status

Console version

{{ systemInfo.version }}

Uptime

{{ formatUptime(systemInfo.uptime_seconds) }}

Python

{{ systemInfo.python_version }}

DB Size

{{ formatBytes(systemInfo.db_stats?.db_size_bytes) }}

Auth
SSO (Azure AD)
Redis
LLM Scoring

Database Records

{{ table.replace('_', ' ') }} {{ count.toLocaleString() }}

LLM API Key

This key is used for both LLM Scoring and AI Rule Generator features.

{{ systemInfo.llm_scoring?.has_api_key ? 'API key configured' : 'No API key set' }} Provider: {{ systemInfo.llm_scoring.provider }} · Model: {{ systemInfo.llm_scoring.model }}

Platform

{{ systemInfo.platform }}

Loading system info...