STL — Semantic Tension Language

A minimal syntax for expressing directional, typed, weighted semantic relations

The whole grammar fits on one line:

[Source]    [Target]  ::mod(key=value, ...)

That is it. No nesting rules, no quoting ceremony, no indentation grammar. Reads like a sentence for humans, generates like markdown for LLMs, parses like a typed edge for machines.

Three components, three roles

Anchor — the noun
[Name]

A named semantic entity. PascalCase or underscore-joined. Unicode and Namespace: prefixes are supported.

[Heavy_Rain]
[黄帝内经]
[Physics:Energy]
Arrow — the direction

A directed relation. [A] → [B] is not the same as [B] → [A]. You can also write ->.

[Cause] → [Effect]
[Child] → [Parent]
[Source] → [Target]
Modifier — edge metadata
::mod(...)

Everything about this edge lives here. Stack multiple ::mod() blocks if needed. Type, confidence, source, time — all in one place.

::mod(confidence=0.9,
  rule="causal",
  strength=0.85)

Anatomy of a real statement

[Heavy_Rain] [Flooding] ::mod(action="triggers", rule="causal", strength=0.85, confidence=0.92)
Anchors — two named entities, direction left to right
Arrow — one directed edge, from cause to effect
Modifier — causal edge, strength 0.85, confidence 0.92

Unrolled into plain English: "Heavy rain triggers flooding; this is a causal relation, with a causal strength of 0.85 and my confidence in this claim is 0.92." Roughly 17 tokens versus 30+ in natural language — and zero ambiguity, fully machine-parsable.

Meta semantic fields — every edge declares its kind

Every STL edge must carry at least one meta semantic field. It tells you what kind of relation this is. Edges without a meta field are "empty shells" and are rejected on write.

FieldSemanticsExample valueWhen to use
is_aClassification"algorithm" / "spec"X belongs to category Y
actionBehavior / causation"triggers" / "reclaims"X does something to Y
roleFunctional role"entry_point" / "guardian"X plays role Y in some system
statusState"deprecated" / "active"X is currently in state Y
phaseTemporal phase"initialization" / "cleanup"X is in lifecycle phase Y
relationGeneric (last resort)"depends_on" / "uses"None of the above fits
Retired fields: type and kind were merged into is_a. predicate was split into action and role. Don't write new edges with the old names.

Common modifiers — the edge's "personality palette"

KeyTypePurpose
confidenceFloat 0–1Confidence in this claim (effectively required)
ruleenum"causal" / "logical" / "empirical" / "definitional"
strengthFloat 0–1Strength of the causal or associative tie
sourceStringProvenance — DOI, document path, experiment ID
occurred_timeDateTimeWhen the event actually happened (external time)
created_atEpoch floatWhen this edge was recorded (internal; ingest pipelines may override)
lessonStringA compressed learning attached to the edge (typical for empirical)
pathStringA file path referenced by this edge
descriptionStringFree-text annotation
certaintyFloat 0–1Agent's judgment of objective truth — independent from confidence

Confidence calibration band

Five tiers so that the same number means the same thing across writers, sessions, and projects.

0.0 0.3 0.5 0.7 0.85 0.95
0.95–1.00
Definitional truth · mathematical fact · direct quotation
0.85–0.94
Well-evidenced fact · widely accepted theory
0.70–0.84
General knowledge · moderate evidence
0.50–0.69
Plausible but uncertain · limited evidence
0.30–0.49
Speculative · weak evidence
0.00–0.29
Highly uncertain · hypothetical

Build your own — live STL builder

Change any input — the output updates live. Color key: blue = anchor · yellow = arrow · purple = ::mod keyword · cyan = key · pink = string · green = number.

STL vs JSON vs Natural Language

Same fact: "Heavy rain causes flooding; this is a causal relation with strength 0.85." Three ways to express it:

Natural Language

"Heavy rain causes flooding."
✓ Most familiar to humans
✗ Causal or correlational? Unsaid.
✗ What strength? Unsaid.
✗ How confident? Unsaid.
✗ LLM re-hallucinates at parse time

JSON

{
  "subject":"Heavy_Rain",
  "object":"Flooding",
  "type":"causal",
  "strength":0.85,
  "confidence":0.92
}
✓ Structured, unambiguous
✗ ~40% more tokens
✗ Not designed to be read aloud
✗ LLM mistakes nested braces

STL ★

[Heavy_Rain] [Flooding]
::mod(
  action="triggers",
  rule="causal",
  strength=0.85,
  confidence=0.92)
