Summary
Pure blocks (record, calculation, rule, label) stay free of IO. Effectful work uses external, action, and policy.
external
Declare npm or Node imports with typed signatures:
See examples/external.point and examples/action.point.
Externals are impure boundaries. Calculations should not call them directly.
action
Async operations with explicit effect metadata:
module Effects
external node fs
read file(path: Text): Text from "node:fs" as readFileSync
action load config
input path: Text
output contents: Text
touches file
return read file(path)touches values include network, file, env, process, time, random, database, or none. Action calls inside other actions or workflows require await (missing-await if omitted).
Database actions declare touches database so point index and review tools see the IO boundary. Use parameterized queries only — see Database interop.
policy and guard
Pure boolean guards:
See examples/policy.point.
Forms: allow expr, deny expr, require expr.
`guard output paths` scopes file writes in pipelines — see examples/pipelines/guarded-output.point.
Compiler note
external— import boundary with typed signatureaction— async IO withtouchesmetadatapolicy/guard— pure boolean checks (pipeline guards scope file paths)
Examples
examples/external.point— externalsexamples/action.point— file touchexamples/async.point— awaitexamples/policy.point— policiesexamples/app/notes/notes.point— database actions
Common mistakes
- Calling an action without
awaitinside another action - Returning
Errorwhere a non-result type is expected
Agent diagnostic notes
- Action refs in
point indexincludeeffectsmetadata for review - Prefer patching
.pointwhen fixing effect boundaries
