Symbiont DSL Specification¶
This specification reflects the actual grammar in
crates/dsl/tree-sitter-symbiont/grammar.js, which is the source of truth. For a practical, example-driven walkthrough see the DSL Guide. Agent files use the.symbiextension (legacy.dslis still recognized). Validate any file withsymbi dsl -f agents/<name>.symbi.
Overview¶
The Symbiont DSL is a declarative language for defining governed agents, their policies, supporting types, and runtime integrations (schedules, channels, memory, webhooks). A program is a sequence of top-level items.
Top-level items¶
A program is any number of:
metadata { ... }— document metadataagent name(params) -> Type { ... }— an agent definitionpolicy name { ... }— a named policytype Name = ...— a type alias or structfunction name(params) -> Type { ... }— a free functionschedule name { ... }— a cron schedulechannel name { ... }— an inter-agent channelmemory name { ... }— a persistent memory storewebhook name { ... }— webhook ingestion- comments
Metadata¶
metadata {
version = "1.0.0"
author = "ThirdKey"
description = "..."
tags = ["category", "use-case"]
}
Each pair is identifier = (or :) value, where a value is a string,
number, boolean, identifier, array, or record. Managed-CLI (Mode B) agents also
recognize executor, model, allowed_tools, and system_prompt — see the
DSL Guide.
Agent definition¶
agent name(param: Type, ...) -> ReturnType {
capabilities = ["read", "analyze"]
policy policy_name {
allow: read(input) if true
deny: write(any)
}
with memory = "ephemeral", sandbox = "tier1" {
result = process(input);
return result;
}
}
The parameter list and -> ReturnType are optional. The only items allowed
inside an agent body are: capabilities, policy, function, with blocks,
and comments.
Capabilities¶
An array of strings (the separator may be = or :).
Policies¶
policy name {
allow: <expr> [if <expr>]
deny: <expr> [if <expr>]
require: <expr> [if <expr>]
audit: <expr> [if <expr>]
}
Each rule is one of allow / deny / require / audit, then :, then an
expression, then an optional if <expr> guard. Policies may also appear at the
top level and inside channel blocks.
with blocks¶
Zero or more identifier = value (or array) attributes, comma-separated,
followed by a block. Attributes the runtime understands include sandbox
(docker/tier1, gvisor/tier2, firecracker/tier3, e2b), timeout,
memory, security, and others; unrecognized attributes parse but are ignored.
Functions¶
Types¶
Built-in types: String, int, float, bool. Generics use angle brackets
and may take multiple arguments: Map<K, V>, Result<T, E>. User-defined types:
Statements¶
Statements appear inside blocks. Most statements must end with ;:
let x = <expr>;- assignment:
x = <expr>;(also+=,-=,*=,/=,%=; the left side may be a member/index expression) return <expr>;(the expression is optional)- expression statement:
<expr>; if <expr> { ... } else { ... }— alsoif let pattern = <expr> { ... };elsemay chain anotherifor a blockfor x in <expr> { ... }match <expr> { pattern => result, _ => result }try { ... } catch (e) { ... }(one or morecatchclauses; a catch binds an identifier)
A block may end with a trailing expression (no ;), which becomes the block's
value. There is no while loop.
Expressions¶
Precedence, lowest to highest: ||, &&, equality (==, !=, in),
comparison (<, >, <=, >=), additive (+, -), multiplicative
(*, /, %), unary (!, not, -), postfix, primary.
- Boolean operators are
&&and||—and/orare not keywords. Negation is!ornot. - Postfix: member access
a.b, function callf(x, y), indexinga[i]. - Calls accept positional and named arguments:
f(a, name = b)(named-arg separator may be=or:). - Record / struct literals:
TypeName { field: expr, ... }or{ field: expr }. - Lambda:
x => expr. if <expr> { ... } else { ... }is also usable as an expression.- Grouping
( <expr> ), arrays[a, b], and vault referencesvault://path/to/secret.
Literals¶
- String:
"..."with\escapes. (No string interpolation.) - Number:
42,1_000,3.14. - Boolean:
true,false. - Duration:
30s,5m,2h,7d,1w,6months,1y, and theN.seconds/N.minutes/N.hoursforms. - Identifier:
[a-zA-Z_][a-zA-Z0-9_]*.
Comments¶
Both // and # introduce line comments. (There is no block-comment syntax.)