Effects Catalog
An effect row is the part of a function’s type that names the authority the
function may exercise: def f(x: T) -> R !{fs.read, model.invoke}. This page is the
authoritative catalog of the capabilities a row may name. For how rows are inferred,
declared, and checked, see Functions & Effects;
for how they are granted and confined, see
Effects & Capabilities.
The deterministic core: !{}
Section titled “The deterministic core: !{}”A function typed with the empty row !{} provably performs no model calls and
no I/O. It is a type-enforced sublanguage, not a convention — the deterministic core
of Sema. An omitted row is not a wildcard: it asks the compiler to infer the
minimal row from the body, which is fail-closed (a function that touches nothing
infers !{}). Authority is always conspicuous.
def add(a: int, b: int) -> int !{}: # provably pure — no model, no I/O return a + b
def load_config(path: str) -> Config !{fs.read}: # authority is stated ...!{*} is the explicit all-effects top (⊤) — a loud, greppable escape hatch for
spikes and REPL work, not the meaning of silence. sema check warns on it at
bronze and errors at silver+.
The catalog
Section titled “The catalog”Every capability belongs to a namespace (fs, net, model, …) and names a
specific operation (fs.read, model.invoke, …). The table below is the
authoritative set of effect capabilities and the constructs that typically require
them. Effect instances are parameterized — net.connect("api.internal:443"),
fs.read("data/**") — and policies match on those instances (see below).
| Effect | Meaning | Typically required by |
|---|---|---|
fs.read |
Read files under the project root (read, list, stat). | File reads: io/fs reads, config loading, read_* helpers. |
fs.write |
Write, append, copy, or remove files under the project root. | File writes: report/artifact output, snapshots, caches on disk. |
net.connect |
Open an outbound network connection (HTTP/HTTPS). | net.* fetches, service calls to a remote endpoint, remote model APIs. |
net.listen |
Bind and accept inbound connections. | Serving an HTTP endpoint / a service that listens. |
model.invoke |
Call a generative model (text/tool generation). | simulate def … by <model>; the ~ semantic operators (~=/~!=/~</~in/~[query]/…) when calibrated; semantic.* verbs (filter/rank/map/classify/extract/summarize/translate/cluster/dedup/…); check/ensure semantics(…). |
model.embed |
Compute embeddings for a value. | ~= and similarity when a type coerces via embed; semantic.cluster/dedup; explicit embed(...). |
model.configure |
Configure/select a model resource (bind roles, calibration, sampling). | Model registry setup and with model(...) rebinding; pinning a judge/calibration for a decision site. |
observe.record |
Record telemetry to the run journal. | collector channels and the ` |
db.read |
Read from the database (queries). | db.query/db.read; typed sql"…" SELECTs. |
db.write |
Write to the database (insert/update/exec). | db.exec/db.insert; typed sql"…" writes. |
db.path |
Bind the database to a filesystem path. | Selecting the embedded SQLite location ([db] path). |
db.url |
Bind the database to a DSN. | Selecting a database by DSN ([db] url), including a @provides("db") backend. |
env.read |
Read the process environment. | env.* reads; configuration sourced from the environment. |
env.write |
Write the process environment. | env.* writes that set variables for the run. |
proc.run |
Run a subprocess and read its result. | proc.* invocations that shell out (returns {stdout, stderr, code}). |
ui.notify |
Emit a user-facing notification/alert. | Alerts and user prompts routed to the terminal/UI. |
ui.render |
Render user-facing output. | Rendering to the terminal/UI. |
memory.read |
Read the in-process key/value store. | std.cache @memoize (in-run memo), scratch state across a run. |
memory.write |
Write the in-process key/value store. | @memoize cache fills; ephemeral run-scoped state. |
event.emit |
Publish a domain event. | emit in the event/emit/subscriber system (Events). |
code.* |
Generate, patch, or evaluate staged code. | reflect/Code[T]/runtime eval; supervise/heal code repair. |
ffi.call |
Call foreign (e.g. Python) functions. | native/ported interop and ffi.call (Python Interop). |
clock.read |
Read the (deterministic) clock. | Timestamps; time-budgeted work. Returns a fixed epoch so runs replay identically. |
random.* |
Draw randomness (seeded/deterministic). | Sampling, jitter, shuffles — reproducible under a fixed seed. |
config.* |
Read or bind configuration. | The config/DI layer and sema.toml-sourced settings (Packaging). |
package.* |
Package-manager operations. | Dependency resolution / install (sema add/remove). |
policy.* |
Install or scope a policy. | with policy(...) and policy administration (Policy). |
human.* |
Request human input or approval. | Human-in-the-loop approval, supervise/heal escalation. |
Namespace discipline
Section titled “Namespace discipline”Sema separates two things that look similar:
- Declaring a capability is open. An effect row may name any capability, so
!{fs.raed}still parses — rows are intentionally extensible, and a later real capability shows up as a signature diff, not a silent change. - Calling an operation is checked. Calling an operation resolves like any
builtin. A call to an unrecognized op on a known namespace —
fs.raed("x"),model.invok(...)— raises aNameErrorat the call site rather than silently journaling an effect and returningNone. Each namespace has a recognized callable surface; typos are caught, not swallowed.
Statement position is guarded the same way: an unknown word …: directive parses as
inert (the declarative-config escape), but sema check warns on any directive
in a def/simulate body that no runtime handler recognizes — so a misplaced or
misspelled clause surfaces at check time instead of doing nothing at runtime.
def fetch(url: str) -> Response !{net.connect}: return net.fetch(url) # ok — net.fetch is a recognized net op
def broken(url: str) -> Response !{net.connect}: return net.ftech(url) # NameError at the call site — not a silent NoneHow policy constrains effects
Section titled “How policy constrains effects”A function’s row is an upper bound on the authority it may use; a policy
grants and confines that authority, matching on effect instances:
policy ReadOnlyData: allow: fs.read("data/**") forbid: fs.write forbid: net.connect examples: - fs.read("data/reports/q3.json") -> allow - fs.write("data/out.json") -> deny
with policy(ReadOnlyData): load_inputs() # may read data/**, may not write or connectPolicy examples are verified at load (sema check errors if an examples:
entry contradicts the rules). Confinement is transitive over closures: a closure
created under a policy that forbids a capability stays forbidden even when it is
invoked elsewhere. The runtime is an effect-handler stack, so policy enforcement,
record/replay, mocking, and batching are all handlers over these same operations —
one mechanism, applied per function row (and, for net, per endpoint).
See also
Section titled “See also”- Effects & Capabilities — granting and confining authority.
- Functions & Effects — how rows are written and inferred.
- Policy — the full
policyconstruct. - CLI reference —
sema check(row discipline) andsema assure --grade silver(explicit rows required).