✓ Reads like a sentence
✓ ~30% fewer tokens than JSON
✓ Zero ambiguity, fully typed
✓ Sits inside the LLM's training distribution

Four core statement patterns

Causal — cause and effect
[Smoking] [Lung_Cancer] ::mod(action="increases_risk", rule="causal", strength=0.92, confidence=0.99, source="WHO_2024")
Required: action + rule="causal" + strength + confidence + source
Definitional — a fact by definition
[Photon] [Massless_Boson] ::mod(is_a="particle_classification", rule="definitional", confidence=0.99)
Required: is_a + rule="definitional" + confidence ≥ 0.95
Empirical lesson — distilled experience
[Refresh_Token] [Auth_Failure] ::mod(action="causes", rule="empirical", lesson="Testing-mode OAuth tokens expire after 7 days", occurred_time="2026-04-23", confidence=0.95)
Required: action + rule="empirical" + lesson + occurred_time + confidence
Fact with source — measured or cited value
[Tau_Mass] [1776_MeV] ::mod(is_a="measured_value", confidence=0.99, source="PDG_2024", occurred_time="2024")
Required: is_a or action + confidence + source

Why STL exists — design rationale

ConstraintJSONNatural LanguageSTL
Can an LLM write it correctly first try? Breaks on deep nesting No structure → hallucinates again at parse Flat grammar, validated by Lark
Can a human scan-read it? Eyes jump between braces Yes Yes — reads left to right
Can a machine parse it precisely? Yes No Yes — via stl_parser
Can it carry typed metadata? Yes, but verbose "I'm kinda sure" — what number? Schema-typed inside ::mod()
Can it map directly to a graph edge? Needs an interpretation layer Requires NER + relation extraction pipeline One STL line = one graph edge. Zero adapters.
Core stance: STL is the zero-friction bridge between language and graph. Writing STL is writing the graph; reading the graph is reading STL. Not another serialization format — a substrate where humans and LLMs co-author structured knowledge.

From STL to STG — language to graph

STL is the language. STG (Semantic Tension Graph) is the graph you build by writing STL. One STL statement equals one STG edge.

What is STG, in one paragraph?

STG is an agent's cognitive knowledge graph, persisted across sessions. Typical scales run from a few thousand to tens of thousands of nodes. Writes happen through STL ingest. Retrieval uses spreading activation (propagate), gravitational community structure, Hebbian reinforcement, and time-aware decay. It is not an external database — it is the agent's memory itself, activated on demand.

The lifecycle of an STL statement inside STG
  • Ingest: stg ingest '[A] → [B] ::mod(...)' parses the STL and stores it as an edge.
  • Activate: stg propagate "keyword" spreads activation and surfaces the relevant subgraph.
  • Reinforce: stg learn path A B C walks a path and raises salience along it.
  • Consolidate: session-end runs prune, save, and Hebbian decay updates.
  • Curate: stg consolidate merges duplicate edges (manual trigger).

Tooling — making STL real

stl_parser — Python library (PyPI)
  • parse(text) / parse_file(path) — STL → ParseResult
  • stl(src, tgt).mod(...).build() — programmatic construction without string concatenation
  • validate_llm_output(text) — three-stage cleanup for noisy LLM output (21 auto-repair rules)
  • to_json() / to_rdf() / to_pydantic() — round-trip conversion
  • stl_diff(a, b) / stl_patch(doc, diff) — semantic-level diff and patch
  • STLGraph / STLAnalyzer — NetworkX-backed graph analysis
CLI — 11 commands

stl validate · stl parse · stl convert · stl analyze · stl build · stl clean · stl query · stl chain · stl diff · stl patch · stl schema-validate

MCP tools — call STL directly inside Claude or other agents
  • validate_stl — check syntax of a single STL line
  • parse_stl — parse into structured JSON
  • analyze_stl — graph analysis (centrality, cycles, degree)
  • validate_stl_file — batch-validate a file
  • time_dimension — extract the temporal axis
Schema ecosystem — domain-specific constraints

Six built-in schemas constrain domain-specific fields: tcm (Traditional Chinese Medicine) · scientific · causal (causal chains) · historical · medical · legal

Path: STL-TOOLS/schemas/

Repositories:
Language spec → github.com/scos-lab/semantic-tension-language
Tool implementations → github.com/scos-lab/STL-TOOLS (PyPI: stl_parser)
Graph engine → github.com/scos-lab/stg-engine (PyPI: stg-engine)