TURN Trigger Language (TTL)
1. Overview
The TURN Trigger Language (TTL) formalizes graph-native triggers that enable the Atomic Knowledge Graph to observe itself and actuate responses. This is the mechanism by which the graph watches itself—the core differentiator that makes ADAMAS fundamentally different from static orchestration systems.
TTL unifies data and behavior in the knowledge graph. Rather than separating rules from data, triggers live alongside the atoms they observe. The graph is simultaneously the source of truth, the observer, and the actuator.
2. Design Philosophy
The Self-Mutating Graph
Traditional systems separate data from behavior through external rules engines:
[Data] → [Rules Engine] → [Actions]
TTL unifies them inside the knowledge graph itself:
[Knowledge Graph]
↓ observes itself
[TriggerAtom]
↓ actuates
[Knowledge Graph mutations + Agent invocations]
Why This Matters
Without TTL, learning is manual: an agent makes an observation, a human reviews it, decides to create a constraint, and manually creates it. Four steps requiring human intervention.
With TTL, learning is autonomous: an agent creates an ObservationAtom, a TriggerAtom fires when confidence ≥ 0.9, a constraint proposal agent launches automatically, a policy validator runs, and only high-impact items need human review. The flywheel spins without human intervention for routine cases.
3. TTL Syntax
Basic Structure
@trigger <WatchedAtomType>
WHEN <condition>
[WITH <context_queries>]
ACTUATE {
<actuator_chain>
}
[CONFIG {
<configuration>
}]
Here's a complete example—the observation-to-constraint promotion trigger:
@trigger ObservationAtom
WHEN confidence >= 0.9
AND 'limitation' IN tags
AND occurrence_count >= 3
WITH {
related_code: "MATCH (o)-[:ABOUT]->(c:CodeAtom) RETURN c",
existing_constraints: "MATCH (c:ConstraintAtom) RETURN c.name"
}
ACTUATE {
@agent: {
query: "AgentAtom WHERE 'constraint_proposer' IN tags",
prompt: "Propose a constraint based on: {{observation}}",
tier: "cheap"
},
@system: {
operation: "update",
target: "PolicyAtom WHERE name = 'constraint_review_queue'",
data: {pending_reviews: "{{pending_reviews}} + 1"}
},
@human: {
condition: "impact = 'high'",
prompt: "High-impact constraint proposed: {{constraint_proposal}}",
timeout: "24h",
fallback: "escalate"
}
}
CONFIG {
enabled: true,
priority: 100,
debounce: "5s",
max_fires_per_hour: 10
}
Condition Syntax
TTL supports simple, compound, and nested conditions:
| Type | Syntax | Example |
|---|---|---|
| Comparison | field op value | confidence >= 0.9 |
| Equality | field = value | status = 'completed' |
| Containment | field CONTAINS value | tags CONTAINS 'security' |
| Pattern | field MATCHES pattern | name MATCHES 'auth_*' |
| Temporal | field > NOW() - INTERVAL | updated_at > NOW() - INTERVAL '1 hour' |
| AND | cond AND cond | confidence >= 0.9 AND tags CONTAINS 'limitation' |
| OR | cond OR cond | status = 'failed' OR retry_count >= 3 |
| NOT | NOT cond | NOT status = 'skipped' |
| Nested | (cond) OR cond | (confidence >= 0.9 AND tags CONTAINS 'limitation') OR manual = true |
Field Access
TTL supports direct fields, nested fields via dot notation, relationship traversal with bracket syntax, and array indexing:
confidence // Direct field
metadata.source // Nested field
[ABOUT->CodeAtom].language // Relationship traversal
tags[0] // Array access
4. Actuator Types
TTL provides six actuator types, each serving a distinct role in the trigger response chain.
@agent — Launch Agent Reasoning
Invokes an agent to process the trigger event. Agents can be found by ID or discovered dynamically via graph query.
@agent: {
// Find agent
id: "agent_constraint_proposer",
query: "AgentAtom WHERE 'proposer' IN tags",
// Prompt
prompt: "Analyze this: {{observation}}",
// Execution options
tier: "cheap" | "expensive" | "adaptive",
model_override: "claude-sonnet-4-5",
thinking_budget: 16000,
token_budget: 5000,
// Context injection
inject: ["observation", "related_code", "existing_constraints"]
}
@system — Automatic Rule Evaluation
Performs CRUD operations on the knowledge graph without agent involvement. Supports create, update, delete, and validate operations.
@system: {
operation: "create" | "update" | "delete" | "validate",
// For create
atom_type: "ConstraintAtom",
data: { name: "{{proposed_name}}", source_observations: ["$atom_id"] },
// For update
target: "PolicyAtom WHERE name = 'review_queue'",
data: { pending_count: "pending_count + 1", last_updated: "NOW()" },
// For validate
validation_rules: ["{{new_constraint}} does not conflict with existing"]
}
@human — Require Human Approval
Inserts a human decision point into the actuator chain. Supports conditional execution, timeout handling, and escalation paths.
@human: {
condition: "impact = 'high' OR cost_usd > 10",
prompt: "Review this constraint proposal:\n{{constraint_proposal}}",
options: ["approve", "reject", "modify"],
timeout: "24h",
reminder_at: "12h",
fallback: "approve" | "reject" | "escalate" | "defer",
escalate_to: "AgentAtom WHERE role = 'architect'",
notify_channel: "slack://adamas-reviews"
}
@schedule — Defer Execution
Schedules actuator execution for a future time. Supports relative delays, absolute times, cron expressions, and batching.
@schedule: {
delay: "5m", // Relative delay
at: "2026-02-01T00:00:00Z", // Absolute time
cron: "0 0 * * *", // Recurring (daily at midnight)
batch: true,
batch_window: "1h",
max_batch_size: 100,
then: { @agent: { ... } }
}
@message — Inter-Agent Communication
Sends messages between agents via named channels, supporting both fire-and-forget and request-response patterns.
@message: {
to: "AgentAtom WHERE 'ops_team' IN tags",
channel: "security-alerts",
message: "New high-confidence observation: {{observation.summary}}",
correlation_id: "$trace_id",
priority: "high",
await_response: true,
timeout: "5m"
}
@trigger — Chain to Another Trigger
Chains execution to another TriggerAtom, passing context forward. Enables composable trigger pipelines.
@trigger: {
trigger_id: "secondary_validation_trigger",
context: {
source_observation: "$atom_id",
proposed_constraint: "{{constraint_proposal}}"
}
}
5. Actuator Chaining
Sequential Execution
Actuators execute in sequence by default. Use THEN for explicit ordering:
ACTUATE {
@agent: { ... } // 1. Agent proposes
THEN
@system: { ... } // 2. System validates
THEN
@human: { ... } // 3. Human approves
THEN
@system: { ... } // 4. System creates
}
Parallel Execution
Use | for concurrent actuators:
ACTUATE {
@agent: { id: "scout_a" } | @agent: { id: "scout_b" } | @agent: { id: "scout_c" }
THEN
@agent: { id: "synthesizer" }
}
Conditional Branching
Use IF/ELSE blocks to branch based on prior results:
ACTUATE {
@agent: { ... }
THEN
IF "{{result.confidence}} >= 0.9" {
@system: { operation: "create", ... }
} ELSE {
@message: { to: "human_reviewer", ... }
}
}
6. Trigger Lifecycle
Triggers follow a six-stage lifecycle from registration through recording:
| Stage | Description | Mechanism |
|---|---|---|
| Registration | Trigger created via DGP mutation | createTrigger mutation → TriggerAtom in graph |
| Loading | Engine loads enabled triggers at startup | Indexed by watched atom type, sorted by priority |
| Watching | Gateway emits events on every atom mutation | NATS: adamas.atoms.<AtomType>.created|updated|deleted |
| Matching | Find triggers watching this atom type | Check debounce, rate limits, evaluate condition predicates |
| Firing | Build context and execute actuator chain | WITH queries → context → actuator execution → context update |
| Recording | Create TriggerFireAtom for audit trail | Captures triggering atom, context snapshot, results, status |
Every trigger fire creates a TriggerFireAtom recording the triggering atom, a snapshot of the context at fire time, every actuator executed with its result and duration, and the overall outcome status (success, partial, or failed).
7. Built-in Triggers
Flywheel: Observation → Constraint
When observations reach high confidence and recurrence, automatically propose them as formal constraints:
@trigger ObservationAtom
WHEN confidence >= 0.9
AND 'limitation' IN tags
AND occurrence_count >= 3
ACTUATE {
@agent: {
query: "AgentAtom WHERE 'constraint_proposer' IN tags",
prompt: "Propose a constraint based on: {{observation.description}}",
tier: "cheap"
}
THEN
@system: {
operation: "create",
atom_type: "ConstraintAtom",
data: { name: "{{agent_result.proposed_name}}", enforcement: "advisory" }
}
}
Flywheel: Constraint → Router Update
When constraints are validated, update the routing engine to reflect new knowledge:
@trigger ConstraintAtom
WHEN status = 'validated' AND type = 'model_limitation'
WITH {
affected_model: "MATCH (c {id: $atom_id})-[:ABOUT]->(m:ModelAtom) RETURN m"
}
ACTUATE {
@system: {
operation: "update",
target: "RouterAtom WHERE DEFAULT_MODEL->ModelAtom.id = '{{affected_model.id}}'",
data: { escalation_rules: "{{escalation_rules}} + [...]" }
}
THEN
@message: {
channel: "ops-notifications",
message: "Router updated: {{affected_model.name}} will now escalate"
}
}
Security: High-Severity Alert
Critical security observations trigger parallel notification and incident response:
@trigger ObservationAtom
WHEN type = 'security' AND severity = 'critical'
ACTUATE {
@message: {
to: "AgentAtom WHERE 'security_team' IN tags",
channel: "security-alerts",
priority: "high"
}
|
@agent: {
id: "agent_incident_responder",
tier: "expensive",
thinking_budget: 32000
}
}
Quality: Failed Execution Analysis
After repeated task failures, trigger root cause analysis with optional task disablement:
@trigger ExecutionAtom
WHEN success = false AND retry_count >= 3
WITH {
recent_failures: "MATCH (e:ExecutionAtom) WHERE e.success = false ... RETURN count(e)",
task_def: "MATCH (e {id: $atom_id})-[:EXECUTION_OF]->(t:TaskAtom) RETURN t"
}
ACTUATE {
IF "{{recent_failures.count}} > 5" {
@agent: { query: "AgentAtom WHERE 'failure_analyst' IN tags", tier: "expensive" }
THEN
@human: {
condition: "{{agent_result.recommended_action}} = 'disable_task'",
prompt: "Analyst recommends disabling task. Approve?",
timeout: "1h", fallback: "defer"
}
} ELSE {
@message: { channel: "task-failures", message: "Task failed after 3 retries" }
}
}
8. CLI Tools
The adamas-triggers CLI manages the full trigger lifecycle:
# List triggers
adamas-triggers list
adamas-triggers list --enabled
adamas-triggers list --watching ObservationAtom
# Show details
adamas-triggers show <trigger_id>
# Enable / disable
adamas-triggers enable <trigger_id>
adamas-triggers disable <trigger_id>
# Dry-run test
adamas-triggers test <trigger_id> --atom '{"confidence": 0.95, "tags": ["limitation"]}'
# Fire history
adamas-triggers history <trigger_id>
adamas-triggers history <trigger_id> --since 24h --status failed
# Create / validate
adamas-triggers create trigger.ttl
adamas-triggers validate trigger.ttl
Example dry-run output:
$ adamas-triggers test promote-observation --atom '{"confidence": 0.95, "tags": ["limitation"]}'
✓ Trigger: promote-observation (enabled)
✓ Condition: MATCHES
- confidence >= 0.9: 0.95 >= 0.9 ✓
- 'limitation' IN tags: true ✓
Actuator chain (dry run):
1. @agent: constraint_proposer — Would execute with prompt
2. @system: create ConstraintAtom — Would create from agent result
⚠ Note: Dry run — no actuators were executed
9. Monitoring & Observability
TTL exposes Prometheus-style metrics for operational visibility:
# Trigger fires
turn_trigger_fires_total{trigger_id, status}
# Actuator executions
turn_actuator_executions_total{trigger_id, actuator_type, status}
turn_actuator_duration_ms{trigger_id, actuator_type}
# Rate limiting
turn_trigger_debounced_total{trigger_id}
turn_trigger_rate_limited_total{trigger_id}
TriggerFireAtoms link to SpanAtoms for distributed tracing:
MATCH (fire:TriggerFireAtom)-[:TRACED_BY]->(span:SpanAtom)
WHERE fire.trigger_id = $trigger_id
RETURN fire, span
ORDER BY fire.fired_at DESC
LIMIT 100
10. Security Considerations
Privilege Escalation Prevention
Triggers run with the privileges of the trigger author, not the triggering atom's author. The TriggerEngine validates that the author has permission to invoke the specified agents and mutate the target atom types before the trigger is registered.
Trigger Auditing
All trigger fires are recorded as AuditAtoms capturing the event type, actor (trigger ID), target (atom type and ID), action taken, outcome status, and full trace ID. This provides a complete audit trail for compliance and debugging.
