# JSON Envelope Returned by Needle 2 complete(): Structure and Fields

> Understand the JSON envelope returned by Needle 2 complete(). Explore key fields like type, content, function calls, and confidence for tool invocations and output.

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

---

**Needle 2's `complete()` method returns a JSON envelope containing fields like `type`, `text` (or `content`), `function_calls` for tool invocations, and a `confidence` field injected by the Python wrapper.**

The `cactus-compute/needle` repository provides a lightweight inference engine that exposes a Python API for text completion and tool calling. Understanding the **JSON envelope returned by Needle 2's `complete()` function** is essential for parsing model responses, handling tool calls, and integrating the engine into production applications.

## JSON Envelope Structure

When you invoke `Needle.complete()`, the underlying C library (`needle_complete`) writes a JSON-encoded envelope into a pre-allocated buffer. The Python wrapper decodes this buffer into a dictionary with the following optional fields:

### Response Type and Content Fields

The envelope always includes a **`type`** field that describes the response category:

- **`"answer"`** – Standard text generation with no tool invocation
- **`"call"`** – The model has decided to invoke one or more tools
- Custom strings depending on the engine configuration

The generated prose appears in either **`text`** or **`content`** (the exact key varies by engine version). This field contains the raw model output when `type` is not `"call"`.

### Tool Invocation Fields

When **`type`** equals `"call"`, the envelope includes a **`function_calls`** array. Each object in this array contains:

- **`name`** – The tool identifier (string)
- **`arguments`** – A JSON object containing the parameters for the tool call

These objects map directly to the schemas defined in [`needle/agent/tools.py`](https://github.com/cactus-compute/needle/blob/main/needle/agent/tools.py).

### Confidence Calibration Field

The Python wrapper adds a **`confidence`** field (float or `null`) **only when a fine-tuned weight file is loaded**. Because the confidence head is not calibrated for tuned models, the wrapper explicitly sets this value to `null` in `Needle._complete`.

### Additional Metadata

The engine may pass through other keys (e.g., `model`, `usage`) unchanged. The wrapper does not modify these custom fields.

## How the Envelope Is Built in the Source Code

The construction of the JSON envelope follows a specific path through the codebase:

1. **`Needle.complete()`** forwards the request to the private method `_complete()` (lines 19-22 of [`needle/__init__.py`](https://github.com/cactus-compute/needle/blob/main/needle/__init__.py))

2. **`_complete()`** calls the low-level C library function **`needle_complete`** and decodes the buffer as JSON (lines 24-31)

3. **Confidence injection** occurs when `self._weights` is present (lines 35-37), where the wrapper adds `response["confidence"] = None`

The same envelope structure propagates through [`needle/playground/server.py`](https://github.com/cactus-compute/needle/blob/main/needle/playground/server.py) (lines 30-39), where the server calls `engine.complete()` and returns the result to HTTP clients.

## Practical Code Examples

### Basic Text Completion

For standard generation without tools, the envelope contains the generated text and a null confidence score:

```python
from needle import Needle

agent = Needle()
result = agent.complete("Tell me a short joke.")

print(result["text"])          # → "Why did the scarecrow win an award?"

print(result["type"])          # → "answer"

print(result["confidence"])    # → null

```

### Tool-Calling Completion

When the model invokes tools, the envelope contains the `function_calls` array:

```python
from needle import Needle, tool

@tool
def get_weather(city: str) -> dict:
    return {"city": city, "temp_c": 22}

agent = Needle(tools=[get_weather])
result = agent.complete("What's the weather in Paris?")

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

print(result["function_calls"])      # → [{"name": "get_weather", "arguments": {"city": "Paris"}}]

```

### Multi-Step Agent Execution

When using the higher-level `run()` method, the system collects intermediate results and adds them to the final envelope:

```python
agent = Needle(tools=[get_weather])
out = agent.run("Plan a picnic in Paris.")

# The envelope includes final response plus execution history

print(out["results"])  # → List of function call results collected during the run

```

## Summary

- The **JSON envelope** returned by `Needle.complete()` contains `type`, `text` (or `content`), and optionally `function_calls` and `confidence`
- The **`type`** field distinguishes between direct answers (`"answer"`) and tool invocations (`"call"`)
- **`function_calls`** provides structured tool invocation data when the model decides to use external functions
- The **`confidence`** field is injected by the Python wrapper in [`needle/__init__.py`](https://github.com/cactus-compute/needle/blob/main/needle/__init__.py) only when fine-tuned weights are loaded, always set to `null` for tuned models
- The underlying C library (`needle_complete`) generates the raw JSON, which the Python wrapper decodes and augments before returning to the caller

## Frequently Asked Questions

### What is the difference between the `text` and `content` fields in the Needle 2 JSON envelope?

The envelope may use either `text` or `content` as the key for generated prose depending on the specific engine version you are running. Both keys serve the same purpose: they contain the raw text generated by the model when no tool call is required. Your application should check for both keys or consult the engine documentation for your specific version.

### Why is the `confidence` field always null in my Needle 2 responses?

According to the source code in [`needle/__init__.py`](https://github.com/cactus-compute/needle/blob/main/needle/__init__.py) (lines 35-37), the Python wrapper adds the `confidence` field only when a fine-tuned weight file is loaded via `self._weights`. Because the confidence head is not calibrated for fine-tuned models, the wrapper explicitly sets this value to `null` to indicate that the confidence score is unavailable or unreliable.

### How does Needle 2 handle multiple tool calls in a single completion?

When the model decides to invoke multiple tools simultaneously, the `type` field is set to `"call"` and the `function_calls` array contains multiple objects. Each object includes a `name` string identifying the tool and an `arguments` object containing the parameters. Your application must iterate through this array to execute all requested tool calls.

### Where in the source code is the JSON envelope actually constructed?

The envelope originates in the low-level C library function `needle_complete`, which writes JSON into a pre-allocated buffer. The Python wrapper in [`needle/__init__.py`](https://github.com/cactus-compute/needle/blob/main/needle/__init__.py) (specifically the `_complete` method at lines 19-38) decodes this buffer and conditionally adds the `confidence` field before returning the final dictionary to the caller.