compositetools

package
v0.42.1 Latest Latest
Warning

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

Go to latest
Published: Aug 10, 2026 License: Apache-2.0 Imports: 11 Imported by: 0

Documentation

Overview

Package compositetools provides a MultiSession decorator that adds composite tool (workflow) capabilities to a session.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CheckAnnotationContradiction added in v0.42.1

func CheckAnnotationContradiction(explicit, floor *vmcp.ToolAnnotations) error

CheckAnnotationContradiction reports whether explicit annotations would make a composite tool look SAFER than its derived safety floor allows:

  • readOnlyHint=true while the floor is not true
  • destructiveHint=false while the floor is true
  • openWorldHint=false while the floor is true

idempotentHint never contradicts, and an explicit hint MORE conservative than the floor (e.g. readOnlyHint=false when the floor is true) is allowed.

DeriveCompositeAnnotations always populates ReadOnlyHint, DestructiveHint, and OpenWorldHint when it returns a non-nil floor, so the nil-hint branches below are defensive (they would only matter for a hand-built floor). A nil floor (no tool steps) or nil explicit means there is nothing to guard and the check returns nil.

func CompositeToolNames added in v0.42.1

func CompositeToolNames(defs map[string]*composer.WorkflowDefinition) []string

CompositeToolNames returns the names of the composite tools in defs. Order is undefined (map iteration). Used for name-conflict detection so annotation policy cannot drop a colliding name from the conflict check.

func ConvertWorkflowDefsToTools

func ConvertWorkflowDefsToTools(
	defs map[string]*composer.WorkflowDefinition,
	stepResolver StepAnnotationResolver,
) []vmcp.Tool

ConvertWorkflowDefsToTools converts workflow definitions to vmcp.Tool format.

This creates the tool metadata (name, description, schema) that gets exposed via the MCP tools/list endpoint. The actual workflow execution logic is handled by the workflow executor adapters created separately.

Each workflow definition becomes a tool with:

  • Name: workflow.Name
  • Description: workflow.Description
  • InputSchema: workflow.Parameters (JSON Schema format)
  • OutputSchema: workflow.Output (JSON Schema format, if defined)
  • Annotations: the safety floor derived from the step tools' annotations, merged with the workflow's explicit annotations, if any. When a workflow has at least one tool step the floor is always non-nil (fail-closed): backends that declare no annotations produce a conservative floor rather than no floor.

stepResolver may be nil (or return nil for every step), in which case each tool step's annotations are treated as unknown and taint the floor conservatively. When a workflow's explicit annotations contradict the derived safety floor, the composite tool is DROPPED (not advertised) with a warning that names the offending step tool(s) — an explicit declaration must never make a tool look safer than its steps allow.

Returns a slice of vmcp.Tool ready for aggregation and exposure to clients.

func DeriveCompositeAnnotations added in v0.42.1

func DeriveCompositeAnnotations(stepAnn []*vmcp.ToolAnnotations) *vmcp.ToolAnnotations

DeriveCompositeAnnotations computes the safety-floor annotations for a composite tool from the annotations of its step tools.

Fail-closed contract (issue #6192):

  • A workflow with NO tool steps (e.g. only elicitation steps) yields an empty/nil stepAnn slice, and Derive returns nil — there is nothing to derive, so no floor is advertised.
  • A workflow with one or more tool steps yields a non-nil stepAnn slice, and Derive ALWAYS returns a conservative floor, even when every step tool's annotations are nil/unknown. An unknown step never makes the tool look safer — it taints destructive/openWorld to true and readOnly to false. This means an explicit readOnlyHint:true over backends that declare no annotations (the common case) CONTRADICTS the floor and is dropped by CheckAnnotationContradiction.

Derivation rules per hint:

  • ReadOnlyHint: AND across steps — true only when every step declares readOnlyHint=true; any step that is nil or false makes it non-read-only.
  • DestructiveHint: OR across steps — true when any step is nil or declares destructiveHint=true (an unknown step is tainted conservatively).
  • OpenWorldHint: OR across steps — true when any step is nil or declares openWorldHint=true.
  • IdempotentHint: never derived (always nil) — idempotency does not compose across multi-step workflows.

func FilterWorkflowDefsByAnnotations added in v0.42.1

func FilterWorkflowDefsByAnnotations(
	defs map[string]*composer.WorkflowDefinition,
	stepResolver StepAnnotationResolver,
) map[string]*composer.WorkflowDefinition

FilterWorkflowDefsByAnnotations returns only the workflow definitions whose explicit annotations do not contradict the derived safety floor. Definitions that contradict are omitted (with the same warning resolveCompositeAnnotations already emits). This is the CallTool/ListTools shared gate — callers that execute composites must use this filtered set so a dropped tool is never callable.

func FilterWorkflowDefsForSession

func FilterWorkflowDefsForSession(
	defs map[string]*composer.WorkflowDefinition,
	rt *vmcp.RoutingTable,
) map[string]*composer.WorkflowDefinition

FilterWorkflowDefsForSession returns only the workflow definitions whose every tool step references a backend tool that is present in the session routing table.

If a session does not have access to a backend tool (e.g. due to identity-based filtering), any composite tool that depends on that backend tool is also excluded. This prevents a session from invoking a composite tool that would fail at runtime because one or more of its underlying tools are not routable for that session.

func MergeAnnotations added in v0.42.1

func MergeAnnotations(floor, explicit *vmcp.ToolAnnotations) *vmcp.ToolAnnotations

MergeAnnotations merges explicit annotations over the derived floor. Per hint, an explicit non-nil value wins over the floor; Title behaves the same (a non-empty explicit Title wins). Returns nil when both inputs are nil.

The returned value is a deep copy: *bool pointer fields and the Title string are copied so the advertised tool does not alias the author's config pointers. The inputs are not modified.

func NewDecorator

func NewDecorator(
	sess sessiontypes.MultiSession,
	compositeTools []vmcp.Tool,
	executors map[string]WorkflowExecutor,
) sessiontypes.MultiSession

NewDecorator wraps sess with composite tool support. compositeTools is the metadata list appended to session.Tools(). executors maps each composite tool name to its workflow executor. Both may be nil/empty.

func ValidateNoToolConflicts

func ValidateNoToolConflicts(backendTools []vmcp.Tool, compositeNames []string) error

ValidateNoToolConflicts validates that composite tool names don't conflict with backend tool names.

Tool name conflicts would cause ambiguity in routing/execution:

  • Which tool should be invoked when a client calls the name?
  • Should it route to the backend or execute the workflow?

This validation ensures clear separation and prevents runtime confusion. Returns an error listing all conflicting tool names if any conflicts are found.

Prefer CompositeToolNames(defs) for the compositeNames argument so conflict detection never depends on annotation conversion (which can drop tools).

Types

type StepAnnotationResolver added in v0.42.1

type StepAnnotationResolver func(stepTool string) *vmcp.ToolAnnotations

StepAnnotationResolver resolves a composite-tool step's tool reference ("{workloadID}.{toolName}") to the backend tool's annotations. It returns nil when the step tool is unknown or the backend declares no annotations.

type WorkflowExecutor

type WorkflowExecutor interface {
	ExecuteWorkflow(ctx context.Context, params map[string]any) (*WorkflowResult, error)
}

WorkflowExecutor executes a named composite tool workflow.

type WorkflowResult

type WorkflowResult struct {
	Output map[string]any
	Error  error
}

WorkflowResult holds the output of a workflow execution.

Jump to

Keyboard shortcuts

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