Documentation
¶
Overview ¶
Package tool implements the Tool Gateway decision chain of the Fenced kernel: versioned descriptors, canonical argument normalization, policy evaluation, human approval binding, budget hard-stop and durable side-effect receipts (architecture §9.2, §12.2; invariants 6 and 9).
Index ¶
- Variables
- func CompareToolVersions(left, right string) int
- func LatestVersionPerName(descriptors []store.ToolDescriptor) []store.ToolDescriptor
- func NormalizeArgs(paramsSchema json.RawMessage, args []byte, maxBytes int64) (json.RawMessage, [sha256.Size]byte, error)
- type ApprovalNotUsableError
- type ApprovalNotUsableReason
- type ExecutionRequest
- type ExecutionResult
- type Gateway
- func (g *Gateway) GetToolDescriptor(ctx context.Context, tenantID, name, version string) (store.ToolDescriptor, error)
- func (g *Gateway) InvokeTool(ctx context.Context, in InvokeInput) (InvokeResult, error)
- func (g *Gateway) ListTools(ctx context.Context, tenantID string) ([]store.ToolDescriptor, error)
- type GatewayOption
- type InvokeInput
- type InvokeOutcome
- type InvokeResult
- type PolicyChecker
- type ReceiptStore
- type SecretBroker
- type SecretHandle
- type SecretScope
- type ToolExecutionError
- type ToolExecutor
Constants ¶
This section is empty.
Variables ¶
var ( // ErrToolArgsInvalid reports arguments that fail schema validation or // size bounds. ErrToolArgsInvalid = errors.New("tool arguments are invalid") // ErrBudgetExhausted is the hard-stop outcome: the task budget is // exhausted and new consumption must stop (invariant 12). ErrBudgetExhausted = errors.New("task budget exhausted: new consumption stopped") // ErrToolExecutionFailed reports a tool that ran but did not succeed; the // failure is already recorded in the side-effect receipt. ErrToolExecutionFailed = errors.New("tool execution failed") )
Functions ¶
func CompareToolVersions ¶
CompareToolVersions orders two tool versions: semantic versions compare numerically; anything else falls back to a byte-wise comparison so non-semver registry labels stay deterministic.
func LatestVersionPerName ¶
func LatestVersionPerName(descriptors []store.ToolDescriptor) []store.ToolDescriptor
LatestVersionPerName collapses descriptors to exactly one entry per tool name: the latest version among the given (already capability-filtered) set, in stable name order (P1-02). The model-facing surface must never advertise two same-named tools — duplicate names are ambiguous for the model and rejected by downstream consumers — while invocation keeps resolving bare names to this same latest version, so what tools/list shows is exactly what a bare-name call executes. Explicit "name@version" references continue to pin any granted older version.
func NormalizeArgs ¶
func NormalizeArgs(paramsSchema json.RawMessage, args []byte, maxBytes int64) (json.RawMessage, [sha256.Size]byte, error)
NormalizeArgs validates the invocation arguments against the descriptor's JSON Schema, rejects non-object or oversized documents, and returns the canonical normalized document together with its SHA-256. Two invocations with semantically identical arguments always hash to the same value, which is what approvals and idempotency are bound to; the normalized document is what the executing adapter receives.
Types ¶
type ApprovalNotUsableError ¶
type ApprovalNotUsableError struct {
Reason ApprovalNotUsableReason
Err error
}
ApprovalNotUsableError carries the reason behind an unusable approval.
func (*ApprovalNotUsableError) Error ¶
func (e *ApprovalNotUsableError) Error() string
func (*ApprovalNotUsableError) Unwrap ¶
func (e *ApprovalNotUsableError) Unwrap() error
type ApprovalNotUsableReason ¶
type ApprovalNotUsableReason string
ApprovalNotUsableReason classifies why a bound approval cannot authorize an invocation, so the fenced boundary and the runtime can react differently to "still pending" (park) versus "rejected or expired" (fail).
const ( ApprovalPending ApprovalNotUsableReason = "PENDING" ApprovalRejected ApprovalNotUsableReason = "REJECTED" ApprovalExpired ApprovalNotUsableReason = "EXPIRED" ApprovalBindingMismatch ApprovalNotUsableReason = "BINDING_MISMATCH" )
type ExecutionRequest ¶
type ExecutionRequest struct {
Descriptor store.ToolDescriptor
Action string
Resource string
Args json.RawMessage
Secret SecretHandle
}
ExecutionRequest is the sanitized input an executing adapter receives.
type ExecutionResult ¶
type ExecutionResult struct {
Output json.RawMessage
FailureCode string
}
ExecutionResult is the outcome of one tool execution. Output must already be sanitized by the adapter; the gateway additionally bounds and redacts it.
type Gateway ¶
type Gateway struct {
// contains filtered or unexported fields
}
Gateway orchestrates the tool decision chain. It is the enforcement point for policy, approval binding, budget hard-stop and receipts; the executing adapter is injected so the chain is testable without real tools.
func NewGateway ¶
func NewGateway(policyChecker PolicyChecker, tools store.ToolStore, budget store.BudgetStore, receipts ReceiptStore, executor ToolExecutor, secrets SecretBroker, options ...GatewayOption) *Gateway
func (*Gateway) GetToolDescriptor ¶
func (g *Gateway) GetToolDescriptor(ctx context.Context, tenantID, name, version string) (store.ToolDescriptor, error)
GetToolDescriptor returns one immutable descriptor. An empty version selects the registry's latest; the gateway service pins a concrete version before it reaches here whenever a capability freeze is enforced.
func (*Gateway) InvokeTool ¶
func (g *Gateway) InvokeTool(ctx context.Context, in InvokeInput) (InvokeResult, error)
InvokeTool runs one invocation through the full decision chain.
type GatewayOption ¶
type GatewayOption func(*Gateway)
GatewayOption configures a Gateway.
func WithApprovalTTL ¶
func WithApprovalTTL(ttl time.Duration) GatewayOption
WithApprovalTTL sets the lifetime of created approval requests (default 15 minutes).
func WithBounds ¶
func WithBounds(maxArgsBytes, maxResultBytes int64) GatewayOption
WithBounds sets the argument and result size bounds (defaults 64 KiB and 1 MiB).
type InvokeInput ¶
type InvokeInput struct {
TenantID string
TaskID uuid.UUID
RunID uuid.UUID
AttemptID uuid.UUID
// FencingToken is the fenced identity of the invoking Attempt. The
// gateway itself does not verify it (lease/fencing is enforced by the
// Runtime Protocol boundary); carriers pass it through so downstream
// fenced transports (for example a worker's gRPC forwarding) can
// preserve it.
FencingToken int64
AgentVersionRef string
// SecretRef is an optional symbolic capability from the immutable
// AgentVersion manifest. Empty means this invocation receives no secret.
SecretRef string
ToolName string
// ToolVersion selects a descriptor; empty resolves the latest version.
ToolVersion string
Action string
Resource string
Args json.RawMessage
IdempotencyKey string
// ApprovalID is required when the previous decision was REQUIRES_APPROVAL
// and a human decided it; the gateway re-checks the binding (§9.2).
ApprovalID *uuid.UUID
}
InvokeInput is a fenced tool invocation from a running Attempt.
type InvokeOutcome ¶
type InvokeOutcome string
InvokeOutcome classifies the result of an invocation.
const ( // OutcomeExecuted: the tool ran and its receipt is durable. OutcomeExecuted InvokeOutcome = "EXECUTED" // OutcomeDenied: policy denied the invocation; nothing ran. OutcomeDenied InvokeOutcome = "DENIED" // OutcomeRequiresApproval: a human decision is required; no budget or // side effect was touched. OutcomeRequiresApproval InvokeOutcome = "REQUIRES_APPROVAL" // OutcomeReplayed: the identical invocation already ran; the stored // receipt is returned without re-execution. OutcomeReplayed InvokeOutcome = "REPLAYED" )
type InvokeResult ¶
type InvokeResult struct {
Outcome InvokeOutcome
ToolCall store.ToolCall
ApprovalID *uuid.UUID
Result json.RawMessage
ReceiptOperation string
DenyReasons []string
PolicyRevision string
}
InvokeResult is the machine-readable outcome of an invocation.
type PolicyChecker ¶
type PolicyChecker interface {
EvaluateTool(context.Context, string, policy.ToolContext) policy.Decision
}
PolicyChecker decides tool invocations outside the LLM. The engine is fail-closed: missing tenant data and evaluation errors deny by default.
type ReceiptStore ¶
type ReceiptStore interface {
GetRuntimeReceipt(context.Context, string, uuid.UUID, string, string) (store.RuntimeReceipt, error)
WriteRuntimeReceipt(context.Context, store.WriteRuntimeReceiptInput) error
}
ReceiptStore persists and replays side-effect receipts (at-least-once + idempotent consumer contract, ADR-003).
type SecretBroker ¶
type SecretBroker interface {
Issue(context.Context, SecretScope) (SecretHandle, error)
}
SecretBroker issues scoped handles for a tool invocation.
type SecretHandle ¶
type SecretHandle string
SecretHandle is an opaque, scope-limited capability handle. The actual credential is injected by the Tool Gateway into the executing adapter and never reaches the Agent (architecture §12.4).
type SecretScope ¶
type SecretScope struct {
TenantID string
AttemptID string
ToolName string
Resource string
SecretRef string
}
SecretScope describes the constrained capability a tool may use.
type ToolExecutionError ¶
ToolExecutionError carries the machine-readable failure code of a tool that ran but did not succeed. The receipt already records the failure, so a replay returns the same outcome.
func (*ToolExecutionError) Error ¶
func (e *ToolExecutionError) Error() string
func (*ToolExecutionError) Unwrap ¶
func (e *ToolExecutionError) Unwrap() error
type ToolExecutor ¶
type ToolExecutor interface {
Execute(context.Context, ExecutionRequest) (ExecutionResult, error)
}
ToolExecutor runs one tool invocation with a constrained credential.