Semantic Triggers
Semantic triggers define concept-based rules that fire when an agent's queries, memories, or reasoning steps match a semantic concept — understanding meaning, not just keywords.
Why Agents Need Semantic Triggers
Traditional rule-based alerting relies on exact keyword matches. A trigger for "financial risk" would miss queries about "credit exposure" or "debt-to-equity ratios." Semantic triggers understand meaning:
- A trigger for "accessing personal data" fires on queries about SSNs, emails, or home addresses
- A trigger for "expensive query patterns" fires on cross joins and unfiltered table scans
- A trigger for "financial regulation" fires on queries about trading data or regulatory reporting
How It Works
Agent activity (query, memory store, CoT step)
│
▼
Stage 1: Semantic Pre-Filter
- Embed the activity content
- Search trigger concept index for top-K nearest concepts
- Fast: sub-millisecond for thousands of triggers
│
▼
Stage 2: Exact Cosine Verification
- Compute exact cosine similarity for candidates
- Apply threshold check (configurable per trigger)
- Eliminates false positives from ANN approximation
│
▼
Cooldown Check
- Has this trigger fired recently for this agent?
- Debounce interval prevents alert storms
│
▼
Dispatch Action
- Webhook, AgentNotify, WriteEvent, or FlagForReview
Trigger Definition
| Field | Type | Description |
|---|---|---|
trigger_id | UUID | Unique identifier |
org_id | VARCHAR | Organization scope |
name | VARCHAR | Human-readable name |
concept | TEXT | Semantic concept to match (natural language) |
threshold | FLOAT | Cosine similarity threshold (0.0 to 1.0) |
action | Action | What to do when fired |
cooldown_secs | INTEGER | Minimum seconds between firings per agent |
enabled | BOOLEAN | Whether active |
created_at | TIMESTAMP | When registered |
Architecture
Trigger Management
Trigger definitions are managed per organization:
- In-memory index keyed by trigger ID
- One vector index per organization containing embedded concept vectors
- CRUD operations: register, update, delete, list
Two-Stage Evaluation
The evaluation pipeline runs in two stages:
- Approximate Nearest Neighbor Pre-Filter — Embeds the input, searches top-K nearest concept vectors (default K=10). Narrows thousands of triggers to a small candidate set in under a millisecond.
- Exact Cosine Verification — Computes exact cosine similarity for candidates. Only those above threshold pass.
- Cooldown Debounce — Checks per-agent, per-trigger cooldown timer.
Action Dispatch
Four action types when a trigger fires:
Webhook
HTTP POST with HMAC-SHA256 signature verification:
{
"trigger_id": "abc123",
"trigger_name": "Financial Risk Alert",
"agent_id": "analyst-agent",
"content": "SELECT credit_exposure, debt_ratio FROM ...",
"similarity_score": 0.91,
"fired_at": "2025-01-15T10:30:00Z"
}
Signature sent in X-HatiData-Signature header.
AgentNotify
Notification to the agent's offline inbox:
{
"notification_id": "def456",
"trigger_name": "Financial Risk Alert",
"message": "Your query matched a financial risk trigger.",
"severity": "warning"
}
WriteEvent
Structured event written to _hatidata_trigger_events for later analysis.
FlagForReview
Creates a review request requiring human administrator approval before the agent can proceed. The strongest action type for high-sensitivity triggers.
Agent Notification Inbox
Per-agent notification storage:
- Bounded queue (default: 100 notifications)
- TTL eviction (default: 24 hours)
- FIFO overflow — oldest notification evicted when full
- Poll interface via
get_notifications(agent_id)
MCP Tools
register_trigger
// Input
{
"name": "PII Access Alert",
"concept": "queries accessing personally identifiable information such as social security numbers, email addresses, phone numbers, or home addresses",
"threshold": 0.82,
"action": { "type": "webhook", "url": "https://alerts.yourcompany.com/hatidata", "secret": "whsec_your_webhook_secret" },
"cooldown_secs": 300
}
// Output
{ "trigger_id": "a1b2c3d4-...", "status": "registered", "concept_embedded": true }
list_triggers
// Input
{ "enabled_only": true }
// Output
[{
"trigger_id": "a1b2c3d4-...",
"name": "PII Access Alert",
"concept": "queries accessing personally identifiable information...",
"threshold": 0.82,
"action_type": "webhook",
"cooldown_secs": 300,
"enabled": true,
"fire_count": 47,
"last_fired_at": "2025-01-15T09:22:00Z"
}]
delete_trigger
{ "trigger_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" }
test_trigger
Test without dispatching actions:
// Input
{ "text": "SELECT ssn, email, phone FROM customers WHERE state = 'CA'" }
// Output
{
"matches": [{
"trigger_id": "a1b2c3d4-...",
"trigger_name": "PII Access Alert",
"similarity_score": 0.94,
"above_threshold": true,
"would_fire": true,
"cooldown_active": false
}]
}
Common Trigger Patterns
Data governance:
{ "name": "PII Column Access", "concept": "accessing columns containing personal data like names, emails, SSNs, addresses, or phone numbers", "threshold": 0.85, "action": {"type": "flag_for_review"} }
Cost control:
{ "name": "Expensive Query Pattern", "concept": "queries with cross joins, full table scans without filters, or SELECT * on large tables", "threshold": 0.78, "action": {"type": "agent_notify", "severity": "warning"} }
Compliance:
{ "name": "Financial Regulation", "concept": "queries related to financial transactions, trading data, or regulatory reporting", "threshold": 0.80, "action": {"type": "webhook", "url": "https://compliance.yourcompany.com/alerts"} }
Anomaly detection:
{ "name": "Schema Discovery", "concept": "queries exploring information_schema, pg_catalog, or system tables", "threshold": 0.75, "action": {"type": "write_event"} }
Usage Example
from hatidata_agent import HatiDataAgent
agent = HatiDataAgent(
host="your-org.proxy.hatidata.com",
agent_id="admin",
password="hd_live_your_api_key",
)
trigger = agent.register_trigger(
name="Cost Anomaly Detection",
concept="queries that scan very large tables without filters",
threshold=0.80,
action={"type": "agent_notify", "severity": "warning"},
cooldown_secs=600,
)
matches = agent.test_trigger(text="SELECT * FROM events")
for match in matches["matches"]:
print(f"{match['trigger_name']}: {match['similarity_score']:.2f}")
notifications = agent.get_notifications()
for note in notifications:
print(f"[{note['severity']}] {note['message']}")
Configuration
Trigger behavior is configurable per deployment:
| Setting | Default | Description |
|---|---|---|
| Triggers enabled | true | Enable/disable semantic triggers |
| ANN top-K | 10 | Candidates in pre-filter stage |
| Default cooldown | 5 minutes | Default cooldown between firings |
| Inbox size | 100 | Max notifications per agent inbox |
| Inbox TTL | 24 hours | Notification time-to-live |
| Webhook timeout | 10 seconds | HTTP timeout for webhook actions |
Related Concepts
- Persistent Memory — Triggers can monitor memory stores
- Chain-of-Thought Ledger — Triggers can evaluate reasoning
- Branch Isolation — Explore alternatives when triggers fire