Documentation
¶
Overview ¶
Package interaction provides the model-directed execution Strategy for the Agent Framework. Input and Output reuse core/chat values.
A Definition owns the serializable working context, the model/Tool state machine, exact managed Delegate bindings, typed Delegate Artifacts, and an optional pure completion validator. A Dispatcher owns model I/O. A ToolSet binds ordinary executable Tools to a separate child Deployment that the Definition binds; its scheduling retains only frozen input validators and classifiers, never executable Tools or their backends. Hosts cover declaration identity in deployment digests. Direct model calls remain available through package chatclient without an Interaction or Engine.
Model-call and child work quotas default to unlimited; a finite zero MaxModelCalls is rejected at construction. Model boundary errors, including nil or structurally invalid responses, leave the Effect Unknown and require explicit Host resolution. A structurally valid response that violates Interaction constraints terminates with external / interaction.model.invalid_response without retrying the model or committing the rejected Step. Model preparation errors settle as definite host failures before external work begins.
Only FinishReasonToolCalls admits Tool and Delegate execution. Length-truncated calls receive model-visible feedback for another model attempt; calls accompanying other finish reasons fail the Process without execution. Restored pending batches satisfy the same rule, and advertised names must refer to bound deferred Tools.
Tool and Delegate children are requested only through Framework Effects. One child-call batch owns start confirmations, wait identity, boundary validation, and ordered results for both bindings. Tools refill their bounded window after any child drains; Delegates await their entire batch. Admission progress derives from the ordered invocation records, including retained settlements, so recovery needs no separate scheduling cursor. Each invocation is absent until its start is declared, then the same record retains its start receipt and result without a parallel requested marker. A rejected Tool child start terminates the Interaction with the original Failure, because the ToolSet is required infrastructure. A rejected Delegate start is a model-visible rejected result, because choosing another worker is the model's delegation policy. A Tool child's Failure propagates unchanged to the parent. A drained Delegate subtree with unresolved Effects fails the parent without another model call. A canceled parent never resumes to collect or publish children.
Each Tool call owns one Effect, its result, and any input continuation. Completed siblings retain their settlements when another call remains unknown or waits for input. A valid tool.Failure produces its model-visible error ToolResult and disposition; its Cause cannot turn it into cancellation, input, or host control. HostFailure, ordinary errors, invalid output, cancellation, deadlines, and a panic from Tool.Call leave the Tool Effect unknown until the Host settles it; terminating the Process retains those identities without establishing that external work failed. A panic from a tool's input validator is instead a definite failure classified before Tool.Call runs: it fails the Step without reaching the model and leaves no unknown Effect. Observer callbacks describe attempts and never replace the Engine's settlement boundary. A complete round continues to the model or completes directly only after its Checkpoint is acknowledged. Recovery never replays Tools or models: Hosts settle investigated outcomes with ToolSet.SettleToolResult or Dispatcher.SettleModelResult, using requests retained by agent.TreeSnapshot.EffectRequest, and submit them through agent.Process.ResolveUnknownEffect. Model context receives complete results in original call order.
SettledResults projects exact known results from the authoritative tree; it has no storage or acknowledgment role. ToolCallRef correlates one logical call across ToolInvocation.Reference, RoundResults.Reference, and ActiveDelegateChild.Reference; its ProcessID is the requesting Interaction, not the Tool child. A Tool child's reference comes only from the ToolChildKey its parent gave it, so a ToolSet run as a root or under any other ChildKey has none.
Descriptor.SignalSchema admits only steering envelopes as unaddressed input. NewSteerSignal steering accepted during model or child work applies before the next model call, after the current result batch; it never preempts a model request or answers a Tool input wait. Tool answers address the Tool child's wait through PendingToolInputs. A parent Strategy delivers the same SignalRequest through agent.NewChildSignalEffect. Unsupported envelopes are rejected before admission; semantic protocol violations discard the Step with a contract Failure, and a Step error never consumes input.
Index ¶
- Variables
- func AdvertiseTools(ctx context.Context, names ...string) error
- func DelegateChildKey(modelCallSequence uint64, toolCall chat.ToolCall) (agent.ChildKey, error)
- func HostFailure(cause error) error
- func NewSteerSignal(id agent.SignalID, messages ...chat.Message) (agent.SignalRequest, error)
- func NewToolInputResponseSignal(id agent.SignalID, waitID agent.WaitID, response json.RawMessage) (agent.SignalRequest, error)
- func RequireToolInput(prompt json.RawMessage, responseSchema json.RawMessage, ...) error
- func ToolChildKey(modelCallSequence uint64, toolCallIndex uint32) (agent.ChildKey, error)
- type ActiveDelegateChild
- func (a ActiveDelegateChild) ChildKey() agent.ChildKey
- func (a ActiveDelegateChild) ModelCallSequence() uint64
- func (a ActiveDelegateChild) ProcessID() agent.ProcessID
- func (a ActiveDelegateChild) Reference() (ToolCallRef, bool)
- func (a ActiveDelegateChild) ToolCall() chat.ToolCall
- func (a ActiveDelegateChild) ToolCallIndex() uint32
- func (a ActiveDelegateChild) Valid() bool
- type Artifact
- type CompletionCandidate
- type CompletionDecision
- type CompletionValidator
- type ConcurrentTool
- type Definition
- type DefinitionConfig
- type Delegate
- type DelegateConfig
- type DirectResultTool
- type Dispatcher
- func (d *Dispatcher) Dispatch(ctx context.Context, request agent.EffectRequest, emit agent.DeltaEmitter) (agent.Settlement, error)
- func (d *Dispatcher) ObservationFailures() ObservationFailures
- func (*Dispatcher) Policy(_ agent.Effect) agent.EffectPolicy
- func (d *Dispatcher) SettleModelResult(request agent.EffectRequest, response *chat.Response, messages []chat.Message) (agent.Settlement, error)
- type DispatcherConfig
- type Input
- type ModelContextReducer
- type ModelInvocation
- func (m ModelInvocation) AppliedSteerSignalIDs() []agent.SignalID
- func (m ModelInvocation) AttemptID() (agent.EffectAttemptID, bool)
- func (m ModelInvocation) DeploymentRef() agent.DeploymentRef
- func (m ModelInvocation) EffectID() agent.EffectID
- func (m ModelInvocation) ModelCallSequence() uint64
- func (m ModelInvocation) Relation() agent.ProcessRelation
- func (m ModelInvocation) StepSequence() uint64
- func (m ModelInvocation) TreeIncarnationID() (agent.TreeIncarnationID, bool)
- func (m ModelInvocation) Valid() bool
- type ModelObserver
- type ModelResponseDelta
- type ModelSettlement
- type ObservationFailures
- func (o ObservationFailures) LastModelSettledPanic() (ObserverPanic, bool)
- func (o ObservationFailures) LastModelStartedPanic() (ObserverPanic, bool)
- func (o ObservationFailures) LastToolSettledPanic() (ObserverPanic, bool)
- func (o ObservationFailures) LastToolStartedPanic() (ObserverPanic, bool)
- func (o ObservationFailures) ModelSettledPanics() uint64
- func (o ObservationFailures) ModelStartedPanics() uint64
- func (o ObservationFailures) ToolSettledPanics() uint64
- func (o ObservationFailures) ToolStartedPanics() uint64
- type ObserverPanic
- type Output
- type PendingToolInput
- func (p PendingToolInput) ProcessID() agent.ProcessID
- func (p PendingToolInput) Prompt() json.RawMessage
- func (p PendingToolInput) ResponseSchema() json.RawMessage
- func (p PendingToolInput) ResponseSignal(id agent.SignalID, response json.RawMessage) (agent.SignalRequest, error)
- func (p PendingToolInput) Valid() bool
- func (p PendingToolInput) WaitID() agent.WaitID
- type ResultDisposition
- type ResultEntry
- type RoundResults
- func (r RoundResults) CallCount() uint32
- func (r RoundResults) Complete() bool
- func (r RoundResults) Digest() agent.Digest
- func (r RoundResults) Entries() []ResultEntry
- func (r RoundResults) JSON() json.RawMessage
- func (r RoundResults) ModelCallSequence() uint64
- func (r RoundResults) Reference(toolCallIndex uint32) (ToolCallRef, bool)
- func (r RoundResults) Relation() agent.ProcessRelation
- type ToolCallRef
- func (ToolCallRef) JSONSchemaAlias() any
- func (t ToolCallRef) MarshalText() ([]byte, error)
- func (t ToolCallRef) ModelCallSequence() uint64
- func (t ToolCallRef) ProcessID() agent.ProcessID
- func (t ToolCallRef) String() string
- func (t ToolCallRef) ToolCallIndex() uint32
- func (t *ToolCallRef) UnmarshalText(text []byte) error
- func (t ToolCallRef) Valid() bool
- type ToolInputContinuation
- type ToolInvocation
- func (t ToolInvocation) AttemptID() (agent.EffectAttemptID, bool)
- func (t ToolInvocation) DeploymentRef() agent.DeploymentRef
- func (t ToolInvocation) EffectID() agent.EffectID
- func (t ToolInvocation) Reference() (ToolCallRef, bool)
- func (t ToolInvocation) Relation() agent.ProcessRelation
- func (t ToolInvocation) StepSequence() uint64
- func (t ToolInvocation) ToolCall() chat.ToolCall
- func (t ToolInvocation) TreeIncarnationID() (agent.TreeIncarnationID, bool)
- func (t ToolInvocation) Valid() bool
- type ToolObserver
- type ToolSet
- type ToolSetConfig
- type ToolSettlement
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( ErrInvalidResult = errors.New("interaction: invalid result") ErrInvalidToolInputRequest = errors.New("interaction: invalid tool input request") ErrToolInputRequired = errors.New("interaction: tool input required") ErrInvalidToolAdvertisement = errors.New("interaction: invalid tool advertisement") ErrInvalidPendingToolInput = errors.New("interaction: invalid pending tool input") ErrInvalidDefinitionConfig = errors.New("interaction: invalid definition configuration") ErrInvalidDispatcherConfig = errors.New("interaction: invalid dispatcher configuration") ErrInvalidToolSet = errors.New("interaction: invalid tool set") ErrInvalidToolCallRef = errors.New("interaction: invalid tool call reference") ErrInvalidDelegate = errors.New("interaction: invalid delegate") ErrInvalidArtifact = errors.New("interaction: invalid artifact") ErrInvalidInput = errors.New("interaction: invalid input") )
These sentinels belong to construction, domain values, Dispatcher operations, and Tool control flow rather than Steps, so they carry no Failure classification.
var ( ErrInvalidSteer = agent.NewClassifiedError( agent.FailureKindContract, "interaction.signal.invalid", "interaction: invalid steer", ) ErrInvalidExecutionState = agent.NewClassifiedError( agent.FailureKindContract, "interaction.state.invalid", "interaction: invalid execution state", ) ErrInvalidProtocol = agent.NewClassifiedError( agent.FailureKindContract, "interaction.protocol.invalid", "interaction: invalid protocol payload", ) // ErrInvalidModelResponse rejects the whole Step, so a structurally valid // response that violates Interaction constraints never enters its state. ErrInvalidModelResponse = agent.NewClassifiedError( agent.FailureKindExternal, "interaction.model.invalid_response", "interaction: invalid model response", ) )
Execution sentinels own the Failure persisted when they reach Step. Wrapping one is the only way a Step error acquires its classification. Protocol and restored-state errors stay distinct because their recovery responsibilities differ.
var ErrHostFailure = errors.New("interaction: host failure")
ErrHostFailure separates host infrastructure failure from model or tool behavior.
var ErrModelResponseTooLarge = errors.New("interaction: model response exceeds byte limit")
ErrModelResponseTooLarge reports response resource admission failure. After model execution starts, the incomplete response is discarded and its Effect remains unknown. Oversize replacement context is rejected before calling the model and settles as a definite host failure.
Functions ¶
func AdvertiseTools ¶
AdvertiseTools stages already-bound deferred Tools for model visibility from the next model call onward. The change commits only if the current Tool call succeeds. It never adds executable authority. Names must be exact deferred Tool names; repeated names are idempotent. A nil ctx is invalid and panics; a context without an active Tool call returns ErrToolAdvertisementUnavailable.
func DelegateChildKey ¶
DelegateChildKey correlates a Delegate ToolCall with its managed child Process.
func HostFailure ¶
HostFailure marks cause as an Interaction-host failure. A nil cause remains nil, and an already marked error is returned unchanged. A Tool returning this error supplies no definite ToolResult: its Effect remains unknown until the Host explicitly resolves it. Marking an error does not prove that external work failed or authorize replay.
func NewSteerSignal ¶
NewSteerSignal wraps user messages as an unaddressed Signal. The mailbox makes steering deduplicated, ordered, and snapshot-visible, so a resumed Process sees the same guidance. Steering admitted before a Tool input wait remains pending until the Tool batch settles, including admission during the Step that enters Waiting.
Example ¶
package main
import (
"fmt"
"github.com/Tangerg/scope/agent"
"github.com/Tangerg/scope/agent/strategy/interaction"
"github.com/Tangerg/scope/core/chat"
)
func main() {
id, err := agent.ParseSignalID("signal:user-correction")
if err != nil {
panic(err)
}
request, err := interaction.NewSteerSignal(
id,
chat.NewUserMessage(chat.NewTextPart("Use the newer requirements.")),
)
if err != nil {
panic(err)
}
_, addressesWait := request.WaitID()
fmt.Println(request.ID(), request.Valid(), addressesWait)
}
Output: signal:user-correction true false
func NewToolInputResponseSignal ¶
func NewToolInputResponseSignal( id agent.SignalID, waitID agent.WaitID, response json.RawMessage, ) (agent.SignalRequest, error)
NewToolInputResponseSignal validates JSON and addresses the exact wait. Execution checks the authoritative response schema; PendingToolInput.ResponseSignal also validates that schema locally.
func RequireToolInput ¶
func RequireToolInput( prompt json.RawMessage, responseSchema json.RawMessage, continuationState json.RawMessage, ) error
RequireToolInput validates the request and returns an error matching ErrToolInputRequired. A Tool returns this before external side effects, or after storing enough ContinuationState to prove safe re-entry. A HostFailure, cancellation, or deadline in the same error chain takes precedence: the Effect remains unknown instead of committing an input checkpoint.
Prompt is a Tool-defined JSON value for the consumer; responseSchema governs its answer. ContinuationState is returned only to the requesting Tool through ToolInputContinuationFromContext. The request freezes all three values and holds no Process or wait identity. JSON numbers retain their precision; prompt and continuationState must each fit within one MiB before and after normalization.
func ToolChildKey ¶ added in v0.38.0
ToolChildKey names the Tool child Process that serves the ToolCall at toolCallIndex in the response to modelCallSequence. The Engine keeps a ChildKey unique under its parent, so the key, not the child's input, owns the ToolCallRef a Tool child reports.
Types ¶
type ActiveDelegateChild ¶
type ActiveDelegateChild struct {
// contains filtered or unexported fields
}
ActiveDelegateChild is the immutable Interaction-owned attribution of one model ToolCall to its currently active managed child Process. It contains no Engine handle, persistence identity, or Host metadata.
func ActiveDelegateChildren ¶ added in v0.36.0
func ActiveDelegateChildren( snapshot agent.ProcessSnapshot, ) (children []ActiveDelegateChild, found bool, err error)
ActiveDelegateChildren interprets only Interaction-owned state. A valid snapshot without an active Interaction Delegate segment returns found=false. Returned children preserve model ToolCall order.
func (ActiveDelegateChild) ChildKey ¶
func (a ActiveDelegateChild) ChildKey() agent.ChildKey
ChildKey derives the child's key from the ToolCall that requested it.
func (ActiveDelegateChild) ModelCallSequence ¶
func (a ActiveDelegateChild) ModelCallSequence() uint64
ModelCallSequence returns the one-based model call that requested the child.
func (ActiveDelegateChild) ProcessID ¶
func (a ActiveDelegateChild) ProcessID() agent.ProcessID
func (ActiveDelegateChild) Reference ¶ added in v0.40.0
func (a ActiveDelegateChild) Reference() (ToolCallRef, bool)
func (ActiveDelegateChild) ToolCall ¶
func (a ActiveDelegateChild) ToolCall() chat.ToolCall
func (ActiveDelegateChild) ToolCallIndex ¶
func (a ActiveDelegateChild) ToolCallIndex() uint32
ToolCallIndex returns the zero-based ToolCall position in the model response.
func (ActiveDelegateChild) Valid ¶
func (a ActiveDelegateChild) Valid() bool
type Artifact ¶
type Artifact struct {
// contains filtered or unexported fields
}
Artifact is one successful, schema-validated Delegate output, identified by its exact Delegate binding rather than a Go type.
func (Artifact) Decode ¶
Decode strictly decodes the output into T. Schema validation against the exact Delegate Descriptor already happened when the Artifact was admitted.
func (Artifact) DelegateName ¶
func (Artifact) ModelCallSequence ¶ added in v0.32.0
ModelCallSequence identifies the model call within this Interaction Process. Together with ToolCallID it identifies an Artifact across snapshot restoration.
func (Artifact) ToolCallID ¶ added in v0.32.0
type CompletionCandidate ¶
type CompletionCandidate struct {
// contains filtered or unexported fields
}
CompletionCandidate is the immutable model context and semantic output proposed by an Interaction together with all successful Delegate Artifacts available at that boundary.
func (CompletionCandidate) Artifacts ¶
func (c CompletionCandidate) Artifacts() []Artifact
Artifacts returns an independently owned slice of successful Delegate outputs in original model ToolCall order across model calls. Each Artifact is immutable.
func (CompletionCandidate) Output ¶
func (c CompletionCandidate) Output() Output
Output returns an independently owned candidate Output.
func (CompletionCandidate) WorkingContext ¶
func (c CompletionCandidate) WorkingContext() *chat.Request
WorkingContext returns an independently owned copy of the model context preceding this candidate. It is Interaction state, not Host conversation or transcript history, and it does not yet contain the candidate Output.
type CompletionDecision ¶
CompletionDecision is the explicit result of a CompletionValidator. Accepted=true requires empty Feedback. Accepted=false requires concise, non-empty Feedback that will be appended as a user message before the next model call.
func (CompletionDecision) Valid ¶
func (c CompletionDecision) Valid() bool
type CompletionValidator ¶
type CompletionValidator func(ctx context.Context, candidate CompletionCandidate) (CompletionDecision, error)
CompletionValidator decides whether a model or direct-Tool candidate is a valid semantic completion. It must be bounded, deterministic and side-effect-free: no I/O, clock, randomness, shared mutation or goroutines. A rejected candidate must return actionable Feedback; a finite MaxModelCalls remains the hard bound on retry rounds. Evaluation requiring external work belongs in a managed child Process, not this callback. Computation must honor cancellation of the current Step context.
type ConcurrentTool ¶
type ConcurrentTool interface {
// ConcurrencyPolicy returns an immutable classifier, frozen at ToolSet
// construction. It must not retain the Tool or any execution backend,
// including through a bound method or closure. Nil requires exclusive calls.
// The classifier receives an admitted invocation and must be deterministic,
// bounded, side-effect-free, concurrent-safe, and not retain its input.
// Its identity and captured configuration belong in ConfigurationDigest.
ConcurrencyPolicy() func(tool.Invocation) (key string, concurrent bool)
}
ConcurrentTool supplies an independent scheduling policy for calls within one model-requested batch. Tools without a policy, or calls returning concurrent=false, execute alone. A non-empty key names a mutually exclusive resource: calls with the same key in that batch never overlap. Cross-Process resource coordination remains the Tool owner's job.
Each call keeps its own Effect and may wait for external input while siblings continue. The limit counts a waiting child as active until its Tool result is complete. Pure scheduling declarations may be reevaluated during recovery.
type Definition ¶
type Definition struct {
// contains filtered or unexported fields
}
Definition is an immutable managed model/Tool-loop definition. It never calls a model client or an executable Tool: the model Dispatcher owns model I/O, and the ToolSet's child Deployment, which the Definition holds only as its binding, owns Tool execution.
func NewDefinition ¶
func NewDefinition(config DefinitionConfig) (*Definition, error)
func (*Definition) ChildDeployments ¶ added in v0.41.0
func (d *Definition) ChildDeployments() []agent.Deployment
ChildDeployments reports the Tool child binding, when Tools are configured, and every Delegate binding.
func (*Definition) Descriptor ¶
func (d *Definition) Descriptor() agent.Descriptor
func (*Definition) Restore ¶
func (d *Definition) Restore(ctx context.Context, state agent.ExecutionState) (agent.Execution, error)
Restore recreates an Interaction solely from its opaque state. It accepts the current Interaction state schema and rejects unknown fields.
type DefinitionConfig ¶
type DefinitionConfig struct {
Name string
Description string
// MaxModelCalls bounds model Effects in one Interaction. Its zero value is
// unlimited; a finite zero is rejected because an Interaction needs a model call.
MaxModelCalls agent.Quota
// Tools is the frozen ordinary Tool authority. The Interaction owns its
// Deployment as one of its ChildDeployments.
Tools ToolSet
// ToolBudget is allocated from the parent for each ordinary Tool child.
// Its quotas also apply to input continuations; zero quotas are unlimited.
ToolBudget agent.Budget
// ToolCapabilities is the attenuated authority granted to each Tool child.
ToolCapabilities agent.CapabilitySet
// MaxConcurrentToolCalls bounds active calls declared safe to overlap.
// Zero means one; calls without a concurrency declaration execute alone.
MaxConcurrentToolCalls int
// Delegates is the frozen model-visible manifest of exact child
// Deployments. Names must be unique within this slice and must not collide
// with ordinary Tools in ToolSet.
Delegates []Delegate
// CompletionValidator optionally verifies a proposed final semantic output
// against the current WorkingContext and accumulated typed Delegate
// Artifacts. It is a pure Strategy callback whose identity must be covered by
// the Deployment's ConfigurationDigest. Nil accepts every otherwise valid
// completion.
CompletionValidator CompletionValidator
}
DefinitionConfig describes immutable Interaction behavior. Cumulative quotas default to unlimited; the Host retains cancellation and capacity controls.
type Delegate ¶
type Delegate struct {
// contains filtered or unexported fields
}
Delegate is an immutable, model-visible binding to one exact managed child Deployment. It is a composition value owned by Interaction, not an executable Tool or a second Process-start entry point.
func NewDelegate ¶
func NewDelegate(config DelegateConfig) (Delegate, error)
NewDelegate fixes the target at construction; model selection cannot change its Deployment, budget, or capabilities.
type DelegateConfig ¶
type DelegateConfig struct {
// Name is the provider-compatible model Tool name.
Name string
Description string
// Deployment is the exact child behavior binding. An Interaction
// configured with this Delegate owns it as one of its ChildDeployments.
Deployment agent.Deployment
// Budget is permanently allocated from the parent for each invocation.
Budget agent.Budget
Capabilities agent.CapabilitySet
}
DelegateConfig exposes one exact child Deployment as a model-selectable Interaction capability. Name and Description are written for the model; lifecycle identity and resource authority remain frozen Framework values.
type DirectResultTool ¶
type DirectResultTool interface {
// ReturnsDirectResult is read once by NewToolSet; it must not depend on
// mutable state or perform I/O.
ReturnsDirectResult() bool
}
DirectResultTool is an optional Tool capability declaring that a successful model-requested batch containing only such tools returns its ordered results directly instead of making another model call. The declaration is frozen by NewToolSet; a panic or capability-resolution error rejects construction.
type Dispatcher ¶
type Dispatcher struct {
// contains filtered or unexported fields
}
Dispatcher executes model calls emitted by an Interaction Execution. It is immutable after construction and may serve Processes concurrently when the supplied model capability supports concurrent use.
func NewDispatcher ¶
func NewDispatcher(definition *Definition, config DispatcherConfig) (*Dispatcher, error)
func (*Dispatcher) Dispatch ¶
func (d *Dispatcher) Dispatch( ctx context.Context, request agent.EffectRequest, emit agent.DeltaEmitter, ) (agent.Settlement, error)
Dispatch executes one validated Interaction protocol operation and returns a definite owner-defined Signal payload. An error means the external outcome is not provable; Engine therefore records an unknown settlement instead of retrying the operation. A nil ctx is invalid and panics before the request is processed.
func (*Dispatcher) ObservationFailures ¶
func (d *Dispatcher) ObservationFailures() ObservationFailures
ObservationFailures returns a concurrency-safe snapshot of ModelObserver panics isolated by this Dispatcher. The counts do not alter settlements.
func (*Dispatcher) Policy ¶ added in v0.44.0
func (*Dispatcher) Policy(_ agent.Effect) agent.EffectPolicy
Policy forbids model replay and requires no capabilities.
func (*Dispatcher) SettleModelResult ¶ added in v0.32.0
func (d *Dispatcher) SettleModelResult(request agent.EffectRequest, response *chat.Response, messages []chat.Message) (agent.Settlement, error)
SettleModelResult validates an investigated response without calling the model or context reducer. The Host must use the Dispatcher bound to the original Engine-minted request. messages must be the complete context actually sent to the model, including any reduction; it is required even when unchanged.
type DispatcherConfig ¶
type DispatcherConfig struct {
// Exactly one of Model and Streamer is required. The selected capability
// owns the entire response lifecycle; streaming is accumulated before settlement.
Model chat.Model
Streamer chat.Streamer
// MaxResponseBytes bounds the canonical successful result envelope and,
// independently, the canonical empty result envelope plus cumulative stream
// deltas. Both include replacement context. Zero uses agent.MaxPayloadBytes;
// positive values may lower that limit. No partial response is promoted.
// Pre-call host failures use a separate diagnostic budget: their message is
// bounded by agent.MaxDiagnosticBytes before canonical encoding, and their
// complete envelope remains bounded by agent.MaxPayloadBytes.
MaxResponseBytes int
// Observer receives exact model response facts. Nil disables observation.
Observer ModelObserver
// ModelContextReducer optionally replaces the message context immediately
// before each model call. Nil sends WorkingContext unchanged.
ModelContextReducer ModelContextReducer
}
type Input ¶
type Input struct {
Messages []chat.Message `json:"messages"`
Options chat.Options `json:"options,omitzero"`
}
Input excludes executable Tools: the Deployment fixes their ToolSet authority.
type ModelContextReducer ¶
type ModelContextReducer interface {
// ReduceModelContext returns the complete, non-empty messages for the
// attributed invocation; a result that fails request validation settles
// as a Host failure. The Dispatcher clones the result, so implementations
// may return a sequence they still reference.
ReduceModelContext(
ctx context.Context,
invocation ModelInvocation,
request *chat.Request,
) ([]chat.Message, error)
}
ModelContextReducer owns an optional, provider-neutral reduction immediately before one actual model call. The request is an independently owned snapshot containing the exact Tool manifest and options that the model would receive; implementations return only the complete replacement message sequence, so they cannot change model options or Tool authority. When the messages change, the settlement carries them and WorkingContext adopts them, so later calls and checkpoints never regrow the reduced context.
ReduceModelContext must return a definite outcome. A non-nil error means the main model was not called and is settled as a Host failure. Implementations that perform I/O must therefore resolve their own ambiguity before returning.
type ModelInvocation ¶
type ModelInvocation struct {
// contains filtered or unexported fields
}
ModelInvocation is the immutable execution attribution of one actual model call. It contains no Engine handle or Host metadata.
func ModelInvocationFromContext ¶
func ModelInvocationFromContext(ctx context.Context) (ModelInvocation, bool)
ModelInvocationFromContext returns the attribution installed only for the duration of an Interaction model call. A nil context has no attribution.
func (ModelInvocation) AppliedSteerSignalIDs ¶
func (m ModelInvocation) AppliedSteerSignalIDs() []agent.SignalID
AppliedSteerSignalIDs returns the ordered identities of steer Signals whose messages were first made visible to this exact model request. The returned slice is independently owned. An empty slice means the request applied no new steer input; previously applied messages may still remain in WorkingContext.
func (ModelInvocation) AttemptID ¶ added in v0.38.0
func (m ModelInvocation) AttemptID() (agent.EffectAttemptID, bool)
AttemptID identifies this physical invocation. Logical requests retained in snapshots have no attempt identity until the Engine dispatches them again.
func (ModelInvocation) DeploymentRef ¶
func (m ModelInvocation) DeploymentRef() agent.DeploymentRef
func (ModelInvocation) EffectID ¶
func (m ModelInvocation) EffectID() agent.EffectID
func (ModelInvocation) ModelCallSequence ¶
func (m ModelInvocation) ModelCallSequence() uint64
ModelCallSequence returns the one-based model call position in this Interaction.
func (ModelInvocation) Relation ¶
func (m ModelInvocation) Relation() agent.ProcessRelation
func (ModelInvocation) StepSequence ¶
func (m ModelInvocation) StepSequence() uint64
StepSequence returns the one-based Process Step that declared the model Effect.
func (ModelInvocation) TreeIncarnationID ¶ added in v0.21.0
func (m ModelInvocation) TreeIncarnationID() (agent.TreeIncarnationID, bool)
TreeIncarnationID identifies the durable writer activation, when present.
func (ModelInvocation) Valid ¶
func (m ModelInvocation) Valid() bool
type ModelObserver ¶
type ModelObserver interface {
// OnModelStarted receives the effective request after context reduction and
// local admission, immediately before calling the model. It is detached.
OnModelStarted(ctx context.Context, invocation ModelInvocation, request *chat.Request)
// OnModelSettled receives exactly one host-boundary outcome for a started
// call, including cancellation, invalid responses and panics. A valid
// response is observed before settlement encoding and capacity admission;
// a later admission failure does not retract this response fact.
OnModelSettled(ctx context.Context, invocation ModelInvocation, settlement ModelSettlement)
}
ModelObserver receives provider-neutral model attempts. Callbacks are observational, must return in bounded time, and have their panics isolated.
type ModelResponseDelta ¶
type ModelResponseDelta struct {
// contains filtered or unexported fields
}
ModelResponseDelta is one validated provider-neutral streaming increment. It is observational and never a source for final Output or restoration.
func ParseModelResponseDelta ¶
func ParseModelResponseDelta(payload json.RawMessage) (ModelResponseDelta, error)
func (ModelResponseDelta) ResponseDelta ¶
func (m ModelResponseDelta) ResponseDelta() *chat.ResponseDelta
ResponseDelta returns an independently owned transport increment.
type ModelSettlement ¶ added in v0.38.0
ModelSettlement describes a physical model call, not durable Effect settlement. Response is a detached validated response; without one, no complete response was established and Failure is a bounded diagnostic, never proof that the provider did no work or consumed no tokens.
func (ModelSettlement) Unknown ¶ added in v0.38.0
func (m ModelSettlement) Unknown() bool
Unknown reports a call that established no complete response.
type ObservationFailures ¶ added in v0.26.0
type ObservationFailures struct {
// contains filtered or unexported fields
}
ObservationFailures snapshots panics isolated by one Dispatcher or ToolSet. Counts saturate at math.MaxUint64. Only the latest panic per callback is kept; editing a returned diagnostic cannot change the retained evidence.
func (ObservationFailures) LastModelSettledPanic ¶ added in v0.38.0
func (o ObservationFailures) LastModelSettledPanic() (ObserverPanic, bool)
func (ObservationFailures) LastModelStartedPanic ¶ added in v0.38.0
func (o ObservationFailures) LastModelStartedPanic() (ObserverPanic, bool)
func (ObservationFailures) LastToolSettledPanic ¶ added in v0.26.0
func (o ObservationFailures) LastToolSettledPanic() (ObserverPanic, bool)
func (ObservationFailures) LastToolStartedPanic ¶ added in v0.26.0
func (o ObservationFailures) LastToolStartedPanic() (ObserverPanic, bool)
func (ObservationFailures) ModelSettledPanics ¶ added in v0.38.0
func (o ObservationFailures) ModelSettledPanics() uint64
func (ObservationFailures) ModelStartedPanics ¶ added in v0.38.0
func (o ObservationFailures) ModelStartedPanics() uint64
func (ObservationFailures) ToolSettledPanics ¶ added in v0.26.0
func (o ObservationFailures) ToolSettledPanics() uint64
func (ObservationFailures) ToolStartedPanics ¶ added in v0.26.0
func (o ObservationFailures) ToolStartedPanics() uint64
type ObserverPanic ¶ added in v0.26.0
type ObserverPanic struct {
ObserverType string
ProcessID agent.ProcessID
EffectID agent.EffectID
AttemptID agent.EffectAttemptID
Message string
Stack string
}
ObserverPanic is a detached diagnostic for one isolated callback failure. Message retains at most 4 KiB of the formatted panic value and Stack retains at most 64 KiB of the failing goroutine's stack. ProcessID and EffectID bind the failure to the exact invocation without retaining its request or response.
type Output ¶
type Output struct {
ModelResponse *chat.Response `json:"model_response,omitzero"`
// DirectToolResults preserves model ToolCall order.
DirectToolResults []chat.ToolResult `json:"direct_tool_results,omitempty"`
// ModelCalls is the number of model Effects issued by this Interaction.
ModelCalls uint64 `json:"model_calls"`
}
Output is the final semantic Interaction result. Exactly one completion is present: ModelResponse when the model produced a final response without requesting another tool round, or DirectToolResults when every call in one model-requested batch targeted a DirectResultTool and returned successfully. ModelResponse is accumulated independently of best-effort stream Delta delivery, so it remains complete after observer loss or snapshot restoration.
type PendingToolInput ¶
type PendingToolInput struct {
// contains filtered or unexported fields
}
PendingToolInput is the consumer-facing view of one current Tool input wait. It excludes the Tool's continuation state.
func PendingToolInputs ¶
func PendingToolInputs(snapshot agent.TreeSnapshot) ([]PendingToolInput, error)
PendingToolInputs reads every current Tool input wait in a captured tree, including while Paused. An answer clears the wait; only Resume releases a pause. The returned order follows the snapshot's Process order. The caller selects a wait explicitly and sends its ResponseSignal to that wait's ProcessID.
func (PendingToolInput) ProcessID ¶
func (p PendingToolInput) ProcessID() agent.ProcessID
ProcessID returns the Tool child that must receive the response.
func (PendingToolInput) Prompt ¶
func (p PendingToolInput) Prompt() json.RawMessage
Prompt returns an independently owned Tool-defined JSON prompt.
func (PendingToolInput) ResponseSchema ¶
func (p PendingToolInput) ResponseSchema() json.RawMessage
func (PendingToolInput) ResponseSignal ¶
func (p PendingToolInput) ResponseSignal( id agent.SignalID, response json.RawMessage, ) (agent.SignalRequest, error)
ResponseSignal validates response locally against ResponseSchema and returns one WaitID-addressed SignalRequest with caller-supplied deduplication ID.
func (PendingToolInput) Valid ¶
func (p PendingToolInput) Valid() bool
func (PendingToolInput) WaitID ¶
func (p PendingToolInput) WaitID() agent.WaitID
type ResultDisposition ¶ added in v0.23.0
type ResultDisposition string
ResultDisposition describes a definite outcome. Unknown execution outcomes and input checkpoints never enter RoundResults. Rejection does not assert that a Tool's business operation ran.
const ( ResultInvalid ResultDisposition = "" ResultSucceeded ResultDisposition = "succeeded" ResultFailed ResultDisposition = "failed" ResultRejected ResultDisposition = "rejected" )
func (ResultDisposition) String ¶ added in v0.26.0
func (r ResultDisposition) String() string
func (ResultDisposition) Valid ¶ added in v0.26.0
func (r ResultDisposition) Valid() bool
type ResultEntry ¶ added in v0.23.0
type ResultEntry struct {
ToolCallIndex uint32 `json:"tool_call_index"`
Call chat.ToolCall `json:"call"`
Result chat.ToolResult `json:"result"`
Disposition ResultDisposition `json:"disposition"`
}
ResultEntry keeps exact provider attribution and output together. Entries returned by RoundResults are independent copies and cannot alter the snapshot.
type RoundResults ¶ added in v0.28.0
type RoundResults struct {
// contains filtered or unexported fields
}
RoundResults is an immutable, possibly sparse view of definite results for one Interaction round. Entries retain original call indexes. Complete reports knowledge, never permission to continue a canceled Process; only the Interaction state machine admits a complete round through a Checkpoint before continuation.
func SettledResults ¶ added in v0.28.0
func SettledResults(snapshot agent.TreeSnapshot) ([]RoundResults, error)
SettledResults interprets Scope-owned facts in one complete tree cut, ordered child-before-parent and then by original call index. Unknown operations, waiting checkpoints and calls that never started produce no synthetic result. Definite tool settlements remain visible even when cancellation prevented the Tool or parent Step from consuming them. Delegate projection requires a fully terminal subtree without unresolved Effects.
This is a read-only projection of current recovery facts, not a transcript: later cuts may retire an admitted round, and overlapping cuts repeat facts that RoundResults.Reference identifies. A Host that keeps result history derives it inside its TreeCommitter transactions. Reading or storing this projection never authorizes tool reexecution.
func (RoundResults) CallCount ¶ added in v0.28.0
func (r RoundResults) CallCount() uint32
func (RoundResults) Complete ¶ added in v0.28.0
func (r RoundResults) Complete() bool
func (RoundResults) Digest ¶ added in v0.28.0
func (r RoundResults) Digest() agent.Digest
Digest binds the exact JSON content and attribution, independently of EffectIDs and tree incarnation. It is a content hash, not a storage acknowledgment.
func (RoundResults) Entries ¶ added in v0.28.0
func (r RoundResults) Entries() []ResultEntry
func (RoundResults) JSON ¶ added in v0.28.0
func (r RoundResults) JSON() json.RawMessage
func (RoundResults) ModelCallSequence ¶ added in v0.28.0
func (r RoundResults) ModelCallSequence() uint64
func (RoundResults) Reference ¶ added in v0.40.0
func (r RoundResults) Reference(toolCallIndex uint32) (ToolCallRef, bool)
Reference uses the original model response index, not an entry's position in this possibly sparse projection. A missing result does not invalidate a call's reference; false means that index is outside the admitted round.
func (RoundResults) Relation ¶ added in v0.28.0
func (r RoundResults) Relation() agent.ProcessRelation
type ToolCallRef ¶ added in v0.40.0
type ToolCallRef struct {
// contains filtered or unexported fields
}
ToolCallRef identifies one logical call by its requesting Interaction Process, one-based model call sequence and zero-based position in that response. It is immutable and comparable. Provider call IDs, execution attempts and managed child identities do not participate in equality. A reference identifies a call; it does not prove execution, settlement or permission to replay it.
Example ¶
package main
import (
"fmt"
"github.com/Tangerg/scope/agent/strategy/interaction"
)
func main() {
// A Host persists the value returned by an invocation or result round's
// Reference method, independently of its product record identity.
retained, err := interaction.ParseToolCallRef("process:analysis/2/0")
if err != nil {
panic(err)
}
items := map[interaction.ToolCallRef]string{retained: "item-7"}
encoded, err := retained.MarshalText()
if err != nil {
panic(err)
}
var restored interaction.ToolCallRef
if err := restored.UnmarshalText(encoded); err != nil {
panic(err)
}
fmt.Println(restored == retained, items[restored])
fmt.Println(restored.ProcessID(), restored.ModelCallSequence(), restored.ToolCallIndex())
}
Output: true item-7 process:analysis 2 0
func ParseToolCallRef ¶ added in v0.40.0
func ParseToolCallRef(value string) (ToolCallRef, error)
ParseToolCallRef accepts only the canonical text encoding. Parsing restores a reference, never an execution authority or a managed child identity.
func (ToolCallRef) JSONSchemaAlias ¶ added in v0.40.0
func (ToolCallRef) JSONSchemaAlias() any
func (ToolCallRef) MarshalText ¶ added in v0.40.0
func (t ToolCallRef) MarshalText() ([]byte, error)
func (ToolCallRef) ModelCallSequence ¶ added in v0.40.0
func (t ToolCallRef) ModelCallSequence() uint64
func (ToolCallRef) ProcessID ¶ added in v0.40.0
func (t ToolCallRef) ProcessID() agent.ProcessID
func (ToolCallRef) String ¶ added in v0.40.0
func (t ToolCallRef) String() string
String is the canonical, lossless text encoding used by MarshalText. The zero value has an empty encoding and cannot be marshaled.
func (ToolCallRef) ToolCallIndex ¶ added in v0.40.0
func (t ToolCallRef) ToolCallIndex() uint32
func (*ToolCallRef) UnmarshalText ¶ added in v0.40.0
func (t *ToolCallRef) UnmarshalText(text []byte) error
func (ToolCallRef) Valid ¶ added in v0.40.0
func (t ToolCallRef) Valid() bool
type ToolInputContinuation ¶
type ToolInputContinuation struct {
// contains filtered or unexported fields
}
ToolInputContinuation is the immutable state and validated external response attached only while re-entering the Tool that requested input.
func ToolInputContinuationFromContext ¶
func ToolInputContinuationFromContext(ctx context.Context) (ToolInputContinuation, bool)
ToolInputContinuationFromContext returns continuation data only for the active resumed Tool call. Ordinary first attempts and a nil context return false.
func (ToolInputContinuation) Response ¶
func (t ToolInputContinuation) Response() json.RawMessage
func (ToolInputContinuation) State ¶
func (t ToolInputContinuation) State() json.RawMessage
type ToolInvocation ¶
type ToolInvocation struct {
// contains filtered or unexported fields
}
ToolInvocation is the immutable execution attribution of one actual Tool call. ToolCall is the exact model request being executed.
func ToolInvocationFromContext ¶
func ToolInvocationFromContext(ctx context.Context) (ToolInvocation, bool)
ToolInvocationFromContext returns the attribution installed only for the duration of the exact Interaction Tool call. A nil context has no attribution.
func ToolInvocationFromRequest ¶ added in v0.40.0
func ToolInvocationFromRequest(request agent.EffectRequest) (ToolInvocation, error)
ToolInvocationFromRequest decodes the exact attribution retained by a Tool EffectRequest, including requests recovered from TreeSnapshot.EffectRequest. Retained requests have no physical AttemptID until dispatched again. This operation performs no Tool call and does not resolve an unknown Effect.
func (ToolInvocation) AttemptID ¶ added in v0.38.0
func (t ToolInvocation) AttemptID() (agent.EffectAttemptID, bool)
AttemptID identifies this physical invocation, when dispatched by the Engine.
func (ToolInvocation) DeploymentRef ¶
func (t ToolInvocation) DeploymentRef() agent.DeploymentRef
func (ToolInvocation) EffectID ¶
func (t ToolInvocation) EffectID() agent.EffectID
func (ToolInvocation) Reference ¶ added in v0.40.0
func (t ToolInvocation) Reference() (ToolCallRef, bool)
Reference correlates this attempt with its requesting Interaction's results. It comes from the ChildKey an Interaction gives the Tool child, which the Engine keeps unique under the parent. A ToolSet run as a root, or started under any other ChildKey, has no reference; its physical invocation attribution remains available through this value.
func (ToolInvocation) Relation ¶
func (t ToolInvocation) Relation() agent.ProcessRelation
func (ToolInvocation) StepSequence ¶
func (t ToolInvocation) StepSequence() uint64
StepSequence returns the one-based Tool child Step that declared this attempt.
func (ToolInvocation) ToolCall ¶
func (t ToolInvocation) ToolCall() chat.ToolCall
func (ToolInvocation) TreeIncarnationID ¶ added in v0.21.0
func (t ToolInvocation) TreeIncarnationID() (agent.TreeIncarnationID, bool)
TreeIncarnationID identifies the durable writer activation, when present.
func (ToolInvocation) Valid ¶
func (t ToolInvocation) Valid() bool
type ToolObserver ¶
type ToolObserver interface {
// OnToolStarted marks the actual external Tool-call boundary; it is not
// emitted for calls rejected before execution. Concurrently authorized Tool
// calls may invoke this method in parallel.
OnToolStarted(ctx context.Context, invocation ToolInvocation)
// OnToolSettled receives exactly one conclusive or unknown host-boundary
// outcome for a started Tool call. The ToolResult, when present, is detached;
// the callback cannot alter the candidate value used for settlement.
OnToolSettled(ctx context.Context, invocation ToolInvocation, settlement ToolSettlement)
}
ToolObserver receives exact Tool-call facts. Callbacks are observational, must return in bounded time, and have their panics isolated. Tool children may invoke them concurrently when their calls may overlap. Callbacks do not acknowledge durable Effect settlement.
type ToolSet ¶
type ToolSet struct {
// contains filtered or unexported fields
}
ToolSet binds an immutable Tool manifest to one Deployment that executes a single call per child Process. Definition owns scheduling; the child owns its Effect settlement and any input continuation. No model client enters this binding. A zero ToolSet represents the absence of ordinary Tools.
func NewToolSet ¶
func NewToolSet(config ToolSetConfig) (ToolSet, error)
func (ToolSet) Configured ¶ added in v0.26.0
Configured distinguishes a constructed ToolSet from the optional absence of Tools.
func (ToolSet) Deployment ¶
func (t ToolSet) Deployment() agent.Deployment
Deployment returns the exact child binding each Tool call runs under. An Interaction configured with this ToolSet owns it as one of its ChildDeployments.
func (ToolSet) ObservationFailures ¶
func (t ToolSet) ObservationFailures() ObservationFailures
ObservationFailures returns isolated Tool observer panic counts and diagnostics.
func (ToolSet) SettleToolResult ¶ added in v0.31.0
func (t ToolSet) SettleToolResult(request agent.EffectRequest, output chat.ToolOutput, disposition ResultDisposition, advertisedToolNames []string) (agent.Settlement, error)
SettleToolResult converts an investigated external outcome into the same completion protocol used by live dispatch, without calling or replaying the Tool. request must be the original Engine-minted request for this exact Deployment; its call identifies the result, and disposition alone decides whether the output reports an error. Direct-return policy comes only from the binding; rejected and failed results cannot advertise Tools.
type ToolSetConfig ¶
type ToolSetConfig struct {
Name string
Description string
Tools []tool.Tool
DeferredTools []tool.Tool
// Observer receives exact Tool call facts. Nil disables observation.
Observer ToolObserver
ImplementationDigest agent.Digest
ConfigurationDigest agent.Digest
}
ToolSetConfig freezes ordinary Tool authority and its exact execution binding. The digests cover the executable Tools, optional capabilities, and observer.
type ToolSettlement ¶
type ToolSettlement struct {
Result *chat.ToolResult
InputRequired bool
Failure string
// Evidence is non-final output from an unknown call. It is never promoted
// to Result and cannot establish whether the external operation succeeded.
Evidence *chat.ToolOutput
}
ToolSettlement is the observed outcome of one Tool call attempt. Result is the value produced for the model; it enters the Tool child state only after that Effect settles. InputRequired instead means the Tool returned a continuation request; the Engine has not yet committed its wait. With neither, the call's external outcome remains unestablished, including host failures, cancellation, deadlines, and panics, and Failure diagnoses it. Observation never settles the Effect.
func (ToolSettlement) Unknown ¶
func (t ToolSettlement) Unknown() bool
Unknown reports a call whose external outcome remains unestablished.
Source Files
¶
- active_delegate.go
- advertisement.go
- artifact.go
- capability.go
- child_batch.go
- child_key.go
- child_signals.go
- clone.go
- context_reducer.go
- definition.go
- delegate.go
- dispatcher.go
- doc.go
- errors.go
- execution.go
- host_failure.go
- input.go
- invocation.go
- model_tool_result.go
- observer.go
- output.go
- pending_input.go
- protocol.go
- round_results.go
- state.go
- steer.go
- stream.go
- tool_call_ref.go
- tool_dispatcher.go
- tool_execution.go
- tool_input.go
- tool_round.go
- tool_set.go