Skip to documentation
Documentation navigation

Documentation navigation

Documentation / guides

Structured output with tools

Combine ordinary tools with structured output only when the model advertises both.

developer

Structured output and ordinary tool calls are separate representations. A request that exposes both must use a model with Caps.StructuredOutputWithTools; the capability implies Caps.Tools and Caps.StructuredOutput.

Request gate

request := inference.Request{
	Model: model.CustomModel(
		model.ProviderName("acme"), model.APIFormatOpenAI,
		"https://api.example.test", "agent",
		model.WithTools(),
		model.WithStructuredOutputWithTools(),
	),
	Tools: []inference.Tool{{Name: "lookup", Description: "Read a record."}},
	Output: &inference.OutputSchema{
		Name: "final_answer",
		Schema: json.RawMessage(`{"type":"object","properties":{"answer":{"type":"string"}},"required":["answer"],"additionalProperties":false}`),
	},
}
if err := inference.ValidateRequestFeatures(request); err != nil {
	panic(err)
}

StructuredOutputToolName is reserved for the internal terminal representation. An ordinary tool with that name returns StructuredOutputConflictError. Duplicate ordinary tool names also fail when output is requested.

Response representations

With FinishReasonToolUse, structured extraction requires exactly one ToolUseBlock named _looprig_final_output and may include thinking blocks only. An ordinary tool call, natural-language text, or a mixture is a contradiction. With FinishReasonStop, extraction requires text and rejects any tool call.

Proof

Related: Tool definitions, Tool-call deltas, Tool choice.

← back to documentation