Referencia
Índice de capacidades
Deny-by-default: se declara con require capability("scope"). Ver Capacidades e intent para el modelo.
-- 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)| Capacidad | Gatea | Scope | ¿Auto-otorgada en run? |
|---|---|---|---|
stdout | print / salida | — | sí |
time | now, format_time, sleep | — | sí |
llm | reason/decide/analyze/generate, llm_step (incl. egress al proveedor) | — | sí |
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 del endpoint de la suscripción: el push service) | host: net("api.x"), net(".x"), net("") | no |
file | lectura y escritura | ruta: file("/data/*") | no |
file.read / file.write | I/O de mínimo privilegio; file.read también gatea watch(path) (v0.6.9+ — mirar un árbol es leerlo) | glob de ruta | no |
db | sql/mongo_/redis_ | ruta (SQLite) o URL canónica | no |
secret | secret(...) | nombre: secret("APP_*") | no |
reveal | reveal(...) | nombre/label (scopeado) | no |
sign | secp256k1_sign / ed25519_sign (blockchain) | nombre del secret de la clave (auditado) | no |
wallet | crear custodia: mnemonic_ / hd_derive / keystore_ | nombre del secret de origen (auditado) | no |
spend | spend(monto, unidad, motivo) — declaración auditada de dinero (spend.log, techo SYNSEMA_SPEND_CEILING) | nombre de unidad o prefijo con * final: spend("USD") | no (jamás — como sign) |
exec | run (one-shot) y proc_spawn (proceso vivo, v0.6.7+; pty: true v0.6.8+ — sin capability extra, un pty no da poder del SO que un pipe no tenga) | nombre del comando | no |
serve | serve on N | puerto | no (y exigida) |
env | env(...) | nombre / prefijo | no |
stdin | read_line, ask de texto libre; term_open (v0.6.11+ — la terminal interactiva, raw mode) | — | no |
memory | la familia de estado persistente: remember/recall/forget_memory/memory_summary, add_rule/check_rules/get_rules, create_progress/…/resume_point | nombre declarado = la identidad del .db: memory("agent-name") (prefijo en el techo: memory=shop-*) | no (escribe archivos; la declaración ES la identidad) |
sandbox_run (v0.6.14+) | run_program(source, opts) — corre otro programa Synsema en un proceso hijo bajo un techo ∩ el del padre | — (sin scope) | no |
Notas: los scopes de ruta son fieles (los escapes con .. se deniegan; se comparan sin distinguir mayúsculas en Windows/macOS). sandbox despoja todo. Un require por-task acota la task a solo lo que declara (∩ el programa). Bajo serve/modo seguro, incluso las auto-otorgadas deben declararse. En --cap-set, none es un techo vacío (nada, ni siquiera stdout). Lo que el programa lee vía un template (render/include/layout de un archivo en disco) también lo gatea file.read, como read_file — los templates horneados en un binario synsema build son parte del programa y no necesitan capability.