DSL β Usage Guide
π Key Concepts
The DSL is how you program Trigger Blocks. Instead of using menus or long settings forms, you write a short, readable rule that says:
- On β what event should trigger
- If β an optional condition to check
- Do β one or more actions the trigger should perform
- Emit β optional outputs that are passed into the workflow
Every rule written in the DSL is directly connected to a tool. That means:
- Events come from the tool (e.g. "email_received", "page_created").
- Variables are pieces of data provided by the tool (e.g. subject, filepath, page_id).
- Capabilities (actions) are what the tool can do (e.g. save_artifacts, set_variable, index_document).
- Emits define what the workflow should output to the next step (commonly
query=...
).
π Key Definitions
- Event: The trigger that starts the rule. Always defined by the tool.
- Predicate (if β¦): A condition written with functions like
not_empty(x)
orcontains(str, 'abc')
. - Action (do β¦): A step that uses a capability from the tool. Each action has a name and parameters.
- Emit: Key-value outputs produced after the actions. Used for passing data or queries into the workflow.
π§© Parsing (Beta)
Every tool in INTELLITHING comes with its own capabilities, variables, types, and hints. To make working with them easier, the parser at the bottom of the toolβs rule configuration lets you create rules using natural language instead of learning the full syntax.
Hereβs how it works:
- Review the toolβs documentation to understand its capabilities and variables.
- Type your desired rule in plain natural language.
- Click Parse.
- The system will generate a fully executable rule for you.
This means you donβt need to memorize each toolβs syntax. Instead, you can write naturally, and the parser will convert it into a valid, execution-ready rule.
π‘ Tip: Use the parser to get started quickly, then fine-tune the generated rule if you need more control.
π Rule Syntax
The general form of a rule is:
- on β required. Must be one of the toolβs supported events.
- if β optional. Condition that decides whether the rule should run.
- do β required. One or more actions, separated by commas.
- emit β optional. Defines query text or payload for downstream blocks.
π Example
Let's say we picked gmail tool and want to create a rule
The tool offers the following which can be found in its documentaion.
βοΈ These are all tool specific
Events offered by this particular tool
email_received
email_sent
Pick one. Your rule only runs when that event occurs.
Variables offered by this particular tool
Available for predicates and templates:
subject
(string) β Email subjectfrom
(string) β Senderto
(string) β Recipient(s)cc
(string) β CC addressesbody
(string) β Body snippet (up to \~2k chars)attachments
(array) β List of attachments (each hasfilename
,mime
,size
,data
)has_attachments
(bool) β Convenience flagid
(string) β Message iddate
(string,YYYY-MM-DD
) β Email dateevent
(string) β Event subtypesaved_paths
(array) β Paths written bysave_artifacts
filepath
(string) β First saved path (set bysave_artifacts
)
Template tokens offered by this particular tool
Resolved by the Gmail tool when you render templates:
{yyyy}
,{mm}
,{dd}
β Current UTC date parts{event}
β Current event{subject_slug}
β Slug from email subject{attachment_name}
β Slug from the current attachmentβs filename
You can mix these with regular DSL placeholders like
{subject}
or{attachments[0].filename]}
.
Capabilities (actions you can call in do ...
)
-
save_artifacts
β Persist all attachments to disk using templates. Params: -
dir_template
(string) filename_template
(string)base_dir
(string)decode_base64
(boolean)
Produces:
saved_paths
(array),filepath
(string)- If multiple files are saved, it also creates per-item emissions with
{"filepath": "...", "query": "This is the file path: ..."}
-
If exactly one file is saved, it sets a top-level
query
to"This is the file path: <path>"
-
set_variable
β Set/override a variable from a template. Params (required): -
name
(string) value_template
(string)
Produces:
- (none directly; it returns
{name: rendered_value}
)
Predicates you can use in if ...
Use simple boolean functions such as:
not_empty(x)
,empty(x)
contains(str, 'needle')
,startswith(s, 'p')
,endswith(s, 's')
equals(a, b)
len_gt(x, n)
,len_lt(x, n)
,len_eq(x, n)
- Combine with
and
,or
,not
, and parentheses.
Bringing it together
Goal:
When a new email with attachments arrives, save all attachments into a dated folder structure and make those file paths available to the workflow. Also set a handy variable for downstream steps and produce a human-readable query
.
Rule:
on email_received if not_empty(attachments)
do save_artifacts(
base_dir='workspace/archive/',
dir_template='gmail/{yyyy}-{mm}-{dd}/',
filename_template='{subject_slug}-{attachment_name}'
),
set_variable(name='latest_file', value_template='{filepath}')
emit query='Saved attachment(s). First file: {latest_file}'
What this does
-
Trigger Runs on
email_received
only. -
Filter (if β¦)
not_empty(attachments)
ensures we only act when the email actually has attachments. -
Action 1 β save_artifacts(...)
-
Where files go
-
base_dir='workspace/archive/'
β everything is rooted here. dir_template='gmail/{yyyy}-{mm}-{dd}/'
β daily folder likeworkspace/archive/gmail/2025-08-23/
.-
How files are named
-
filename_template='{subject_slug}-{attachment_name}'
β slugified subject + slugified original filename (the adapter provides both tokens). -
Outputs
-
Sets
saved_paths
(array) for all saved files. - Sets
filepath
to the first saved file path. - If there are multiple attachments, the action also returns per-file emissions with a ready-made
query
for each item ("This is the file path: <path>"
). -
If there is only one attachment, it sets a top-level
query
with that text. -
Action 2 β set_variable(...)
-
Creates/updates
latest_file
with the value of{filepath}
(the first saved path from the prior action). -
This is convenient for downstream blocks to refer to βthe first fileβ without re-indexing arrays.
-
Emit
-
Emits a final
query
for the workflow:Saved attachment(s). First file: {latest_file}
- If
save_artifacts
produced per-item emissions (multiple attachments), your workflow will also receive those itemized emissions, each with its ownfilepath
andquery
. The workflow can fan-out or iterate as designed.
Resulting data available to downstream blocks
latest_file
β path to the first saved filefilepath
β same as above (fromsave_artifacts
)saved_paths
β list of all saved pathsquery
β the rule-level summary you emitted- For multi-file emails: a list of emissions each containing
filepath
and a per-itemquery
Authoring Checklist
- Pick an event:
email_received
oremail_sent
. - Narrow with a predicate (optional): e.g.,
not_empty(attachments)
. -
Choose actions from this tool only:
-
save_artifacts(...)
(dir/file templates; optional base dir; optional base64 decode) set_variable(name, value_template)
-
Use templates inside params and
emit
: -
Regular variables:
{subject}
,{from}
,{attachments[0].filename]}
- Gmail adapter tokens:
{yyyy}
,{mm}
,{dd}
,{subject_slug}
,{attachment_name}
- Emit a concise
query
(and/or additional key/value pairs) your workflow can display or pass along.
Tips & Pitfalls for this particular example
- No attachments? Predicate should guard the action: use
if not_empty(attachments)
to avoid a no-op. - Multiple attachments: Expect per-item emissions from
save_artifacts
with per-file queries. - Single attachment: A top-level
query
is set bysave_artifacts
; you can still override/augment with your ownemit
. - Wonβt overwrite with empty values:
set_variable
skips replacing an existing non-empty value with an empty string. - Date tokens are UTC-based for
{yyyy}
,{mm}
,{dd}
. - Processed once: The connector marks processed messages as seen to avoid reprocessing on later intervals.
Summary
- DSL is how you program trigger blocks to start workflows.
- Each tool defines events, variables, and capabilities in its own doc section.
- The DSL stitches them together with the pattern: