Needle 2 Input Without Declared Tool: Plain-Prompt Mode Behavior

When you submit a Needle 2 request without declaring tools, the library automatically falls back to plain-prompt mode, constructing a prompt without the <tools> block and returning raw text responses instead of executing function calls.

When building AI applications with the cactus-compute/needle repository, you may occasionally submit queries that don't require external function calls. Understanding how Needle 2 input without declared tool parameters behaves ensures your application handles standard chat completions gracefully without raising errors or forcing unnecessary tool invocations.

How Needle 2 Handles Missing Tool Declarations

Prompt Construction Logic

In needle/model/run.py, the build_prompt function explicitly checks for missing tools between lines 215-221. When the condition if not tools: evaluates to true, the function invokes render_example with only the query dictionary, deliberately excluding the <tools> token block from the final prompt string. This means the underlying LLM receives no function schemas, tool descriptions, or calling conventions.

Model Generation Behavior

Without tool declarations embedded in the prompt, the language model generates standard textual responses. The output stream contains no <tool_call> or <tool_result> tags, as the special delimiters defined in needle/model/tokenizer.py remain unutilized. Consequently, the model relies exclusively on its parametric knowledge rather than attempting to invoke external capabilities.

Response Processing Flow

The post-processing pipeline searches for tool invocation markers within the generated text. When the parser detects no <tool_call> sequences—which is guaranteed in plain-prompt mode—the system returns the raw assistant text directly to the caller. This design prevents runtime exceptions and allows downstream code to treat empty tool call collections as a valid "no operation" state.

Practical Code Examples

Calling Needle 2 Without Tools

import needle

# Initialize with model weights

nl = needle.Needle(weights="path/to/weights.safetensors")

# Plain query without tool declarations

response = nl.complete(query="What is the capital of France?")
print(response)  # Output: "Paris"

Explicit Empty Tools List

import needle

nl = needle.Needle(weights="weights.safetensors")

# Empty list triggers identical behavior to None

response = nl.complete(
    query="Summarize the latest news.",
    tools=[]
)
print(response)  # Returns standard summarization without function calls

Internal Prompt Building Logic


# Simplified excerpt from needle/model/run.py

def build_prompt(query, tools=None):
    if not tools:  # Executes when tools is None or []

        prompt, _ = render_example({"query": query})
    else:
        prompt, _ = render_example({"query": query, "tools": tools})
    return prompt

Key Source Files and Implementation Details

The plain-prompt fallback mechanism spans several critical components within the repository:

  • needle/__init__.py – The main Needle class exposes the complete() method. When the tools argument is omitted, it propagates a falsy value to the prompt construction layer.

  • needle/model/run.py – Lines 215-221 contain the conditional logic that detects empty tool configurations. This if not tools: check determines whether to inject the <tools> XML block into the rendered template.

  • needle/model/tokenizer.py – Defines the special token delimiters including <tools>, <tool_call>, and <tool_result>. These markers are only present in the prompt when the tools list contains registered functions.

  • needle/agent/tools.py – Implements the @tool decorator and registry system. When no tools are supplied to the completion call, the internal registry remains empty, and no validation errors occur during prompt assembly.

Summary

  • Needle 2 gracefully degrades to plain-prompt mode when no tools are declared, ensuring compatibility with standard chat completion use cases.
  • The build_prompt function in needle/model/run.py detects falsy tool values at lines 215-221 and omits the <tools> section from the prompt template.
  • Responses generated in this mode lack <tool_call> tags, causing the parser to return raw text directly without attempting function execution.
  • Both None and empty list [] values for the tools parameter trigger identical behavior, making the API surface flexible for dynamic tool selection.
  • No exceptions are raised for missing tool declarations, allowing applications to mix tool-enabled and plain-text queries seamlessly.

Frequently Asked Questions

Does Needle 2 raise an error if I forget to declare tools?

No. According to the cactus-compute/needle source code, missing or empty tool declarations are valid configurations that trigger plain-prompt mode. The build_prompt function simply skips tool-related token injection, and the model returns standard text responses without raising exceptions or warnings.

How does plain-prompt mode affect model performance?

When operating without declared tools, the model processes shorter prompts that exclude function schemas and XML delimiters, potentially reducing token consumption and latency. However, the model cannot access external data sources or APIs, relying exclusively on its training data to generate responses, as implemented in the execution path through needle/model/run.py.

Can I mix tool and non-tool queries in the same Needle 2 session?

Yes. Each invocation of nl.complete() evaluates the tools parameter independently. You can alternate between queries with full tool registries and Needle 2 input without declared tool parameters within the same instance, with the prompt builder dynamically adjusting the input format for each individual request.

What happens if downstream code expects tool calls but none were declared?

If your application logic searches for <tool_call> tags in a plain-prompt response, the parser returns an empty list or None value. The cactus-compute/needle implementation delivers the raw assistant text directly when no tool markers are detected, allowing callers to safely handle absent function invocations by checking for empty tool result collections rather than catching exceptions.

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 →