What Is the .cact File Format and How Does It Handle Engine Versioning in Needle 2?

The .cact file is a self-contained binary archive that bundles trained model weights with the Needle 2 inference engine, and it is strictly version-locked to the specific engine build that created it.

The .cact format serves as the portability layer for tuned models in the cactus-compute/needle repository. When you run needle build, the exporter in needle/model/export.py compresses weights—including any merged LoRA adapters—into a single archive. This file contains everything required for inference: no separate checkpoint files, tokenizers, or configuration files are needed.

How the .cact Archive Is Created

The needle build command produces .cact files from base checkpoints and optional adapters. This process merges LoRA weights into the base model before serialization.


# Build a tuned .cact from a base checkpoint and LoRA adapter

needle build checkpoints/needle2.pkl \
    --lora checkpoints/needle_lora.pkl \
    --out tuned.cact

The exporter implementation lives in needle/model/export.py. It handles weight consolidation, tensor layout optimization, and archive compression.

Engine Version Locking and Compatibility

The .cact format is intrinsically tied to the Needle 2 engine version that created it. Engine upgrades can modify the internal archive structure—adding new sections for quantization metadata, changing tensor serialization formats, or revising header layouts.

Attempting to load an incompatible archive triggers a version-mismatch error. In needle/__init__.py, the constructor catches this condition and raises:

RuntimeError: "failed to load weights from ... – the .cact ..."

This check appears at line 86 of needle/__init__.py, where the loader validates archive compatibility against the running engine's expected format.

Documented Version Compatibility Policy

The doc/finetuning.md file explicitly warns users about this constraint:

"the .cact format is tied to the engine version, so an archive exported by an older package will not load. Rebuild it with the current package version."

This guidance appears at line 84 of the fine-tuning documentation. The policy is strict: no backward compatibility guarantees are provided across engine versions.

Loading and Runtime Behavior

The needle.Needle class accepts a .cact file directly via the weights parameter, as documented in doc/apis.md. At runtime, the engine extracts and deserializes weights from the archive.

import needle

# Load the tuned model—engine extracts weights automatically

agent = needle.Needle(weights="tuned.cact", tools=[...])
response = agent.run("Schedule a meeting for tomorrow at 10 am")
print(response["results"])

Handling Version Mismatch Errors

Production code should catch and handle incompatible archive errors gracefully:

try:
    agent = needle.Needle(weights="old_archive.cact")
except RuntimeError as e:
    if "failed to load weights" in str(e):
        print("⚠️  Incompatible .cact version – rebuild with current needle package.")
        # Re-export required: needle build <checkpoint> --out new_archive.cact

This pattern allows applications to detect stale archives and prompt for re-export rather than crashing ambiguously.

Key Source Files

  • needle/model/export.py — Implements the .cact archive creation and weight merging logic.
  • needle/__init__.py — Contains runtime loading, version validation, and error reporting (line 86).
  • doc/finetuning.md — Documents the version-locked nature of .cact and rebuild requirements (line 84).
  • doc/apis.md — Specifies the weights parameter accepting .cact paths.
  • tests/test_build.py — Validates .cact construction and loading across engine versions.

Summary

  • .cact is a binary archive produced by needle build that bundles model weights with the inference engine.
  • The format is version-locked to the specific Needle 2 engine build that created it.
  • Engine upgrades require archive regeneration — older .cact files will not load and raise RuntimeError.
  • Key validation logic resides in needle/__init__.py with user-facing documentation in doc/finetuning.md.

Frequently Asked Questions

Why does my .cact file fail to load after upgrading cactus-needle?

The .cact format embeds engine-specific serialization details that change between releases. The archive contains no backward-compatibility layer, so the loader in needle/__init__.py rejects mismatched versions with a "failed to load weights" error. Rebuild the archive using needle build with your current package version.

Can I use a .cact file across different machines?

Yes, provided all machines run the same version of cactus-needle. The .cact file is portable but not version-agnostic. Copying between environments with mismatched engine versions will trigger compatibility errors.

Does .cact include LoRA adapters or just base weights?

The archive includes merged weights — base weights plus any LoRA adapters specified during needle build. The exporter in needle/model/export.py performs this merge before serialization, so the .cact contains a single ready-to-run weight set.

How can I verify which engine version created a .cact file?

The cactus-needle package does not expose archive version inspection APIs in the current release. Best practice is to regenerate .cact files whenever upgrading the package and to embed version metadata in your filenames or documentation (e.g., model_v2.1.0.cact).

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →