Reference
Capabilities index
Deny-by-default: declare with require capability("scope"). See Capabilities & intent for the model.
-- Doc example: deny-by-default capabilities + faithful scope.
-- Uses `secret` because it proves the model with no network/disk side effects.
intent: "doc example: capabilities and intent"
require secret("APP_*") -- name-prefix scope: covers APP_KEY, APP_DB, ... only
task read_app_key()
-- APP_KEY is under the declared APP_* scope → allowed (still redacted, as always)
give text(secret("APP_KEY", "demo")) == "secret(APP_KEY)"
task read_unscoped()
-- DB_PASSWORD is NOT under APP_* → denied at the capability check (before any use)
give secret("DB_PASSWORD")
print("APP_KEY is in scope → " + text(read_app_key()))
test "a capability you declared (in scope) is allowed"
assert(read_app_key())
test "anything outside the declared scope is denied (deny-by-default)"
assert_error(read_unscoped)| Capability | Gates | Scope | Auto-granted in run? |
|---|---|---|---|
stdout | print / output | — | yes |
time | now, format_time, sleep | — | yes |
llm | reason/decide/analyze/generate, llm_step (incl. provider egress) | — | yes |
random | random, random_int, random_bytes, token, push_vapid_keys (v0.6.15+) | — | no (tokens/nonces) |
net | http*, fetch, ws_connect, push_send (v0.6.15+ — host of the subscription's endpoint: the push service) | host: net("api.x"), net(".x"), net("") | no |
file | read and write | path: file("/data/*") | no |
file.read / file.write | least-privilege I/O; file.read also gates watch(path) (v0.6.9+ — watching a tree is reading it) | path glob | no |
db | sql/mongo_/redis_ | path (SQLite) or canonical URL | no |
secret | secret(...) | name: secret("APP_*") | no |
reveal | reveal(...) | name/label (scoped) | no |
sign | secp256k1_sign / ed25519_sign (blockchain) | key secret's name (audited) | no |
wallet | create custody: mnemonic_ / hd_derive / keystore_ | source secret's name (audited) | no |
spend | spend(amount, unit, reason) — audited money declaration (spend.log, ceiling SYNSEMA_SPEND_CEILING) | unit name or trailing-* prefix: spend("USD") | no (never — like sign) |
exec | run (one-shot) and proc_spawn (live process, v0.6.7+; pty: true v0.6.8+ — no extra capability, a pty grants no OS power a pipe lacks) | command name | no |
serve | serve on N | port | no (and required) |
env | env(...) | name / prefix | no |
stdin | read_line, free-text ask; term_open (v0.6.11+ — the interactive terminal, raw mode) | — | no |
memory | persistent state family: remember/recall/forget_memory/memory_summary, add_rule/check_rules/get_rules, create_progress/…/resume_point | declared name = the .db identity: memory("agent-name") (ceiling prefix: memory=shop-*) | no (writes files; the declaration IS the identity) |
sandbox_run (v0.6.14+) | run_program(source, opts) — run another Synsema program in a child process under a ceiling ∩ the parent's | — (no scope) | no |
Notes: path scopes are faithful (.. escapes denied; matched case-insensitively on Windows/macOS). sandbox strips everything. A per-task require narrows a task to only what it declares (∩ the program). Under serve/secure mode, even the auto-granted ones must be declared. In --cap-set, none is an empty ceiling (nothing, not even stdout). What the program reads via a template (render/include/layout of a disk file) is gated by file.read too, like read_file — templates baked into a synsema build binary are part of the program and need no capability.