Needle 2 `complete()` Response Structure: Complete Field Reference
Needle.complete() returns a strictly JSON-compatible Python dictionary containing ten top-level keys that encode the model's turn output, including type, function_calls, reasoning, and performance metrics.
This guide breaks down the exact schema returned by the complete() method in the cactus-compute/needle repository. Understanding this contract is essential for parsing tool calls, handling errors, and optimizing inference performance in production agentic workflows.
Anatomy of the complete() Response
The response envelope follows a predictable schema defined in needle/__init__.py and documented in doc/apis.md. Every call returns the following ten fields:
type(str): The turn's contract. Values are"call"(tool execution),"text"(free-form response), or"refuse"(off-topic rejection).success(bool): Indicates whether the model considers the turn successful. Alwaystruefor correctly formed calls.error(str | null): Human-readable error message if generation failed.error_code(int | null): Reserved machine-readable error code (currently unused).function_calls(list[dict]): Array of tool invocations. Each entry containsname(the tool identifier) andarguments(a JSON object of inferred parameters).reasoning(str | null): Free-form derivation explaining how the model mapped natural language to arguments (e.g.,"'ten minutes' → minutes 10").confidence(float | null): Calibrated confidence score between 0 and 1. Returnsnullwhen using tuned weight files.prefill_tps(float | null): Tokens-per-second rate during the prefilling stage.decode_tps(float | null): Tokens-per-second rate during the decoding stage.peak_ram_mb(float | null): Approximate peak RAM consumption in megabytes during the turn.
The JSON grammar guarantees parseability without errors, making the response safe for direct deserialization in any language.
Parsing function_calls and Tool Execution
The function_calls array drives the agentic loop. When type equals "call", this list contains one or more dictionaries requiring execution.
import json
import needle
@needle.tool
def set_lights(room: str, on: bool, brightness: int = 0):
"""Turn a room's lights on/off."""
return {"room": room, "on": on, "brightness": brightness}
agent = needle.Needle(tools=[set_lights])
resp = agent.complete("Turn the kitchen lights on at 75%")
# Extract the call details
call = resp["function_calls"][0]
tool_name = call["name"] # "set_lights"
args = call["arguments"] # {"room": "kitchen", "on": true, "brightness": 75}
# Execute and feed back
result = set_lights(**args)
next_resp = agent.complete(json.dumps(result))
When the model refuses a request or no tool matches the query, function_calls returns an empty list [] and type shifts to "refuse" or "text".
Performance Metrics and Debugging
The response includes three engine-internal metrics useful for profiling:
prefill_tps: Measures prompt processing speed (prompt evaluation).decode_tps: Measures autoregressive generation speed.peak_ram_mb: Tracks memory pressure during the forward pass.
These fields help identify bottlenecks in high-throughput deployments.
Error Handling and Edge Cases
Error states are captured through the error and success fields. When success is false, error contains a descriptive string while error_code remains reserved for future use.
Confidence calibration behaves differently based on model weights. Base models return a calibrated confidence float, but tuned models set this field to null and emit a warning at construction time (as noted in doc/apis.md).
Source Code Implementation
The parsing logic resides in two critical files:
needle/__init__.py(lines 11-26): Implements thecomplete()wrapper that deserializes the native library's JSON payload and conditionally inserts theconfidencekey.doc/apis.md(lines 82-96): Documents the complete envelope schema with field descriptions and type constraints.tests/test_inference.py: Validates that responses contain mandatory keys (type,function_calls, etc.) and conform to the expected structure.
The contract is strictly enforced by the engine's grammar, ensuring backward compatibility as the API evolves.
Summary
- The
complete()response structure in Needle 2 is a flat dictionary with ten standardized keys. function_callscontains the primary actionable data, with each entry specifying a toolnameandargumentsobject.confidenceisnullfor tuned models but populated for base models.- Performance fields (
prefill_tps,decode_tps,peak_ram_mb) aid in latency and memory optimization. - The schema is strictly JSON-compatible and defined in
needle/__init__.pyanddoc/apis.md.
Frequently Asked Questions
What are the possible values for the type field in a Needle 2 response?
The type field accepts three string values: "call" when the model emits a tool invocation, "text" for free-form conversational responses, and "refuse" when the input is off-topic or violates safety constraints. This field determines how your application should handle the subsequent function_calls array.
Why is the confidence field null in my complete() responses?
The confidence field returns null when you load a tuned weight file because calibrated confidence scores are only available for base models. According to the source code in needle/__init__.py, the engine emits a one-time warning at construction when tuned weights are detected, indicating that confidence values will not be populated during inference.
How do I handle empty function_calls arrays?
An empty function_calls list indicates the model either refused the request (type: "refuse") or determined no registered tool matched the query (type: "text"). Your application should check the type field before attempting to iterate over function_calls, and fall back to displaying the reasoning field or a default message when no tools are invoked.
Where is the complete() response schema formally defined?
The schema is formally defined in the engine's envelope parser within needle/__init__.py (lines 11-26) and documented in doc/apis.md (lines 82-96). The tests/test_inference.py file provides the enforcement layer, ensuring all responses contain the mandatory keys and type signatures required by the API contract.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →