# Needle Tool Call Failure Error Handling: Schema Validation, Confidence Gates, and Structured Recovery

> Learn how Needle 2 handles tool call failures with schema validation confidence gates and structured recovery. Ensure stable production pipelines with this robust error handling.

- Repository: [Cactus Compute, Inc./needle](https://github.com/cactus-compute/needle)
- Tags: how-to-guide
- Published: 2026-08-15

---

**Needle 2 captures tool call failures as structured JSON payloads rather than raising exceptions, using a three-layer defense system of schema validation, confidence thresholds, and try/except wrappers to ensure production pipelines remain stable.**

Needle 2, developed in the `cactus-compute/needle` repository, treats tool invocations as first-class citizens in its inference loop. When a user prompt triggers a Python function decorated with `@needle.tool`, the runtime orchestrates execution through a defensive architecture designed to prevent crashes and surface errors as data. Understanding **Needle tool call failure error handling** is essential for building robust AI agents that interact with external APIs and unreliable services.

## The Three Pillars of Needle Error Handling

### Schema Compilation and Type Safety

In [`needle/agent/tools.py`](https://github.com/cactus-compute/needle/blob/main/needle/agent/tools.py), the `@needle.tool` decorator inspects Python function signatures and docstrings to generate JSON schemas. These schemas compile into byte-level decode grammars defined in [`needle/model/architecture.py`](https://github.com/cactus-compute/needle/blob/main/needle/model/architecture.py), ensuring the language model can only emit arguments matching declared types. This prevents malformed inputs from ever reaching the Python execution layer.

### Confidence-Gated Execution

Before any tool runs, Needle checks the model's calibrated confidence score against your configured threshold. As implemented in [`needle/cli.py`](https://github.com/cactus-compute/needle/blob/main/needle/cli.py), the runtime compares `result["confidence"]` against the `needle.Needle(confidence=0.8, ...)` parameter. If the score falls below the threshold, Needle rejects the call before execution, avoiding unnecessary crashes from uncertain predictions.

### Structured Exception Wrapping

The actual function call is wrapped in a `try/except` block within [`needle/agent/tools.py`](https://github.com/cactus-compute/needle/blob/main/needle/agent/tools.py). When a function raises an exception, Needle captures the traceback and returns a structured error object containing `{"error": "...", "type": "..."}` instead of propagating the exception upward. This design treats failures as data events rather than terminal errors.

## Understanding the Error Response Format

When a tool fails, the runtime returns a consistent JSON structure that includes the tool name, arguments, error details, and confidence score:

```json
{
  "tool": "get_weather",
  "arguments": {"city": "Lagos"},
  "error": "ValueError: unable to fetch weather data",
  "type": "tool_error",
  "confidence": 0.96
}

```

This payload allows downstream applications to implement recovery logic without terminating the conversation.

## Practical Error Handling Patterns

### Basic Error Detection and Recovery

Inspect the `results` list returned by `agent.run()` for the presence of an `"error"` key to implement fallback logic:

```python
import needle

@needle.tool
def get_weather(city: str):
    """Get the current weather for a city."""
    if city.lower() == "mars":
        raise ValueError("No weather data for extraterrestrial locations")
    return {"city": city, "temp_c": 27, "sky": "clear"}

agent = needle.Needle(tools=[get_weather], confidence=0.85)
response = agent.run("What's the weather like on Mars?")

for result in response["results"]:
    if "error" in result:
        print(f"⚠️ Tool error: {result['error']}")
        fallback = {"city": result["arguments"]["city"], "temp_c": None, "sky": "unknown"}
        print("Using fallback:", fallback)
    else:
        print("✅ Tool succeeded:", result["results"])

```

### Implementing Retry Logic with Exponential Backoff

For transient failures, wrap tools in retry logic before registration:

```python
def safe_get_weather(city, retries=2):
    for attempt in range(retries + 1):
        try:
            return get_weather(city)
        except Exception as e:
            if attempt == retries:
                raise
            print(f"Retry {attempt+1}/{retries}: {e}")

agent = needle.Needle(tools=[safe_get_weather])

```

### Structured Extraction with Validation

When using `needle.extract()` for Pydantic model validation, catch validation errors explicitly:

```python
from pydantic import BaseModel

class Weather(BaseModel):
    city: str
    temp_c: float | None
    sky: str

try:
    weather = needle.extract("Mars is hot", Weather)
except Exception as e:
    print("❌ Extraction failed:", e)

```

## Summary

- **Schema validation** in [`needle/agent/tools.py`](https://github.com/cactus-compute/needle/blob/main/needle/agent/tools.py) and [`needle/model/architecture.py`](https://github.com/cactus-compute/needle/blob/main/needle/model/architecture.py) prevents invalid arguments from reaching Python functions by compiling type constraints into the decode grammar.
- **Confidence gating** in [`needle/cli.py`](https://github.com/cactus-compute/needle/blob/main/needle/cli.py) automatically rejects low-confidence tool calls before execution based on the configurable threshold in the `Needle` constructor.
- **Structured error wrapping** converts Python exceptions into JSON payloads with `error` and `type` fields, allowing applications to treat failures as data rather than crashes.
- **Recovery strategies** include retry logic, fallback values, or escalation to users, all enabled by the consistent error response format documented in [`doc/apis.md`](https://github.com/cactus-compute/needle/blob/main/doc/apis.md).

## Frequently Asked Questions

### What happens when a Needle tool raises an exception?

The runtime catches the exception in [`needle/agent/tools.py`](https://github.com/cactus-compute/needle/blob/main/needle/agent/tools.py) and returns a structured JSON object containing the error message, exception type, original arguments, and confidence score. This prevents the exception from crashing the inference loop and allows your application to handle the failure programmatically.

### How does Needle prevent invalid tool arguments?

Needle compiles JSON schemas derived from Python type hints and docstrings into byte-level decode grammars in [`needle/model/architecture.py`](https://github.com/cactus-compute/needle/blob/main/needle/model/architecture.py). This ensures the language model can only generate syntactically valid arguments that match the declared types, filtering out malformed inputs before they reach the function execution layer.

### Can I customize the confidence threshold for tool execution?

Yes. Pass a `confidence` parameter when initializing the `Needle` class, such as `needle.Needle(tools=[my_tool], confidence=0.85)`. As implemented in [`needle/cli.py`](https://github.com/cactus-compute/needle/blob/main/needle/cli.py), the runtime compares the model's confidence score against this threshold and rejects any tool call that falls below it, preventing execution of uncertain predictions.

### How do I retry a failed tool call in Needle?

Wrap your tool function in custom retry logic that catches exceptions and re-attempts execution with backoff. Register this wrapper function with `@needle.tool` instead of the original. Alternatively, inspect the response from `agent.run()` for `"error"` keys and implement retry logic at the application level based on the structured error payload.