interaction

package
v0.41.0 Latest Latest
Warning

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

Go to latest
Published: Oct 1, 2026 License: Apache-2.0 Imports: 25 Imported by: 0

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. 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 panics leave the Tool Effect unknown until the Host settles it; terminating the Process retains those identities without establishing that external work failed. 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.

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

Examples

Constants

This section is empty.

Variables

View Source
var (
	ErrInvalidResult                = errors.New("interaction: invalid result")
	ErrInvalidToolInputRequest      = errors.New("interaction: invalid tool input request")
	ErrToolInputRequired            = errors.New("interaction: tool input required")
	ErrToolAdvertisementUnavailable = errors.New("interaction: tool advertisement unavailable")
	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")
)

Invalid-value sentinels reject construction, domain values, and Dispatcher operations rather than Steps, so they carry no Failure classification.

View Source
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.

View Source
var ErrHostFailure = errors.New("interaction: host failure")

ErrHostFailure separates host infrastructure failure from model or tool behavior.

View Source
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

func AdvertiseTools(ctx context.Context, names ...string) error

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

func DelegateChildKey(modelCallSequence uint64, toolCall chat.ToolCall) (agent.ChildKey, error)

DelegateChildKey correlates a Delegate ToolCall with its managed child Process.

func HostFailure

func HostFailure(cause error) error

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

func NewSteerSignal(id agent.SignalID, messages ...chat.Message) (agent.SignalRequest, error)

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

func ToolChildKey(modelCallSequence uint64, call chat.ToolCall) (agent.ChildKey, error)

ToolChildKey correlates an ordinary ToolCall with its managed child Process.

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

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

func (a Artifact) Decode[T any]() (T, error)

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 (a Artifact) DelegateName() string

func (Artifact) ModelCallSequence added in v0.32.0

func (a Artifact) ModelCallSequence() uint64

ModelCallSequence identifies the model call within this Interaction Process. Together with ToolCallID it identifies an Artifact across snapshot restoration.

func (Artifact) Output

func (a Artifact) Output() agent.Payload

func (Artifact) ToolCallID added in v0.32.0

func (a Artifact) ToolCallID() string

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

type CompletionDecision struct {
	Accepted bool
	Feedback string
}

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 CompletionSource

type CompletionSource string
const (
	CompletionSourceInvalid CompletionSource = ""
	// CompletionSourceModelResponse means the model produced a final response
	// without requesting another tool round.
	CompletionSourceModelResponse CompletionSource = "model_response"

	// CompletionSourceDirectToolResults means every call in one model-requested
	// batch targeted a DirectResultTool and returned successfully.
	CompletionSourceDirectToolResults CompletionSource = "direct_tool_results"
)

func (CompletionSource) String added in v0.26.0

func (c CompletionSource) String() string

func (CompletionSource) Valid

func (c CompletionSource) 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.

func (*Definition) Start

func (d *Definition) Start(input agent.Payload) (agent.Execution, error)

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.

func (Delegate) Valid

func (d Delegate) Valid() bool

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) ReplayPolicy

func (*Dispatcher) ReplayPolicy(_ agent.Effect) agent.ReplayPolicy

ReplayPolicy forbids model replay.

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.

func (Input) Validate

func (i Input) Validate() error

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

type ModelSettlement struct {
	Response *chat.Response
	Failure  string
	Unknown  bool
}

ModelSettlement describes a physical model call, not durable Effect settlement. Response is a detached validated response. Unknown means no complete response was established; Failure is a bounded diagnostic, never proof that the provider did no work or consumed no tokens.

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 {
	Source CompletionSource `json:"source"`

	// ModelResponse is the authoritative accumulated response when Source is
	// CompletionSourceModelResponse.
	ModelResponse *chat.Response `json:"model_response,omitzero"`

	// DirectToolResults preserves model ToolCall order when Source is
	// CompletionSourceDirectToolResults.
	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. ModelResponse is accumulated independently of best-effort stream Delta delivery, so it remains complete after observer loss or snapshot restoration.

func (Output) Validate

func (o Output) Validate() error

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

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) ModelCallSequence

func (t ToolInvocation) ModelCallSequence() uint64

ModelCallSequence returns the one-based model call that requested the Tool.

func (ToolInvocation) Reference added in v0.40.0

func (t ToolInvocation) Reference() (ToolCallRef, bool)

Reference correlates this attempt with its requesting Interaction's results. A ToolSet invoked as a root has no requesting Interaction and returns false; 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) ToolCallIndex

func (t ToolInvocation) ToolCallIndex() uint32

ToolCallIndex returns the zero-based ToolCall position in the model response.

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

func (t ToolSet) Configured() bool

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, result chat.ToolResult, 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 and result must match its call. Direct-return policy comes only from the binding. disposition must agree with result.IsError; 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
	Unknown       bool
	// 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. Failure diagnoses an attempt that produced no ordinary ToolResult. Unknown means its external outcome remains unestablished, including host failures, cancellation, deadlines, and panics. Observation never settles the Effect.

Jump to

Keyboard shortcuts

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