Documentation
¶
Overview ¶
Package tool defines the provider-neutral executable tool contract, its binding and authorization boundaries, typed function adapter, and instance-scoped registry.
Example ¶
package main
import (
"context"
"fmt"
"github.com/Tangerg/scope/core/chat"
"github.com/Tangerg/scope/core/tool"
)
func main() {
type input struct {
A int `json:"a"`
B int `json:"b"`
}
add, err := tool.NewFunc(tool.FuncConfig{
Name: "add",
Description: "add two integers",
}, func(_ context.Context, value input) (int, error) {
return value.A + value.B, nil
})
if err != nil {
panic(err)
}
registry, err := tool.NewRegistry(add)
if err != nil {
panic(err)
}
fmt.Println(registry.Definitions()[0].Name)
binding, ok := registry.Resolve("add")
if !ok {
panic("missing add")
}
invocation, err := binding.Prepare(chat.ToolCall{ID: "call-1", Name: "add", Arguments: `{"a":2,"b":3}`})
if err != nil {
panic(err)
}
result, err := binding.Call(context.Background(), invocation)
if err != nil {
panic(err)
}
text, _ := result.Text()
fmt.Println(text)
}
Output: add 5
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( ErrDuplicateTool = errors.New("tool: duplicate tool") ErrInvalidRegistry = errors.New("tool: invalid registry") )
var ( ErrInvalidTool = errors.New("tool: invalid tool") ErrInvalidInvocation = errors.New("tool: invalid invocation") )
var ErrAuthorizationDenied = errors.New("tool: authorization denied")
ErrAuthorizationDenied marks a policy refusal rather than a tool failure.
var ErrInvalidFailure = errors.New("tool: invalid failure")
var ErrInvalidWrappingChain = errors.New("tool: invalid wrapping chain")
ErrInvalidWrappingChain reports a decorator chain too deep to traverse safely.
Functions ¶
Types ¶
type Authorization ¶
type Authorization struct {
// contains filtered or unexported fields
}
Authorization carries only the frozen model-visible contract and validated arguments, so policy code cannot bypass Binding or execute the invocation.
func (Authorization) Arguments ¶
func (a Authorization) Arguments() []byte
Arguments is detached for the same reason as Definition.
func (Authorization) Definition ¶
func (a Authorization) Definition() chat.ToolDefinition
Definition is detached because policy implementations may retain or annotate what they inspect without changing the executable contract.
type Authorizer ¶
type Authorizer interface {
Authorize(ctx context.Context, authorization Authorization) error
}
Authorizer is deliberately smaller than an application permission system: identity, consent, tenancy, and policy storage remain caller-owned context. Returning any error denies execution and preserves that cause.
type AuthorizerFunc ¶
type AuthorizerFunc func(context.Context, Authorization) error
AuthorizerFunc adapts a plain function to Authorizer, so a one-off policy does not require a named type.
func (AuthorizerFunc) Authorize ¶
func (a AuthorizerFunc) Authorize(ctx context.Context, authorization Authorization) error
type Binding ¶
type Binding struct {
// contains filtered or unexported fields
}
Binding freezes one Tool definition and compiles its input schema. It is the canonical trust boundary between an untrusted chat.ToolCall and execution. A successfully constructed Binding and every Invocation it creates are safe for concurrent use when the underlying Tool is safe for concurrent calls.
func (Binding) Call ¶
func (b Binding) Call(ctx context.Context, invocation Invocation) (chat.ToolOutput, error)
Call executes an Invocation created by this exact Binding. It rejects values promoted by another binding even when the public Tool name happens to match.
func (Binding) Definition ¶
func (b Binding) Definition() chat.ToolDefinition
Definition returns an independent snapshot of the frozen definition.
type Failure ¶ added in v0.17.0
type Failure struct {
// contains filtered or unexported fields
}
Failure preserves a known tool failure's complete model-visible output and its original cause. It assigns no retry or control-flow policy. Runtimes may expose Output as an error ToolResult after applying their control-plane rules. Ordinary errors remain appropriate when no structured failure output exists.
func NewFailure ¶ added in v0.17.0
func NewFailure(cause error, output chat.ToolOutput) (*Failure, error)
NewFailure validates and snapshots output so error wrapping cannot lose its text, media, or structured details. cause must be non-nil.
func (*Failure) Output ¶ added in v0.17.0
func (f *Failure) Output() chat.ToolOutput
Output returns an independent copy of the complete failure output.
type Func ¶
type Func[In, Out any] struct { // contains filtered or unexported fields }
Func adapts a typed Go function to Tool. It owns the derived input contract, strict argument decoding, invocation, and result encoding.
Func is immutable after construction and is safe for concurrent calls when the wrapped function is safe for concurrent calls.
func NewFunc ¶
func NewFunc[In, Out any](config FuncConfig, function func(context.Context, In) (Out, error)) (Func[In, Out], error)
NewFunc derives the model-visible JSON Schema from the Go input type, so the advertised contract and the decoded arguments cannot drift apart. Hand- written schemas are the usual source of tools that accept what the model was told to send and then fail to decode it.
func (Func[In, Out]) Call ¶
func (f Func[In, Out]) Call(ctx context.Context, invocation Invocation) (chat.ToolOutput, error)
Call strictly decodes a promoted invocation, invokes the wrapped function, and returns a provider-neutral result.
func (Func[In, Out]) Definition ¶
func (f Func[In, Out]) Definition() chat.ToolDefinition
type FuncConfig ¶
FuncConfig describes a typed function tool. NewFunc derives InputSchema from In so the decoder and model-visible contract cannot drift independently.
type Guard ¶
type Guard struct {
// contains filtered or unexported fields
}
Guard keeps authorization at the universal Tool.Call boundary, which makes the same policy work for direct calls, registries, and managed runtimes.
func NewGuard ¶
func NewGuard(config GuardConfig) (Guard, error)
NewGuard snapshots the wrapped tool's definition at construction, so the contract policy evaluates is the contract the model was shown. Resolving it per call would let a mutable inner tool widen its own arguments after approval.
func (Guard) Call ¶
func (g Guard) Call(ctx context.Context, invocation Invocation) (chat.ToolOutput, error)
func (Guard) Definition ¶
func (g Guard) Definition() chat.ToolDefinition
type GuardConfig ¶
type GuardConfig struct {
Tool Tool
Authorizer Authorizer
}
GuardConfig names both collaborators explicitly so neither can be defaulted. A guard silently constructed without an authorizer would report as protected while permitting everything.
type Invocation ¶
type Invocation struct {
// contains filtered or unexported fields
}
Invocation is a complete JSON object validated against one exact frozen Tool definition. Its fields are intentionally private: only Binding.Prepare can promote an untrusted model proposal into an executable invocation.
func (Invocation) Arguments ¶
func (i Invocation) Arguments() []byte
Arguments returns an owned copy of the validated JSON object.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry is an instance-scoped, concurrency-safe collection of executable tools. Its zero value is ready to use. Each runtime or process owns its registry explicitly; there is no package-global counterpart. Registration is atomic for the full batch, definitions are snapshotted at registration time, and model-visible views are returned as defensive copies in stable name order.
func NewRegistry ¶
NewRegistry is a convenience over the usable zero value for the common case of a fixed tool set. Registration is all-or-nothing, so a duplicate name in the initial batch leaves no partially populated registry behind.
func (*Registry) Definitions ¶
func (r *Registry) Definitions() []chat.ToolDefinition
type Tool ¶
type Tool interface {
// Definition returns a detached, valid schema snapshot. Callers may expose or
// mutate the returned value without changing subsequent calls or execution.
Definition() chat.ToolDefinition
// Call executes one schema-validated invocation. Implementations still own
// capability-specific semantic validation. Ordinary failure is returned as
// error without assigning retry or control-flow meaning. Implementations must
// honor ctx and must not retain the invocation or its arguments.
// On error, the returned output is not consumed; use [Failure] to preserve
// complete failure content, including acknowledged partial effects.
Call(ctx context.Context, invocation Invocation) (chat.ToolOutput, error)
}
Tool is the minimal executable capability used by model-driven runtimes. Definition returns an independent snapshot safe to expose to a model. Call receives only an Invocation promoted by the exact frozen Binding.
Tool assigns no control-flow meaning to errors. Retry, pause, abort, and ordinary error feedback belong to the runtime driving the tool.
type WrappingTool ¶
type WrappingTool interface {
// Unwrap returns the next inner tool in a finite decorator chain. It must
// return the same tool for the wrapper's lifetime and must not perform I/O;
// cycles and excessive depth make the chain invalid.
Unwrap() Tool
}
WrappingTool is implemented by a decorator that stands in for another tool. Optional capabilities are resolved through this chain, so a decorator states once that it wraps a tool instead of re-implementing every optional interface the inner tool may acquire.