Writing HashQL J-Expr
SkillFiles & storageHashQL J-Expr syntax for writing queries. Use when writing J-Expr code, using #literal/#struct/#list constructs, understanding function call syntax, or working with HashQL query files (.jsonc).
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Writing HashQL J-Expr skill
What this skill tells your AI
The instructions your AI receives, as published by hashintel/hash in .agents/skills/writing-hashql-jexpr/SKILL.md and read by ahel’s review.
J-Expr is a JSON-based expression syntax for HashQL. It represents typed expressions using JSON primitives.
Expression Types
J-Expr has three expression types:
| JSON Type | J-Expr Meaning |
|---|---|
| String | Path/identifier/symbol |
| Array | Function call |
| Object | Data constructor (with # keys) |
Paths (Strings)
Strings are parsed as paths or identifiers:
"x" // Simple variable
"vertex.id.entity_id" // Dotted path access
"::core::types::String" // Namespaced/rooted path
"::graph::head::entities" // Graph function path
Function Calls (Arrays)
Arrays represent function calls: [function, arg1, arg2, ...]
// Basic function call
["add", {"#literal": 1}, {"#literal": 2}]
// Namespaced function
["::graph::head::entities", ["::graph::tmp::decision_time_now"]]
// Labeled argument with :prefix in object
["greet", {":name": {"#literal": "Alice"}}]
// Shorthand labeled argument (string with :prefix)
["func", ":name"]
Data Constructors (Objects with # Keys)
Objects with special # keys construct data:
| Key | Purpose | Example |
|---|---|---|
#literal | Primitive values | {"#literal": 42} |
#struct | Named fields | {"#struct": {"x": ...}} |
#list | Variable-size ordered | {"#list": [...]} |
#tuple | Fixed-size ordered | {"#tuple": [...]} |
#dict | Key-value map | {"#dict": {"k": ...}} |
#type | Type annotation | Used with other keys |
Literals
{"#literal": 42}
{"#literal": "hello"}
{"#literal": true}
{"#literal": null}
{"#literal": 3.14, "#type": "Float"}
Struct
{"#struct": {"name": {"#literal": "Alice"}, "age": {"#literal": 30}}}
{"#struct": {"x": {"#literal": 1}}, "#type": "Point"}
List and Tuple
{"#list": [{"#literal": 1}, {"#literal": 2}]}
{"#tuple": [{"#literal": 1}, {"#literal": "text"}]}
Dict
{ "#dict": { "key": { "#literal": "value" } } }
Common Patterns
Let Binding
["let", "varName", { "#literal": 10 }, ["add", "varName", { "#literal": 5 }]]
Function Definition
["fn", {"#tuple": []}, {"#struct": {"vertex": "_"}}, "_", body_expr]
Conditionals
["if", condition_expr, then_expr, else_expr]
Comparison
["==", "left", "right"]
[">", {"#literal": 5}, {"#literal": 3}]
Do
- Use
#literalfor all primitive values (numbers, strings, booleans, null) - Use
::prefix for namespaced paths - Use
:prefix for labeled arguments - Combine
#typewith other constructors for type annotations
Don't
- Don't use bare JSON numbers/booleans - wrap in
{"#literal": ...} - Don't confuse
#list(variable-size) with#tuple(fixed-size) - Don't use
#prefix for labeled arguments (use:) - Don't nest
#keys incorrectly - each object should have one primary#key
Examples
Entity query:
["::graph::head::entities", ["::graph::tmp::decision_time_now"]]
Filtering with comparison:
[
"filter",
"entities",
[
"fn",
{ "#tuple": [] },
{ "#struct": { "entity": "_" } },
"_",
["==", "entity.draft_id", { "#literal": null }],
],
]
Struct with type:
{ "#struct": { "value": { "#literal": 100 } }, "#type": "Amount" }
References
- Syntax Reference - Paths, function calls, operators
- Special Forms - Language constructs (
if,let,fn,type,use, etc.) - Data Constructors - Typed data (
#literal,#struct,#tuple,#list,#dict,#type) - Type DSL - Embedded type annotation syntax
- Parser:
libs/@local/hashql/syntax-jexpr/src/parser/ - Object forms:
libs/@local/hashql/syntax-jexpr/src/parser/object/ - Type DSL:
libs/@local/hashql/syntax-jexpr/src/parser/string/type.rs
Signals
- GitHub stars
- 2k
- Forks
- 122
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
writing-hashql-jexpr- Source
- github.com/hashintel/hash