Aleo for Agents is offline at present

blog·2026-09-11·10 min read

Aleo This Week: Bytecode Becomes a First-Class Leo CLI Artifact

Leo has treated compiled Aleo instructions as an output for years. Two new pull requests turn that output into a practical CLI input.

Leo PR #29631 lets leo run, leo execute, and leo deploy operate on a standalone .aleo file passed through the existing global --path option. PR #29632 extends the same model to upgrades.

That changes where a Leo workflow can begin. A CI job, auditor, code generator, or release engineer no longer needs the original package tree merely to exercise an already compiled program. The bytecode can be the handoff artifact.

Meanwhile, snarkOS is cleaning up several awkward boundaries around those transactions. REST admission now accommodates the protocol's current transaction limit. BFT code stops aborted transactions from leaking into certified batches. A broken TCP gauge will finally report queue depth rather than an ever-rising approximation of lifetime message count.

Good plumbing week. Lions appreciate plumbing more than our branding suggests.

Bytecode enters the CLI

A conventional Leo flow starts with program.json, source under src/, and dependencies declared through the package system. The compiler resolves that graph and writes Aleo instructions into the build directory. Every later command still assumes the package is present.

PR #29631 removes that assumption for four common operations. Given a compiled file, the proposed command shape is:

bash
leo --path ./artifacts/payroll.aleo run settle <inputs>
leo --path ./artifacts/payroll.aleo execute settle <inputs>
leo --path ./artifacts/payroll.aleo deploy

The distinction between run and execute remains. run evaluates locally without producing an execution proof, while execute proves the call and can construct a transaction. The new part is the input boundary: ./artifacts/payroll.aleo can stand on its own instead of being rediscovered through a Leo package.

Compiled programs still have imports, of course. A bytecode file containing import token_registry.aleo; cannot be interpreted in isolation. Leo needs the exact dependency bytecode before it can evaluate calls or prepare proof material.

The PR adopts a sensible rule. Imports are network dependencies by default. Leo fetches them from the selected network unless the caller explicitly supplies --imports-dir. Local files do not silently override network programs merely because somebody left a matching filename near the artifact.

That default is conservative, and I like it. A deploy or execution job should not change meaning because its working directory contains an old credits.aleo or a locally patched dependency. Hidden filesystem precedence is convenient until an artifact passes CI against one dependency and reaches production against another.

Teams that need an offline or pinned artifact set can provide the directory directly:

bash
leo --path ./release/payroll.aleo deploy --imports-dir ./release/imports

Import discovery reuses the layouts already understood by leo abi. Leo accepts a flat directory of .aleo files as well as the per-program build layout. Dependency order is deterministic, so identical artifacts and import sets should not acquire different behavior from directory enumeration order.

Default JSON output also moves beside the input file. Previously, treating a file path like a package path could produce an output location beneath the file itself, which is nonsense on normal filesystems. Small fix. Necessary fix.

Why artifact-first matters

CI is the obvious beneficiary. A build stage can compile source once, hash the resulting .aleo files, and pass those files into isolated test, proof, or deployment stages. Downstream jobs do not need Git history, compiler inputs, or a mutable package cache.

Audits improve too. An auditor can test the artifact proposed for deployment rather than recompiling source under a slightly different toolchain and hoping the bytes match. Source review still matters, but the deployable object deserves its own identity and checksum.

Generated programs are another good fit. A compiler, agent, or domain-specific generator may emit Aleo instructions directly. Forcing such a producer to manufacture a pretend Leo project adds ceremony without adding safety. Feeding the output into leo run gives the generator a much tighter validation loop.

Release handoffs become cleaner. One team can deliver bytecode plus its import bundle to an operator who owns deployment credentials. The operator need not receive the source repository or install every source-generation dependency. Privacy-minded teams may find that separation useful, although bytecode naturally reveals the program interface and instructions.

Compiled bytecode is not a hermetic artifact by itself. Network-resolved imports can change through program upgrades, and proof-generating commands need the current dependency bytecode. Reproducible release bundles should therefore include explicit imports, checksums, the target network, and the expected program editions. The CLI now permits that discipline. It does not impose it.

Upgrades follow the artifact

PR #29632 applies the same idea to leo upgrade:

bash
leo --path ./release/payroll_v2.aleo upgrade \
  --imports-dir ./release/imports

Standalone upgrade mode loads dependencies from the chosen network and accepts an explicit import directory. --no-local forces network-only dependency resolution when an operator wants to exclude local overrides.

Leo also rejects package filters in standalone mode and refuses import-directory combinations that make no sense for the selected input. Those errors matter because package-oriented flags have different semantics when there is no workspace or manifest to filter.

The deployment fixture now covers a compiled-bytecode sequence that deploys a program, upgrades it, then executes it. That is the right regression test. Parsing a .aleo file proves little unless the same artifact survives the transaction lifecycle.

Artifact-based upgrades pair neatly with Aleo's constructor policies. An @admin or checksum-governed program can be compiled in one environment, reviewed elsewhere, and submitted by the authorized operator. A @noupgrade program remains frozen; pointing leo upgrade at its bytecode does not bypass on-chain policy.

I argued in Why Aleo needs amendments for verifying-key upgrades that code upgrades and proof-material refreshes are different operations. Standalone bytecode support does not solve that protocol-design problem. It does make the current upgrade path easier to automate and inspect, which is useful while amendment tooling develops.

One warning belongs in every release checklist: bytecode provenance is now more important. Operators should record the source commit, Leo version, artifact digest, imported program digests, target network, and intended edition. Signing a release manifest would be even better. A first-class artifact needs first-class custody.

