What Is the Difference Between Extraction and Tool Calling in Needle?
The difference between extraction and tool calling in Needle is that extraction is a read-only validation pipeline that transforms text into grounded data structures, while tool calling is an execution framework that enables LLMs to invoke registered Python functions with side effects.
The cactus-compute/needle library provides these two distinct pathways for structuring language model interactions. Understanding the architectural difference between extraction and tool calling in Needle is essential for selecting the appropriate pattern for data parsing versus action execution. This guide examines the validation mechanisms, source code implementation, and runtime behaviors that distinguish these two critical modes.
How Extraction Works: The Validation Pipeline
Extraction operates as a pure-functional transformation that guarantees grounded outputs. When you invoke needle.extract(text, schema), the library calls the _extract_one_shot function implemented in needle/__init__.py (around line 486), which utilizes the LLM's structured output mode to generate a candidate data object.
Following generation, Needle enforces strict grounding validation through _validate_extraction (defined near line 468 in needle/__init__.py). This validation logic verifies that every extracted value actually appears in the original input text, preventing hallucinated data. If the validation fails, the system raises ExtractionValidationError.
Because extraction performs no code execution—only data transformation and validation—it remains safe for processing untrusted user inputs without side effects.
from needle import extract, Field
from pydantic import BaseModel
class Invoice(BaseModel):
due_date: str = Field(..., description="Date when the invoice is due")
amount: float = Field(..., description="Total amount due")
text = "Invoice #42 is due on 5th September 2024 for $123.45."
result = extract(text, Invoice)
# The validator guarantees these values appear in the original text
# → {'due_date': '5th September 2024', 'amount': 123.45}
How Tool Calling Works: The Execution Runtime
Tool calling transforms natural language requests into executable actions through a decorator-based registration system. You define functions using the @tool decorator, which introspects type hints to build Pydantic schemas (implemented in needle/agent/tools.py). These registered tools are then passed to a Needle agent instance.
When processing a prompt, the runtime in needle/_worker.py parses the input, identifies the appropriate tool using prompt templates defined in needle/model/run.py (which utilizes special tokens like TOOLS_START and TOOL_CALL_START), extracts arguments, and actually invokes the registered Python function.
Unlike extraction, tool calling executes real code, enabling side effects such as network requests, file system operations, or hardware control. Error handling propagates directly from the tool implementation—if the function raises an exception, the agent surfaces it to the caller without grounding checks against the original text.
from needle import Needle, tool
@tool
def send_email(to: str, subject: str, body: str) -> str:
"""Send an email and return a confirmation message."""
return f"Email sent to {to!r}"
agent = Needle(tools=[send_email])
response = agent("Please email Alice <alice@example.com> with subject 'Report'")
print(response)
# → "Email sent to 'alice@example.com'"
Critical Architectural Differences
The distinction between these patterns centers on validation versus execution:
-
Extraction implements grounding validation via
_validate_extractionto ensure all output values exist in the source text. This creates a sandboxed environment safe for arbitrary text parsing but restricts operations to data transformation only. -
Tool Calling prioritizes argument validation against function signatures. Once arguments are extracted, the system executes the actual function without grounding checks, as the tool's implementation determines correctness and handles side effects.
-
API Entry Points: Extraction uses the standalone
needle.extract()function, while tool calling requires instantiating aNeedleagent with a list of registered tools. -
Error Models: Extraction raises
ExtractionValidationErrorwhen values are not grounded in the source text; tool calling propagates exceptions directly from the executed function.
Key Implementation Files
Understanding the source organization clarifies these architectural boundaries:
-
needle/__init__.py: Contains the publicextract()API and the grounding validation logic (_validate_extraction,_extract_one_shot). -
needle/agent/tools.py: Implements the@tooldecorator and automatic Pydantic schema generation for function arguments. -
needle/_worker.py: Houses the runtime logic that decides between extraction and tool invocation, managing the execution loop and tool selection. -
needle/model/run.py: Defines prompt construction templates, including special tokens that delimit tool definitions and calls. -
tests/test_inference.py: Provides integration examples demonstrating both patterns working together.
Summary
- Extraction provides a read-only, validated data transformation that guarantees grounded outputs through
_validate_extractioninneedle/__init__.py, making it ideal for parsing documents safely. - Tool Calling enables executable actions via the
@tooldecorator andneedle/_worker.pyruntime, supporting side effects but requiring careful security consideration for the executed code. - Validation differs fundamentally: Extraction validates against source text existence to prevent hallucinations; tool calling validates against function signatures to ensure correct argument typing.
- Performance profiles vary: Extraction completes in a single LLM call with immediate validation; tool calling may involve multiple LLM interactions plus the execution time of the registered function.
Frequently Asked Questions
Can extraction and tool calling be used together in the same Needle application?
Yes. The tests/test_inference.py file demonstrates integration patterns where extraction pipelines parse input data before passing structured results to tool-enabled agents. You can use extraction to safely parse user input into validated Pydantic objects, then pass those objects as arguments to tool calls without risking ungrounded data in your function execution.
Why does Needle validate that extracted values exist in the original text?
The _validate_extraction function in needle/__init__.py enforces grounding to prevent LLM hallucinations. By verifying that every extracted field value appears verbatim in the source text, Needle ensures structured outputs are factually anchored to the input. This is critical for applications processing invoices, medical records, or legal documents where fabricated data could cause significant errors.
What happens if a tool function raises an exception during execution?
Unlike extraction, which raises ExtractionValidationError for grounding failures, tool calling propagates exceptions directly from the registered function. The runtime in needle/_worker.py does not catch tool exceptions by default, allowing you to handle errors according to your application's requirements through standard Python exception handling mechanisms.
Do both patterns require Pydantic schemas?
Yes, both leverage Pydantic for structured validation, but in different ways. Extraction accepts a Pydantic model class directly as the schema parameter to needle.extract(). Tool calling uses Python type hints on decorated functions to auto-generate Pydantic schemas in needle/agent/tools.py, which the LLM uses to understand required arguments and types.
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 →