A programming language for agents that makes action, uncertainty, authority, and evidence part of the type system.
Not a plan DSL. Not YAML. Not Python with a policy wrapper. Act is a real programming language — functions, tasks, loops, libraries, modules, types, errors, async, parallelism — where the things agents are bad at accidentally screwing up become compiler-visible: effects, authority, uncertainty, evidence, budgets, secrets, and state.
TypeScript for agents, Rust for side effects,
Temporal for execution, Rego for authority,
built around model calls as first-class expressions.
Pre-alpha. The compiler kernel (lexer, parser, checker, formatter, IR) is
complete, and act-run executes tasks end to end against real models and tools.
A runner/scheduler for long-lived durability (checkpoint resume, replay
storage beyond the process) is the main thing still missing.
- Modules and versioned imports
- Records, enums, unions
Option<T>,Result<T, E>, refinement types- Pure
fn, effectfulproc, durabletask, reactiveagent - Extern tool declarations (typed, effectful, capability-gated, retryable)
- Typed model
inferanddecide(uncertainty-bearing) - Effect rows, static effect checking
- Capabilities (lexical, unforgeable, attenuable)
- Budgets (wall time, tokens, cost, tool calls)
- Bounded
for/await all/await map - Typed durable state cells
try/match/recovererror handlingtrace/check/require/ensure- Typed holes (
??) with structured diagnostics - Canonical formatter with stable AST node IDs
- JSON diagnostics designed for repair by agents
- Compilation to an executable graph IR
Explicitly cut from v1: macros, inheritance, operator overloading, reflection, runtime eval, raw sockets, dynamic imports, unbounded effectful loops, shared mutable memory between agents.
crates/
act-syntax lexer + canonical AST
act-parser parser -> AST
act-diagnostics structured JSON diagnostics
act-check type, effect, capability, taint, budget checking
act-fmt canonical formatter (AST -> source, idempotent)
act-ir lowering to executable graph IR
act-run AST-interpreter runtime + Host (mock / HTTP)
actc CLI
| Code | Rule |
|---|---|
E_EFFECT_MISSING |
A tool/model call requires an effect not declared in scope |
E_UNBOUNDED_LOOP |
An effectful while loop has no max bound |
E_CHECK_UNHANDLED |
check without else bypasses the typed error enum |
E_SECRET_LEAK |
A Secret<T> value flows into a model infer input |
E_STATE_UPDATE_UNGUARDED |
state.update without an expected_version: guard can clobber concurrent writes |
E_COMPENSATION_MISSING |
A non-idempotent write inside a budgeted task has no defer compensate |
E_POLICY_MAY_UNGRANTED |
policy_expect may X but no matching capability is granted |
E_POLICY_MUST_NOT_GRANTED |
policy_expect must_not X but capability X IS granted |
E_REPLAY_WITHOUT_TRACE |
replay trace("X") references a trace that is never recorded |
E_HOLE_UNFILLED |
A typed hole ?? was not filled |
W_MODEL_CONFIDENCE_HIGH_THRESHOLD |
Model confidence threshold >= 0.90 (unreliable self-report) |
cargo build
cargo test
cargo clippy --all-targets -- -D warnings # enforced in CI
cargo fmt --all -- --check # enforced in CIactc lex <file.act> # lex, print tokens
actc parse <file.act> # parse, print a module summary
actc check <file.act> # parse + check, print JSON diagnostics
actc lower <file.act> # parse + check + lower to graph IR, print JSON
actc fmt <file.act> # parse + format to canonical sourceact-run interprets the AST (the IR drops executable detail, so it stays a
structural artifact). It enforces the same guarantees at runtime that the
checker proves statically: budgets (wall time, tokens, cost, tool calls),
optimistic-concurrency state writes, capabilities, and defer compensate on
scope exit. await all branches run on separate OS threads sharing one atomic
budget counter. trace records to the host; replay trace("X") reads it back.
Models and tools are pluggable behind a Host trait. HttpHost calls real
OpenAI-compatible models (via async-openai) and dispatches gh.* calls to the
GitHub REST API. Credentials come from the environment.
# A task that needs no external calls:
actc run examples/<file>.act <task> name=value ...
# Against a real model + GitHub (summarize a file):
OPENAI_API_KEY=... GITHUB_TOKEN=... \
actc run examples/summarize.act summarize \
repo='{"owner":"evalops","name":"act"}' path='"README.md"'examples/fix_regression.act is an end-to-end task: it fetches logs and a diff
in parallel, infers root-cause hypotheses, decides the best patch by weighted
score, opens a pull request, and records a trace an eval can replay.
actc check examples/fix_regression.act # {"ok": true, "diagnostics": []}
actc fmt examples/fix_regression.act # canonicalized sourceMIT.