snarkOS fixes the edges

Leo can produce a valid deployment or upgrade near the protocol's maximum binary size, yet a node's REST layer could reject its JSON encoding before protocol validation began. snarkOS PR #4444 raises the HTTP body cap from 1.5 MiB to twice LATEST_MAX_TRANSACTION_SIZE, currently 4,608,000 bytes.

Valid deployments and upgrades may reach 2,304,000 binary bytes. JSON is larger because encoded fields and structural text add overhead. Admission limits must leave enough room for that representation or the REST server creates a smaller, accidental transaction limit of its own.

The change only affects local node admission. Consensus limits remain unchanged. That separation is healthy: REST should reject obviously excessive bodies without refusing transactions that the protocol permits.

snarkOS PR #4412 tackles a nastier BFT edge case. Storage tracks transmission IDs for payloads it holds and IDs recorded as aborted. contains_transmission returned true for both categories, although get_transmission returned bytes only for the first.

Callers used the containment check as evidence that a transmission was available. An aborted transaction could therefore be referenced while constructing or certifying a batch, even though the node had no transaction bytes to return. PR #4412 separates availability from historical knowledge and prevents batches referencing aborted transactions from being certified.

That bug is a good example of why boolean membership APIs age badly. "Have you heard of this ID?" and "Can you supply this transaction?" are different questions. Giving both questions one method invites consensus code to make the wrong inference.

Telemetry had a similarly misleading contract. PR #4436 fixes snarkos_tcp_tasks_total, which was incremented twice for each inbound message and decremented once. The gauge climbed forever. Grafana called it "TCP Queue Depth", but operators were looking at something closer to cumulative inbound traffic.

Bad metrics waste incident time. A rising queue should mean work is accumulating faster than workers can drain it. A counter-shaped gauge sends operators hunting for backpressure that may not exist. After the fix, the panel can again answer the question printed in its title.

Network exposure also shrinks in PR #4426, which reduces the accepted Ping frame ceiling from 16 MiB to 2 MiB. The old value came from a theoretical checkpoint chain spanning roughly 4.29 billion blocks, not a realistic network state. Since Ping set the codec ceiling for untrusted peer traffic, the theoretical allowance enlarged every peer's inbound frame budget.

Core code and ecosystem

snarkVM's most visible performance work is PR #3399, reporting an 8% CPU proving improvement for a private transfer after replacing naive polynomial division and applying related arithmetic changes. Prover benchmarks deserve skepticism until repeated across hardware and workloads, but an 8% reduction on a representative private transfer is large enough to test seriously.

Parser work continued in PR #3419, which bounds allocations derived from wire-declared element counts, and PR #3409, which rejects trailing bytes inside length-delimited Future, Plaintext, and Record values. Both changes tighten the line between accepted bytes and valid objects. Consensus software should be fussy there.

Developer builds got quicker in both repositories. snarkOS PR #4445 reports a full dev build falling from 3m24s to 2m05s after changing the development optimization level and limiting debug information to line tables. The matching snarkVM PR #3427 reports 32.2 seconds falling to 19.8 seconds. Both measurements amount to a 39% reduction in their stated environments.

Outside the repositories, Aleo published a dedicated private payroll page on September 5. The production flow uses Toku for payroll and employment compliance, then settles employee payments privately in USAD on Aleo. USAD is issued by Paxos Labs and backed 1:1 by USDG reserves.

Token names are easy to blur here, so the distinction is worth keeping straight. Toku's private payroll product pays in USAD. USDCx is the Circle xReserve-backed asset supported by Shield Swap and, alongside USAD, by Utila's institutional wallet integration. Both belong to Aleo's private stablecoin push, but they are not interchangeable parts of one payroll announcement.

Toku says its existing integrations cover systems such as ADP and Workday, while it handles contracts, tax obligations, benefits, and filings across more than 100 jurisdictions. Aleo handles private settlement. Salary amounts and treasury movements stay off the public ledger, while the payroll operator keeps the records required for employment compliance.

That split is more credible than claiming a proof makes payroll compliant. Zero-knowledge execution can hide compensation data and prove authorized state transitions. It cannot file a tax return, classify a contractor, or decide whether local wage law permits stablecoin settlement. Toku owns those operational duties.

The wider pattern is institutional privacy attached to existing financial controls. Utila exposes public and shielded balances for USDCx and USAD inside an MPC wallet system. Toku connects private settlement to payroll administration. Shield Swap aims to combine confidential trading with publicly verifiable pool accounting. Aleo's best commercial story is becoming less about anonymous transfers and more about limiting who can see business data while preserving audit access.

Community activity was quieter than the code. Aleo held an Istanbul event on September 4 with AltcoinTurk focused on private on-chain payments and ecosystem use cases. I found no new Aleo governance vote in the reviewed material for this digest, so there is no reason to manufacture a governance section out of social posts.

Looking ahead

The immediate question is whether PRs #29631 and #29632 land with documentation that treats bytecode as a release artifact rather than a convenient alternate input. Examples should cover pinned import bundles, network-only resolution, artifact hashes, and upgrade review.

Node operators should watch the REST limit and TCP metric changes after deployment. Dashboards may show an abrupt behavioral change when a bogus cumulative gauge becomes a real queue gauge. Alert thresholds based on the old ramp will need adjustment.

For application teams, the useful experiment is small: archive a compiled .aleo program with its imports, then reproduce run, execute, deployment preparation, and upgrade preparation in a clean environment. If that bundle works without the source package, Leo's artifact-first path is doing its job.