# Needle Response Object Structure: A Complete Guide to Agent Outputs

> Understand the Needle response object structure in this guide. Learn about its JSON format, fields like type, function_calls, validation, and results. Explore agent outputs with Needle.

- Repository: [Cactus Compute, Inc./needle](https://github.com/cactus-compute/needle)
- Tags: api-reference
- Published: 2026-09-04

---

**A Needle response object is a Python dictionary returned by `Needle.complete()` or `Needle.run()` that contains a `type` field, optional `function_calls`, `validation` metadata, and execution `results`, formatted as JSON and parsed in [`needle/__init__.py`](https://github.com/cactus-compute/needle/blob/main/needle/__init__.py).**

The **Needle response object** forms the core communication protocol between the inference engine and your application code in the `cactus-compute/needle` library. After every call to `Needle.complete()` or the higher-level `Needle.run()`, the engine returns a serialized JSON payload that the library parses into a structured Python dictionary. Understanding this schema is essential for building reliable agent workflows, handling tool execution, and validating structured extractions.

## Core Structure of a Needle Response Object

The engine always ships results as JSON, which `Needle._complete()` parses using `json.loads` to produce the final dictionary. The parsed object follows a strict schema used to drive tool execution and validation throughout the codebase.

### Required Fields

Every response includes these fundamental keys:

- **`type`** (`str`): The categorical classification of the response. Common values include `"call"` (tool invocation required), `"text"` (direct answer), or `"refuse"` (model declined). The `run()` loop checks this field at line 189 to determine whether to continue the reasoning cycle.

- **`function_calls`** (`list[dict]`): A specification list of tools the model wants to invoke. Each dictionary contains:
  - `name`: The string identifier of the tool
  - `arguments`: A mapping of parameter names to their values
  
  The `Needle.run()` method iterates over this list at lines 88-99 to execute the requested functions.

### Optional Fields

Depending on the operation and engine configuration, these fields may be present:

- **`validation`** (`dict`): Structured extraction validation data containing:
  - `ungrounded`: A list of JSON-pointer strings indicating which extracted fields the model believes lack grounding in the source text
  - `negation`: A boolean flag indicating whether the request was negated
  
  The `_validate_extraction()` method consumes this data at lines 15-27.

- **`confidence`** (`float` or `None`): A confidence score returned by the native engine. This value is set to `None` when using fine-tuned weight files because the confidence head remains uncalibrated. The assignment occurs in `_complete()` at lines 79-81.

### Runtime-Added Fields

When using the higher-level `run()` interface, the library augments the response:

- **`results`** (`list[object]`): Accumulated return values from each tool execution performed during the reasoning loop. `Needle.run()` appends to this list at line 103 after every iteration, providing a complete trace of the agent's tool usage.

## Working with Needle Response Objects in Practice

### Retrieving Raw Completions with `complete()`

Use `Needle.complete()` to obtain the direct engine output without automatic tool execution. The response contains the raw `function_calls` and metadata:

```python
from needle import Needle

agent = Needle(tools=[my_tool])
raw = agent.complete("Set the thermostat to 22°C in the office")

print(raw["type"])                # → "call"

print(raw["function_calls"])      # → [{'name': 'set_thermostat', 'arguments': {...}}]

print(raw.get("confidence"))      # → 0.87 (or None for fine-tuned weights)

```

### Executing Tools with the `run()` Loop

When invoking `Needle.run()`, the library enters a reasoning loop that executes tools automatically. The returned **Needle response object** includes the additional `results` key containing the output of each tool call:

```python
agent = Needle(tools=[my_tool])
resp = agent.run("Configure the office temperature")

print(resp["type"])                # → "call"

print(resp["results"])             # → [{"status": "ok", "new_temp": 21}]

print(resp.get("validation"))      # → may contain grounding info

```

### Handling Validation and Errors

For structured extraction tasks, inspect the `validation` field to identify ungrounded claims or negations before processing the data:

```python
from needle import ExtractionValidationError

try:
    data = agent.extract(
        "Invoice due on 2023-04-01", schema=InvoiceSchema
    )
except ExtractionValidationError as err:
    print("Extraction failed:", err)

```

## Source Code Implementation Details

The **Needle response object** contract is defined and enforced across these key files:

| File | Implementation Details |
|------|------------------------|
| [`needle/__init__.py`](https://github.com/cactus-compute/needle/blob/main/needle/__init__.py) | Core `Needle` class that parses raw engine JSON in `_complete()`, adds the `confidence` field, and implements `run()` which injects the `results` list. |
| [`needle/agent/tools.py`](https://github.com/cactus-compute/needle/blob/main/needle/agent/tools.py) | Constructs the JSON schema for available tools; this schema dictates the exact shape of each entry inside `function_calls`. |
| [`needle/_worker.py`](https://github.com/cactus-compute/needle/blob/main/needle/_worker.py) | Low-level worker interface that returns the raw JSON envelope from the native engine, providing the source data for all response fields. |
| [`tests/test_inference.py`](https://github.com/cactus-compute/needle/blob/main/tests/test_inference.py) | Unit tests asserting the mandatory presence of `type` and `function_calls` keys, illustrating expected usage patterns. |
| [`tests/test_environments.py`](https://github.com/cactus-compute/needle/blob/main/tests/test_environments.py) | Integration tests exercising the response structure when running against built-in environments, confirming field consistency. |

## Summary

- A **Needle response object** is a Python `dict` parsed from engine JSON via `json.loads` in `Needle._complete()`.
- The `type` field (values like `"call"`, `"text"`, or `"refuse"`) drives execution logic in `run()` at line 189.
- Tool specifications reside in `function_calls`, iterated at lines 88-99 of [`needle/__init__.py`](https://github.com/cactus-compute/needle/blob/main/needle/__init__.py).
- Optional `validation` data includes `ungrounded` pointers and `negation` flags, processed by `_validate_extraction()`.
- The `confidence` score is `None` for fine-tuned models, set at lines 79-81.
- The `run()` method adds a `results` list at line 103 containing tool execution outputs.

## Frequently Asked Questions

### What is the data type of a Needle response object?

A Needle response object is a standard Python `dict` (dictionary) parsed from JSON. The library uses `json.loads` in the `_complete()` method to convert the engine's raw JSON output into this dictionary structure, allowing standard Python key-access syntax like `response["type"]` or `response.get("confidence")`.

### How does the `type` field determine program flow?

The `type` field categorizes the model's intention. When `type` equals `"call"`, the `Needle.run()` loop at line 189 continues execution to invoke the tools listed in `function_calls`. If `type` is `"text"`, the loop terminates and returns the final answer. A `type` of `"refuse"` indicates the model declined the request, typically triggering an exception or fallback behavior.

### Why is the `confidence` field sometimes `None`?

The `confidence` field returns `None` specifically when you load a fine-tuned weight file. According to the source code at lines 79-81 of [`needle/__init__.py`](https://github.com/cactus-compute/needle/blob/main/needle/__init__.py), the confidence prediction head is not calibrated for fine-tuned models, so the library explicitly sets this value to `None` rather than returning misleading scores. Native engine weights return a float between 0 and 1.

### What happens to extra fields returned by the engine?

Any additional keys present in the engine's JSON payload—such as `message`, `status`, or model-specific metadata—are preserved unchanged in the returned dictionary. The parsing logic in `_complete()` passes these fields through directly without modification, ensuring forward compatibility with future engine updates.