Documentation
¶
Overview ¶
Package loop runs one employee wake on a CloudWeGo Eino chat model.
A wake is: take the Host's frozen messages -> ask the model -> validate the native tool batch -> let the Host execute every call -> stop on a terminal decision or ask again within the budget. The Host owns context assembly, permissions, receipts and effects; the loop owns ordering, validation, budgets and the rule that nothing counts as done without a Host receipt.
out, err := loop.New(cfg, model, host).Run(ctx, loop.Wake{Identity: id, Messages: msgs})
Index ¶
- Constants
- Variables
- func Locales() []string
- func ToolInfos(tools []Tool) ([]*schema.ToolInfo, error)
- func ValidateArguments(schemaMap map[string]any, args map[string]any) []string
- type Budget
- type BudgetUsage
- type Config
- type Decision
- type Disposition
- type FinalTextHost
- type Host
- type HostFunc
- type Identity
- type Loop
- type ModelCall
- type Outcome
- type Receipt
- type Tool
- type ToolCall
- type ToolOutcome
- type ToolResult
- type Usage
- type Wake
Constants ¶
const ExtraParameters = "employee_loop.parameters"
ExtraParameters is the ToolInfo.Extra key carrying the original JSON Schema map, so a model adapter can send it without a lossy round trip.
const FinalTextOrigin = "host_final_text"
FinalTextOrigin marks the tool outcome of an accepted final text.
Variables ¶
var ( ErrModelBudget = errors.New("employee loop: model budget exhausted") ErrConsecutiveModelErrors = errors.New("employee loop: consecutive model errors exhausted") ErrModelResponseBudget = errors.New("employee loop: valid model response budget exhausted") ErrPhysicalModelBudget = errors.New("employee loop: provider attempt budget exhausted") ErrMissingReceipt = errors.New("employee loop: effect has no host receipt") ErrTerminalConflict = errors.New("employee loop: conflicting terminal tool results") // ErrToolRefused marks a Host refusal made before any effect (for example // an argument that names no known source). The model may correct the call // within the budget; it is not a batch failure. ErrToolRefused = errors.New("employee loop: tool call refused before any effect") )
Errors returned by Run. Budget errors are joined with ErrModelBudget.
Functions ¶
func ValidateArguments ¶
ValidateArguments checks arguments against the portable subset of JSON Schema used by tool contracts: type, required, additionalProperties=false, properties, enum, minLength, maxLength, minItems, maxItems and items. Hosts with a full validator add it through Config.ValidateBatch.
Types ¶
type BudgetUsage ¶
BudgetUsage counts accepted responses and the current error streak.
type Config ¶
type Config struct {
Tools []Tool
Budget Budget
// RequireTerminalTool makes plain assistant text private: only a
// Host-accepted terminal decision ends the wake (see AcceptFinalText).
RequireTerminalTool bool
// RequireNativeToolCall asks the provider for a tool call without
// choosing which one (tool_choice "required").
RequireNativeToolCall bool
// AcceptFinalText lets a FinalTextHost accept a first plain answer of up
// to FinalTextLimit bytes (default 8000) when RequireTerminalTool is set.
AcceptFinalText bool
FinalTextLimit int
// TurnTools narrows the tools offered to the next model call (call
// counts from 1) given the outcomes so far; nil offers every tool. Calls
// to a tool that was not offered are rejected like unknown tools.
TurnTools func(call int, outcomes []ToolOutcome) []string
// Locale selects the built-in repair texts (en, zh-CN).
Locale string
// RepairText replaces the built-in instruction appended after a rejected
// response or provider error.
RepairText func(err error) string
// ValidateBatch and ValidateText add Host rules to the built-in batch
// validation (unknown tools, exclusivity, terminal conflicts, argument
// schemas) and to public text (plain replies and "reply" arguments).
ValidateBatch func([]ToolCall) error
ValidateText func(string) error
// Permanent classifies provider errors that end the wake at once.
Permanent func(error) bool
// Hooks observe the wake; they never change it and must not block.
OnModelCall func(context.Context, ModelCall)
OnToolCall func(context.Context, ToolCall, ToolResult, error, time.Duration)
OnBatchRejected func([]ToolCall, error)
OnModelFailure func(error)
}
Config configures a loop. Everything Host-specific is injected here.
type Decision ¶
type Decision struct {
Kind Disposition
Reply string
}
Decision is a Host-accepted terminal disposition, or a plain text reply when the wake does not require a terminal tool. Reply may accompany Dispatched and Waiting.
type Disposition ¶
type Disposition string
Disposition is how a wake ended.
const ( Reply Disposition = "reply" Quiet Disposition = "quiet" Dispatched Disposition = "dispatched" Waiting Disposition = "waiting" )
type FinalTextHost ¶
type FinalTextHost interface {
AcceptFinalText(context.Context, Identity, string) (ToolResult, error)
}
FinalTextHost accepts a first plain answer as the public reply of a wake that otherwise requires a terminal tool (Config.AcceptFinalText).
type Host ¶
Host owns reads, permissions, durable state and effects. Execute honours ctx and deduplicates effects by identity plus NativeToolCallID; a committed effect returns its receipt even when ctx was cancelled after the commit. The loop never invents a receipt.
type Identity ¶
Identity is supplied by the Host from trusted admission data and passed back to every Host call. The loop never reads or changes it.
type Loop ¶
type Loop struct {
// contains filtered or unexported fields
}
Loop runs wakes with one configuration. It holds no state between runs.
type ModelCall ¶
type ModelCall struct {
Attempt int
Request []*schema.Message
Response *schema.Message
Err error
Elapsed time.Duration
}
ModelCall describes one provider request for observers.
type Outcome ¶
type Outcome struct {
Decision
// ModelCalls counts provider requests (physical attempts).
ModelCalls int
Receipts []Receipt
ToolOutcomes []ToolOutcome
BudgetUsage BudgetUsage
Usage Usage
// Transcript is the accepted conversation: the wake's messages, accepted
// responses and their tool results. Rejected output is never kept.
Transcript []*schema.Message
}
Outcome is the result of one wake. Callers check Run's error as well: ToolOutcomes may hold committed effects of a failed wake.
type Tool ¶
type Tool struct {
Name string
Description string
// Schema is the JSON Schema of the arguments, sent to the model and used
// for validation before any call runs.
Schema map[string]any
// Effect tools change the world; a successful call must return a Host
// receipt.
Effect bool
// Terminal declares the disposition the tool always ends with, so a
// batch mixing dispositions is rejected before any effect.
Terminal Disposition
// Exclusive tools must be the only call of their batch.
Exclusive bool
// Timeout bounds one call; zero leaves it to the wake context.
Timeout time.Duration
}
Tool is a capability supplied by the Host.
type ToolCall ¶
type ToolCall struct {
// Origin marks calls the loop made on the Host's behalf (FinalTextOrigin).
Origin string `json:"origin,omitempty"`
NativeToolCallID string `json:"native_tool_call_id"`
Name string `json:"name"`
Arguments map[string]any `json:"arguments"`
}
ToolCall is one native call of a model response.
type ToolOutcome ¶
type ToolOutcome struct {
Origin string
NativeToolCallID string
ToolName string
Result ToolResult
Error string
}
ToolOutcome is one Host result in call order, including committed effects returned with an error. It does not claim the batch completed.
type ToolResult ¶
ToolResult is the Host's answer to a call. Content is what the model sees.