Needle 2 Engine Architecture for Loading Weights and Initialization
Needle 2 uses a three-step engine initialization sequence: resolve the native shared library, load weight blobs via the needle_load C API, and initialize the engine with needle_init using system prompts and tool schemas.
The cactus-compute/needle repository implements a native inference engine packaged as a platform-specific shared library. This architecture prioritizes runtime performance by executing tensor operations, quantization kernels, and KV-cache management in compiled C/C++ code rather than Python. Understanding how Needle 2 handles weight loading and engine initialization is essential for deploying custom models and debugging deployment issues.
Three-Step Engine Initialization Sequence
The Needle class in needle/__init__.py orchestrates engine startup through a strict, ordered protocol. Each step must succeed before the next begins.
Step 1: Resolve the Native Library
The engine binary location is determined through a cascading priority system:
NEEDLE_LIB_PATHenvironment variable (user override)- Bundled library within the installed package (
fetch._lib_name()) - User cache directory at
~/.cache/cactus-needle/<engine-version>
If no binary exists at any location, fetch.fetch_library automatically downloads the correct build from the Hugging Face model hub.
from needle.agent import fetch
# Force-specific version download
lib_path = fetch.fetch_library("v2.0.10", "/tmp/needle-lib")
print(lib_path)
The resolution logic spans lines 15-30 in needle/__init__.py.
Step 2: Load Weight Blobs via needle_load
When a Needle instance receives a weights argument, the .cact archive is read into memory as a Python bytes object. This blob is passed to the engine's needle_load C-API function along with its byte length.
Critical architectural constraint: The engine accepts the weight blob exactly once per process. The compiled library holds this memory for the process lifetime—it cannot be unloaded, replaced, or shared between incompatible versions.
from needle import Needle
# Load custom finetuned checkpoint
agent = Needle(weights="my_finetuned_model.cact")
# Subsequent agents reuse loaded weights
agent2 = Needle() # OK—no weights argument needed
Attempting to create another agent with different weights raises RuntimeError. This one-time load pattern is implemented in lines 70-88 of needle/__init__.py.
Step 3: Initialize with needle_init
After weight loading (or skipping if using default weights), the engine initializes via needle_init. This C-API call receives three UTF-8 buffers:
- System prompt – Base instructions for agent behavior
- Tool schema JSON – Description of all callable functions
- Tool index file (optional) – Additional tool routing metadata
Successful initialization registers the current Needle instance as the active engine. Lines 90-96 in needle/__init__.py handle this final step.
Native Core vs. Python Wrapper Architecture
Stateless Python Facade
The Needle class serves as a thin communication layer. It manages:
- Input/output buffer serialization
- Tool resolution and dispatch logic
- C-API call marshaling via
ctypes
The actual model state—attention caches, embedding tables, generation buffers—resides entirely within the native engine.
Runtime Execution Model
| Component | Location | Responsibility |
|---|---|---|
| Tensor kernels | Native shared library | Matrix multiplication, attention, quantization |
| KV-cache management | Native shared library | Key-value storage and retrieval during generation |
| Tool calling | Python wrapper | JSON schema validation and function dispatch |
| Tokenization | Native shared library | Text → token conversion |
JAX/Flax is not used at runtime. These frameworks appear only during training and checkpoint export.
Weight Format and Version Compatibility
The .cact file format is tightly coupled to engine version. Each archive contains:
- Serialized model parameters
- Quantization metadata
- Architecture configuration hashes
Loading a .cact file from an older Needle version fails with an explicit version-mismatch error. This prevents silent corruption from incompatible tensor layouts.
The load_checkpoint helper in needle/model/run.py handles archive reading for CLI workflows, though direct Needle(weights=...) instantiation is preferred for programmatic use.
from needle.model.run import load_checkpoint
# CLI-style checkpoint loading
params, config = load_checkpoint("model.cact")
Complete Initialization Examples
Default Weights with Automatic Download
from needle import Needle
# No weights specified—downloads default checkpoint automatically
agent = Needle()
response = agent.complete("Write a haiku about clouds.")
print(response["text"])
Custom Checkpoint with Pre-fetched Engine
import pathlib
from needle.agent import fetch
from needle import Needle
# Ensure engine binary exists locally
fetch.fetch_library("v2.0.10")
# Load finetuned weights once
ckpt = pathlib.Path("experiments/run-42/final.cact")
agent = Needle(weights=str(ckpt))
# Reuse loaded weights across completions
result = agent.run("Summarize the quarterly report.")
Engine Library Resolution Debugging
import os
from needle import Needle
# Force specific library location
os.environ["NEEDLE_LIB_PATH"] = "/opt/needle/libneedle.so"
# Verify resolution without creating agent
from needle.__init__ import _resolve_library
path = _resolve_library()
print(f"Engine will load from: {path}")
Source File Reference Map
| File | Key Function | Lines | Purpose |
|---|---|---|---|
needle/__init__.py |
Library resolution | 15-30 | NEEDLE_LIB_PATH → bundled → cache → download |
needle/__init__.py |
Weight loading | 70-88 | needle_load C-API call with bytes blob |
needle/__init__.py |
Engine initialization | 90-96 | needle_init with prompts and tool schemas |
needle/agent/fetch.py |
fetch_library() |
— | Hugging Face Hub download with version pinning |
needle/model/run.py |
load_checkpoint() |
— | .cact archive deserialization |
needle/model/architecture.py |
Architecture definitions | — | Transformer config used by native engine |
Summary
- Three-step initialization: resolve native library → load weight blob via
needle_load→ initialize engine vianeedle_init - One-time weight load: Per-process constraint enforced by native engine; subsequent agents reuse loaded weights
- Native execution: Core inference runs in compiled C/C++ library, not Python or JAX/Flax
- Version-locked format:
.cactarchives are tied to specific engine versions for safety - Automatic fetching: Missing engine binaries download from Hugging Face Hub via
fetch.fetch_library
Frequently Asked Questions
How do I load multiple different models in the same Python process?
You cannot. Needle 2's native engine loads weights exactly once per process via needle_load. Attempting to create a second Needle instance with different weights raises RuntimeError. Use separate processes or containers for multi-model deployments.
Where does Needle download the engine binary if it's not present?
The fetch.fetch_library function in needle/agent/fetch.py retrieves the correct build from the Hugging Face model hub, caching it in ~/.cache/cactus-needle/<engine-version>. Override this with the NEEDLE_LIB_PATH environment variable.
Can I unload weights to free memory?
No. The native engine holds the weight blob in allocated memory for the process lifetime. There is no needle_unload API. To release memory, terminate the Python process and start fresh.
What happens if my .cact file was created with an older Needle version?
The engine detects version mismatches during needle_load and raises an error with a clear message. You must re-export or re-download checkpoints matching your installed engine version.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →