# How to Access Optional Fields from the Needle.complete() Response

> Safely access optional fields like function_calls, reasoning, and metadata from Needle.complete() responses using the dictionary get() method. Learn how to handle these fields reliably.

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

---

**Use the dictionary `get()` method to safely retrieve optional fields like `function_calls`, `reasoning`, and `metadata` from the dict returned by `Needle.complete()`.**

The `Needle.complete()` method in the cactus-compute/needle repository returns a JSON-decoded Python dictionary containing the model's output. While core fields like `type` and `content` are always present, the response may also include optional fields generated dynamically by the underlying engine. Because the library does not enforce a fixed schema on the returned envelope, you must defensively check for these optional keys to avoid `KeyError` exceptions.

## Understanding the Needle.complete() Response Structure

When you call `agent.complete()`, the library processes a raw C-API string through `json.loads()` and returns the resulting dictionary directly to the caller. According to the source code in [`needle/__init__.py`](https://github.com/cactus-compute/needle/blob/main/needle/__init__.py), the response handling looks like this:

```python

# https://github.com/cactus-compute/needle/blob/main/needle/__init__.py#L52-L63

raw = self._buffer.value.decode("utf-8")
response = json.loads(raw)                     # ← JSON envelope from the engine

if self._weights:
    response["confidence"] = None
if ground:
    _annotate_ungrounded(response, ...)        # adds grounding info

return response

```

Since the envelope is a plain dictionary, any additional keys added by the engine—such as `function_calls` or `reasoning`—will simply be present in the returned `dict` when the model chooses to emit them. The library does **not** guarantee the presence of these fields for every request.

## Optional Fields Available in the Response

The engine may include several optional fields depending on the request configuration and model behavior.

### function_calls

The **`function_calls`** field contains a list of function-call objects generated by the model when tools are available. This field is defined in relation to the tool schemas in [`needle/agent/tools.py`](https://github.com/cactus-compute/needle/blob/main/needle/agent/tools.py). When tools are supplied to the agent, the engine can emit this field to request external function execution.

### reasoning

The **`reasoning`** field stores any chain-of-thought or rationale the model attaches to its response. This appears only when the underlying provider includes reasoning tokens or explanation blocks in the output.

### metadata

The **`metadata`** field contains provider-specific extra information such as confidence scores, token usage statistics, or latency metrics. The structure varies by backend implementation.

### confidence

The **`confidence`** field is conditionally added in [`needle/__init__.py`](https://github.com/cactus-compute/needle/blob/main/needle/__init__.py) when `self._weights` is configured. The source explicitly inserts this key only when weights are present:

```python
if self._weights:
    response["confidence"] = None

```

## Safely Accessing Optional Fields in Python

Because optional fields may be absent, you should never access them using direct bracket notation. Instead, use **`dict.get()`** or **`in`** checks to handle missing keys gracefully.

**Preferred approaches:**

- **`response.get("field_name", default)`** – Returns the value or a default if the key is missing
- **`if "field_name" in response`** – Boolean check before accessing the value

Direct access like `response["function_calls"]` will raise a `KeyError` if the model did not generate tool calls.

## Complete Code Example

Here is a robust pattern for accessing optional fields from the `Needle.complete()` response:

```python
from needle import Needle

# Initialise the agent (optionally with tools or a system prompt)

agent = Needle()

# Simple completion – may or may not include optional fields

resp = agent.complete("Give me the weather forecast for tomorrow")

# Safely access optional fields

function_calls = resp.get("function_calls", [])
if function_calls:
    for call in function_calls:
        print(f"Tool: {call['name']}, args: {call.get('arguments', {})}")

# Access other optional fields

reasoning = resp.get("reasoning")
if reasoning:
    print("Model reasoning:", reasoning)

metadata = resp.get("metadata", {})
print("Metadata:", metadata)

```

The test suite in [`tests/test_inference.py`](https://github.com/cactus-compute/needle/blob/main/tests/test_inference.py) demonstrates this pattern when validating `function_calls` presence in the returned dictionary, confirming that production code should treat these fields as optional.

## Summary

- **`Needle.complete()`** returns a plain Python `dict` parsed from JSON in [`needle/__init__.py`](https://github.com/cactus-compute/needle/blob/main/needle/__init__.py)
- **Optional fields** like `function_calls`, `reasoning`, and `metadata` appear only when the engine emits them
- **Always use `.get()`** or `in` checks to access optional fields safely and avoid `KeyError`
- The **response envelope** is not schema-enforced, so defensive programming is required for robust integrations

## Frequently Asked Questions

### What optional fields can appear in a Needle.complete() response?

The response may include `function_calls` (when tools are used), `reasoning` (when the model provides explanations), `metadata` (provider-specific data), and `confidence` (when weights are configured). These fields are not guaranteed and depend entirely on the model output and request parameters.

### Why does Needle.complete() return a dictionary instead of a typed object?

The library passes through the raw JSON envelope from the underlying C-API engine without unmarshaling it into a fixed dataclass or Pydantic model. This design, implemented in [`needle/__init__.py`](https://github.com/cactus-compute/needle/blob/main/needle/__init__.py), allows the library to remain agnostic to provider-specific extensions and future fields without requiring schema updates.

### How do I handle missing optional fields without raising KeyError?

Use the dictionary `get()` method with an appropriate default value, such as `resp.get("function_calls", [])` or `resp.get("reasoning")`. Alternatively, check for key existence using `if "field_name" in resp` before accessing the value. Never use direct bracket notation for optional fields.

### Where is the response parsing logic implemented in the Needle source code?

The response parsing occurs in [`needle/__init__.py`](https://github.com/cactus-compute/needle/blob/main/needle/__init__.py) around lines 52-63, where the raw buffer is decoded from UTF-8 and passed through `json.loads()`. This file also conditionally enriches the response with additional fields like `confidence` before returning the final dictionary to the caller.