Skip to content

evalops/act

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

27 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Act

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.

Status

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.

Kernel scope (v1)

  • Modules and versioned imports
  • Records, enums, unions
  • Option<T>, Result<T, E>, refinement types
  • Pure fn, effectful proc, durable task, reactive agent
  • Extern tool declarations (typed, effectful, capability-gated, retryable)
  • Typed model infer and decide (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 / recover error handling
  • trace / 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.

Layout

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

What the compiler enforces

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)

Build & test

cargo build
cargo test
cargo clippy --all-targets -- -D warnings   # enforced in CI
cargo fmt --all -- --check                  # enforced in CI

CLI

actc 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 source

Runtime

act-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"'

Example

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 source

License

MIT.

About

A programming language for agents — effects, authority, uncertainty, and evidence in the type system.

Resources

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages