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

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, the response handling looks like this:


# 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. 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 when self._weights is configured. The source explicitly inserts this key only when weights are present:

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:

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 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
  • 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, 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 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.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →