Help us shape the future of Go! Take the 2026 Go Developer Survey

submitresult

package
v0.11.78 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 29, 2026 License: Apache-2.0 Imports: 27 Imported by: 0

Documentation

Overview

Package submitresult provides tool definitions for AI agents to submit their final results.

It exposes ClaudeTool, GoogleTool, and OpenAITool constructors that build executor submit metadata for the terminal submit_result tool, which agents call to return a structured response at the end of a conversation. The handlers parse the call into a toolcall.SubmitOutcome; the executor decides whether the parsed response commits (ending the run) after running its registered result validators (see the executors' WithResultValidator option), or is rejected back to the model with the validators' findings so the loop continues.

Tool metadata comes from a `submitresult:"..."` struct tag on a blank field of the response type: comma-delimited key=value pairs (name, description, payload, payloadDescription, success) and the bare key flat. A comma inside a value is written escaped as `\,` (`\\,` inside a raw-string tag); an unescaped comma ends the value.

Under flat (Options.FlatPayload) each payload property is its own tool parameter, read by exact name, and a submit with a required one missing or null is rejected; the payload leniency below applies only to a nested payload.

Payload leniency: when the model JSON-encodes the payload object into a string instead of passing it as a nested object (a common model mistake), the handlers transparently decode the string and accept the submit instead of rejecting it with a parameter error. The object may be followed by spurious closing delimiters or closing markup tags such as `</invoke>`. Strings that do not contain a JSON object, or that carry other content after it, are still rejected back to the model. When the payload parameter is absent because the model wrote it inside the reasoning string, after a `<parameter name="...">` opener for the payload field, the same rule recovers it from there and the reasoning keeps only the prose before the opener. The same rule recovers a payload the model wrote as a `"<payload>": {...}` JSON member inside the reasoning string (it wrote the whole argument object as text), and the reasoning keeps only the text before that member. A present payload parameter is never overridden. A nested payload that the rule declines in either form is rejected with a hint naming where the payload went; for a JSON member, the hint gives its byte offset in reasoning and asks for the payload as the top-level parameter.

A rejection records ErrParameter wrapping the cause — the same corrective hint the model receives, naming the parameter at fault — so the trace an engineer reads says which of the four causes fired (arguments that did not decode, an absent or mistyped parameter, a stringified payload coercion declined, or a nested payload recovery declined, after an opener or from a JSON member) rather than collapsing them into one string. A declined stringified payload also records its length and a bounded, quoted opening prefix, which is what distinguishes a wrapped object from a YAML document from a truncated write. Consumers that gate on the class match ErrParameter with errors.Is, never the message.

Index

Examples

Constants

This section is empty.

Variables

View Source
var ErrParameter = errors.New("parameter error")

ErrParameter marks a submit rejected before its payload could be parsed, for one of four causes: the arguments did not decode as JSON, a required parameter was absent or of the wrong JSON type, coercion declined a stringified payload, or a payload written inside the reasoning string could not be recovered. Every recording wraps the cause, so a trace names which one fired instead of collapsing them into one string. Consumers gating on the class match this sentinel with errors.Is rather than the message: an unparsed-arguments cause quotes model-controlled text.

Functions

func ClaudeTool

func ClaudeTool[Response any](opts Options[Response]) (claudetool.SubmitMetadata[Response], error)

ClaudeTool constructs the Claude executor metadata for the submit_result tool.

Example

ExampleClaudeTool demonstrates constructing the Claude submit_result tool metadata for a custom response type.

package main

import (
	"fmt"

	"chainguard.dev/driftlessaf/agents/submitresult"
)

func main() {
	type MyResult struct {
		Summary string `json:"summary" jsonschema:"required,description=Summary of findings"`
	}

	tool, err := submitresult.ClaudeTool[*MyResult](submitresult.Options[*MyResult]{
		Description:        "Submit the final analysis result.",
		PayloadDescription: "Structured analysis result.",
	})
	if err != nil {
		panic(err)
	}
	fmt.Println("tool name:", tool.Definition.Name)
}
Output:
tool name: submit_result

func ClaudeToolForResponse

func ClaudeToolForResponse[Response any]() (claudetool.SubmitMetadata[Response], error)

ClaudeToolForResponse constructs the submit_result tool using metadata inferred from the response type annotations.

func GoogleTool

func GoogleTool[Response any](opts Options[Response]) (googletool.SubmitMetadata[Response], error)

GoogleTool constructs the Google executor metadata for the submit_result tool.

func GoogleToolForResponse

func GoogleToolForResponse[Response any]() (googletool.SubmitMetadata[Response], error)

GoogleToolForResponse constructs the submit_result tool using metadata inferred from the response type annotations.

func OpenAITool added in v0.3.0

func OpenAITool[Response any](opts Options[Response]) (openaistool.SubmitMetadata[Response], error)

OpenAITool constructs the OpenAI executor metadata for the submit_result tool.

func OpenAIToolForResponse added in v0.3.0

func OpenAIToolForResponse[Response any]() (openaistool.SubmitMetadata[Response], error)

OpenAIToolForResponse constructs the submit_result tool using metadata inferred from the response type annotations.

Types

type Options

type Options[Response any] struct {
	ToolName           string
	Description        string
	SuccessMessage     string
	PayloadFieldName   string
	PayloadDescription string
	Generator          *schema.Generator

	// OmitReasoning removes the separate reasoning string from the terminal
	// tool schema. Use it when the structured payload already carries the full
	// reasoning and splitting a large result across two arguments adds no value.
	OmitReasoning bool

	// OmitPayloadFields lists JSON property names to withhold from the payload
	// schema advertised to the model, and from that schema's required list.
	// Response itself is untouched: decoding, the result the agent returns, and
	// the type its trace is recorded under all stay the same, so a caller can
	// hide an affordance behind a runtime dial without maintaining a mirror of
	// the response type for the hidden shape.
	//
	// Withholding a field from the schema is not the same as rejecting it: a
	// model that invents the property anyway still decodes into Response.
	// Callers for whom the hidden field is load-bearing must also ignore it on
	// the way out.
	//
	// Every name must match a property of the reflected schema; an unmatched
	// name fails tool construction rather than leaving the field advertised,
	// so a later json-tag rename cannot silently re-expose it.
	OmitPayloadFields []string

	// FlatPayload advertises each payload property as its own tool
	// parameter, beside reasoning, instead of the payload as one object
	// parameter named PayloadFieldName; PayloadFieldName and
	// PayloadDescription go unused. Claude sometimes writes an object
	// parameter's members as nested parameter tags, which the API cuts off
	// at the first closing tag and delivers as a string; a flat tool of
	// scalar properties has no object parameter to write that way. An
	// object or array property is still one, and no string coercion
	// applies to it. A submit is read by exact property name, and one
	// missing or null for a required property is rejected. A payload
	// property named reasoning needs OmitReasoning.
	FlatPayload bool
}

Options configures the submit_result tool wiring.

func OptionsForResponse

func OptionsForResponse[T any]() Options[T]

OptionsForResponse returns an Options pre-populated from the annotations present on the response type T. Callers may further customize the returned struct before passing it to ClaudeTool or GoogleTool.

type ResponsesMetadata added in v0.10.66

type ResponsesMetadata[Response any] struct {
	Definition responses.FunctionToolParam
	Handler    func(context.Context, toolcall.ToolCall, *agenttrace.Trace[Response]) toolcall.SubmitOutcome[Response]
}

ResponsesMetadata describes the terminal function for the Responses protocol. Handler parses a provider-neutral call; the executor must validate an accepted outcome before committing it as the final result.

func ResponsesTool added in v0.10.66

func ResponsesTool[Response any](opts Options[Response]) (ResponsesMetadata[Response], error)

ResponsesTool constructs a native Responses submit function without a client or credentials. It shares payload parsing with the other protocol adapters.

Example
package main

import (
	"fmt"

	"chainguard.dev/driftlessaf/agents/submitresult"
)

func main() {
	type Result struct {
		Summary string `json:"summary"`
	}
	tool, err := submitresult.ResponsesTool(submitresult.OptionsForResponse[Result]())
	if err != nil {
		panic(err)
	}
	fmt.Println(tool.Definition.Name)
}
Output:
submit_result

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL