Language migration guide: 0.3 to 0.6
Language versions are opt-in. Existing explicitly versioned files retain their behavior.
0.3 to 0.4
Add language "0.4"; to use effects, idempotency, deployment requirements, budgets, or evaluations. Existing tasks default to unspecified effects/idempotency. Declare external writes accurately before adding retries; unsafe retries become static errors. Move provider/model settings into deployment JSON when portability matters.
0.4 to 0.5
Add language "0.5"; for parallel map, race, task/tool scheduler limits, and approve. Contextual native handlers should observe Invocation.cancellation. Durable runs should supply both --event-store and a stable --execution-id; resume must use unchanged source and deployment.
0.5 to 0.6
Add language "0.6"; for imports and packages. Visibility now defaults to private, so mark imported APIs public. Replace cross-file global names with alias::name, create agl.json, and check in the generated agl.lock. Generate an API snapshot before a release so breaking changes can enforce a major version bump.
Native extensions declare extension API version 1.
Rust-only implementation
The Python implementation, package, CLI, and task/tool subprocess bridge have been removed. This is a breaking host API change: --plugin, agl::plugins, PYTHON_PROTOCOL_VERSION, and ProtocolEnvelope are no longer available. Language version headers do not restore these host features.
Run programs with agl <source> <pipeline> --input <json>. Move custom task handlers into a Rust Registry and model-callable tool handlers into ToolRegistry; use a Rust host application to register them before execution. See native extensions. Run in-language test blocks against those registries, and use cargo bench --bench runtime for the maintained benchmark.
Control-flow correctness corrections (all versions)
These fixes apply to 0.2–0.6 without a new syntax version:
return,break, andcontinueinside a successfultrynow propagate.- Optional, match, and catch bindings restore shadowed values on every exit.
- Every reachable return must match the pipeline result type. An unrelated valid return no longer hides a mismatch.
- Parallel branches cannot depend on sibling results. Move dependent calls after the join, or execute them sequentially.
- Loop back-edges must preserve entry binding types; break exits participate in the post-loop scope. Use a separate variable when changing a value's type.
- Catch can observe partial execution, so a name must have compatible types at every potential failure prefix to be readable there. Avoid changing an existing variable's type inside a try block; bind the new type to a separate name.
Returning branches no longer hide names supplied by continuing branches. AGL 0.2 still permits fallthrough; 0.3–0.6 require a return on every normally completing path. Diagnostic code AGL2001 is unchanged, but return errors now point to the incompatible expression. Incompatible code may stop passing --check; runtime value encodings and public Rust APIs are unchanged.