How to Persist Tool Embeddings for Faster Loading in Needle 2

Yes—by supplying a file path to the tool_index_path parameter when constructing a Needle agent, you can store computed tool embeddings on disk and reload them instantly on subsequent launches, eliminating redundant computation for large tool catalogues.

Needle 2 builds a retrieval head that embeds every declared tool schema once at startup to select the top-performing tools for each turn. When working with extensive tool sets, this embedding process can dominate initialization time. The cactus-compute/needle repository provides a built-in persistence mechanism that caches these embeddings between runs, dramatically reducing warm-up latency.

Understanding Tool Embeddings in Needle 2

Needle 2 maintains a retrieval system that embeds tool schemas to determine relevance during agent execution. When your catalogue contains more than five tools, only the highest-scoring five are injected into the prompt each turn. Computing these embeddings from scratch on every run creates unnecessary overhead, particularly for agents with dozens or hundreds of registered tools.

The persistence feature addresses this by writing a binary index to disk that maps tool schema fingerprints to their pre-computed embedding vectors. This index is keyed by both the tool schema content and the model version, ensuring compatibility across updates.

Enabling Embedding Persistence with tool_index_path

To activate embedding persistence, you must provide a filesystem path when instantiating the agent.

Constructor Configuration

In needle/__init__.py, the Needle.__init__ method stores the optional persistence path as an instance variable:

def __init__(self, tools, tool_index_path=None, ...):
    # Lines 54-66: Stores tool_index_path for later use

    self.tool_index_path = tool_index_path
    ...

According to the API documentation in doc/apis.md, this parameter specifies the location where Needle will write or read the binary embedding cache.

Native Engine Integration

During agent initialization, the _bind method passes the tool_index_path directly to the underlying native engine:


# Lines 89-90 in needle/__init__.py

result = needle_init(
    ...,
    tool_index_path=self.tool_index_path
)

The native engine handles the actual serialization logic, checking for an existing index at the specified path before computing new embeddings.

How the Embedding Cache Works

The caching system uses fingerprint-based invalidation to ensure accuracy while maximizing reuse:

  1. Fingerprint Generation: Needle computes a hash fingerprint of each tool schema combined with the model version identifier
  2. Binary Storage: Embeddings are stored in a compact binary format keyed by these fingerprints
  3. Incremental Updates: If you modify existing tools or add new ones, only the changed schemas trigger re-embedding; unchanged tools retain their cached vectors
  4. Automatic Fallback: If the fingerprint mismatches or the cache is corrupted, Needle silently recomputes the embeddings and writes a fresh index

As documented in doc/apis.md (lines 147-149), this mechanism ensures that schema changes invalidate only the affected entries rather than requiring a full cache refresh.

Implementation Examples

First Run with Persistence

During the initial execution, Needle computes embeddings and writes the index file:

import needle

@needle.tool
def get_weather(city: str):
    """Return the current weather for *city*."""
    ...

@needle.tool
def set_lights(room: str, brightness: int):
    """Set the brightness (0-100) for *room*."""
    ...

# Initialize with persistence path

agent = needle.Needle(
    tools=[get_weather, set_lights],  # Add dozens more tools here

    tool_index_path="~/.cache/needle_tool_index.bin"
)

# First run computes embeddings and writes to disk

response = agent.run("Dim the kitchen lights to 20%")

Subsequent Runs with Cached Embeddings

On future executions, the embeddings load instantly from disk:


# Same configuration—embeddings read from binary index

agent = needle.Needle(
    tools=[get_weather, set_lights],
    tool_index_path="~/.cache/needle_tool_index.bin"
)

# Near-instant initialization regardless of tool count

result = agent.run("What's the weather in Tokyo?")

When you update a tool's schema or add new functions, the engine automatically detects the changes and updates only the modified entries in the cache.

Summary

  • Persistence activation: Pass a filesystem path to tool_index_path in Needle.__init__ (needle/init.py lines 54-66)
  • Engine integration: The _bind method transmits this path to the native engine (needle/init.py lines 89-90)
  • Storage format: Binary index keyed by schema fingerprints and model version (doc/apis.md lines 147-149)
  • Incremental updates: Only modified tools trigger re-embedding; existing cache entries remain valid
  • Performance impact: Eliminates embedding computation overhead on subsequent runs, critical for large tool catalogues

Frequently Asked Questions

What file format does Needle 2 use for the embedding cache?

Needle 2 stores embeddings in a binary index format optimized for fast loading. The file contains serialized embedding vectors keyed by schema fingerprints and model version identifiers, allowing the native engine to memory-map or load the data efficiently without parsing overhead.

Does the cache invalidate automatically when I update tool schemas?

Yes. The fingerprinting mechanism detects any changes to tool schemas or model versions. When you modify a tool's signature, docstring, or implementation, Needle computes a new fingerprint, recognizes the mismatch with the cached entry, and recomputes only that specific embedding while retaining the rest of the cache intact.

Can I share the embedding cache between different machines?

While technically possible by copying the binary file specified in tool_index_path, this is generally not recommended. The cache contains model-specific embeddings that may depend on the exact transformer weights and tokenizer version installed on the originating machine. Sharing across environments with different Needle or model versions could result in fingerprint mismatches or subtle embedding incompatibilities.

Is there a maximum size limit for the tool_index_path file?

There is no enforced size limit within the Needle 2 codebase itself. The binary index scales linearly with the number of tools and the embedding dimension of your chosen model. For catalogues with hundreds of tools, expect file sizes ranging from a few megabytes to several hundred megabytes depending on the embedding model's output dimensions.

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 →