submitresult

package
v0.11.13 Latest Latest
Warning

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

Go to latest
Published: Oct 9, 2026 License: Apache-2.0 Imports: 24 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). A comma inside a value is written escaped as `\,` (`\\,` inside a raw-string tag); an unescaped comma ends the value.

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; a nested payload that rule declines is rejected with a hint naming where the payload went.

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) 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
}

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