Documentation
¶
Overview ¶
Package delegation defines backend-neutral contracts for assigning work to another agent or execution target.
Mode distinguishes synchronous and asynchronous work. Directory owns discovery; Service owns execution and status lookup. The local service (LocalService), the deploy-bound directory (LocalDirectory), and the delegation resource factories live in this package; the model-facing delegate / delegation_status tools live in the tool subpackage, and the runtime host-factory integration (exposing a Service on every turn host) lives in the hostwrap subpackage.
A host can expose a Service to execution-time tools with WithService, and consumers recover it with ServiceFromHost.
Index ¶
- Constants
- Variables
- func NewDirectoryFactory() res.Factory[*LocalDirectory]
- func NewRandomSessionProviderFactory() res.Factory[RandomSessionProvider]
- func NewServiceFactory(opts ...Option) res.Factory[*LocalService]
- func RegisterDirectory(r *res.Registry) error
- func RegisterSessionProvider(r *res.Registry) error
- func RequestNotFound(id string) error
- func RunAttributesFromContext(ctx context.Context) (map[string]string, bool)
- func TargetNotFound(id string) error
- func UnsupportedMode(mode Mode) error
- func WithRunAttributes(ctx context.Context, attributes map[string]string) context.Context
- func WithService(h agent.Host, service Service) agent.Host
- type AsyncBackend
- type AsyncRequest
- type Deployment
- type Directory
- type IdempotencyRetentionProvider
- type LocalDirectory
- func (d *LocalDirectory) Bind(result Deployment) error
- func (d *LocalDirectory) BindDeployment(view deploy.View) error
- func (d *LocalDirectory) BindTargetSource(source TargetSource) error
- func (d *LocalDirectory) FreezeTargets(instances map[string]*agent.Agent)
- func (d *LocalDirectory) Get(_ context.Context, id string) (Target, error)
- func (d *LocalDirectory) List(context.Context) ([]Target, error)
- func (d *LocalDirectory) Lookup(_ context.Context, id string) (*agent.Agent, error)
- func (d *LocalDirectory) UnfreezeTargets()
- type LocalService
- func (s *LocalService) BindSessionManager(manager *session.Manager) error
- func (s *LocalService) Close() error
- func (s *LocalService) Delegate(ctx context.Context, req Request) (Response, error)
- func (s *LocalService) Get(ctx context.Context, id string) (Response, error)
- func (s *LocalService) Run(ctx context.Context, req AsyncRequest) (Response, error)
- func (s *LocalService) Start() error
- type Mode
- type Option
- func WithDeferredWorkers() Option
- func WithIdempotencyRetention(retention time.Duration) Option
- func WithMaxConcurrency(limit int) Option
- func WithMaxDepth(limit int) Option
- func WithSessionInitializer(initializer SessionInitializer) Option
- func WithSessionProvider(provider SessionProvider) Option
- func WithStreamEscrowTTL(ttl time.Duration) Option
- func WithStreamTargetExporter(exporter StreamTargetExporter) Option
- func WithStreamTargetResolver(resolver StreamTargetResolver) Option
- func WithTimeout(timeout time.Duration) Option
- func WithWorkerHost(host agent.Host) Option
- type RandomSessionProvider
- type Request
- type Response
- type RunIDNotifier
- type Runner
- type Service
- type ServiceProvider
- type ServiceSettings
- type SessionInitializer
- type SessionProvider
- type Status
- type StreamPolicySnapshot
- type StreamRef
- type StreamTarget
- type StreamTargetExporter
- type StreamTargetProvider
- type StreamTargetResolver
- type Target
- type TargetSource
- type TargetViewBinder
- type TargetViewFreezer
- type Work
- type WorkSource
Constants ¶
const ( // ServiceKind is the deployment resource kind of the local // delegation service. ServiceKind = "delegation.Service" // DirectoryKind is the deployment resource kind of the local // delegation directory. DirectoryKind = "delegation.Directory" // SessionProviderKind is the deployment resource kind of a delegation // session identity policy. SessionProviderKind = "delegation.SessionProvider" // BackendDep is the optional async backend dependency. BackendDep = "backend" // DirectoryDep is the required directory dependency shared by the // service and the delegation tool source. DirectoryDep = "directory" // SessionProviderDep is the optional session identity policy // dependency. SessionProviderDep = "session_provider" )
const ( // ParentRunMetadataKey carries the parent (caller) run id. ParentRunMetadataKey = "delegation.parent_run" // CallIDMetadataKey carries the delegate tool call id that // started the delegation. CallIDMetadataKey = "delegation.call_id" )
Metadata keys injected service-side into an async delegation's Request.Metadata so operational views (kanban cards, delegation status) surface run lineage without any per-view plumbing. They are set by the service, not accepted from user-supplied delegate arguments; callers must not treat them as authoritative input.
const ( // StreamTargetKindConversation routes envelopes to a live, // conversation-scoped sink. Reachability is same-process: the // resolving registry must hold the registered sink, so this kind // recovers streams when the in-process escrow was lost (TTL, // release) but does not deliver across processes. StreamTargetKindConversation = "conversation" // StreamTargetKindBus routes envelopes onto a named event bus. // This is the kind capable of true cross-process delivery, as // long as the bus implementation itself spans the processes. StreamTargetKindBus = "bus" )
Stream target kinds. The vocabulary is part of the delegation contract so the submit side (exporter) and the worker side (resolver) agree without importing the runtime.
Variables ¶
var ( // ErrTargetNotFound identifies an unknown target. ErrTargetNotFound = errors.New("delegation: target not found") // ErrRequestNotFound identifies an unknown delegation request. ErrRequestNotFound = errors.New("delegation: request not found") // ErrUnsupportedMode identifies a valid mode unsupported by a backend. ErrUnsupportedMode = errors.New("delegation: mode not supported") )
Functions ¶
func NewDirectoryFactory ¶ added in v0.1.23
func NewDirectoryFactory() res.Factory[*LocalDirectory]
NewDirectoryFactory returns a deployment factory for the local delegation directory resource. Each deployment generation builds and binds its own directory, so reloads always delegate against the current generation's agents.
func NewRandomSessionProviderFactory ¶ added in v0.1.23
func NewRandomSessionProviderFactory() res.Factory[RandomSessionProvider]
NewRandomSessionProviderFactory returns a deployment factory for the default delegation session provider: every delegation mints a fresh ContextID and never persists.
func NewServiceFactory ¶
func NewServiceFactory(opts ...Option) res.Factory[*LocalService]
NewServiceFactory returns a deployment factory for the local delegation service. The service resolves its directory and optional session provider from deploy dependencies, so every deployment generation gets its own bound directory. Options inject app-owned behavior the document cannot express (e.g. delegation.WithWorkerHost); the declarative settings are applied after them.
func RegisterDirectory ¶ added in v0.1.23
RegisterDirectory adds the local directory resource factory to r.
func RegisterSessionProvider ¶ added in v0.1.23
RegisterSessionProvider adds the random session provider factory to r.
func RequestNotFound ¶
RequestNotFound returns a not-found-classified request lookup error.
func RunAttributesFromContext ¶ added in v0.8.1
RunAttributesFromContext returns a copy of the attributes stamped by WithRunAttributes. ok is false when nothing was stamped.
func TargetNotFound ¶
TargetNotFound returns a not-found-classified target lookup error.
func UnsupportedMode ¶
UnsupportedMode returns a not-available-classified backend capability error.
func WithRunAttributes ¶ added in v0.8.1
WithRunAttributes returns a context carrying attributes that the delegation tool copies onto every Request it builds. Tool middleware is the intended producer: it is the last seam that still sees the caller's context before the service is called, so a deployment can stamp its execution policy (plus any other run-scoped metadata) without forking the delegate tool.
The map is copied, so later mutation by the caller does not affect the context. A nil or empty map clears any value stamped further out.
Types ¶
type AsyncBackend ¶
type AsyncBackend interface {
Submit(ctx context.Context, req AsyncRequest) (id string, err error)
Status(ctx context.Context, id string) (Response, error)
}
AsyncBackend stores asynchronous delegations and reports their status. Submit must safely replay the same non-empty Request.IdempotencyKey and identical AsyncRequest during the backend's declared retention window, returning the same id; reuse with different request semantics must return a conflict-classified error. The service borrows an injected backend and never closes it.
type AsyncRequest ¶
type AsyncRequest struct {
Request Request `json:"request"`
Caller string `json:"caller,omitempty"`
Depth int `json:"depth"`
// ParentRunID is the run id of the delegating agent's run. Sync
// delegations derive it from the ambient execution context;
// async delegations persist it here so it survives the queue.
ParentRunID string `json:"parent_run_id,omitempty"`
// CallID is the delegate tool call id that started the
// delegation. Like ParentRunID it is derived from the caller's
// execution context and persisted across the queue for async.
CallID string `json:"call_id,omitempty"`
// Stream is the queue-crossing reference to the caller's stream
// sinks. Nil means the delegation carries no live stream (the
// caller had no inheritable sinks, or the deployment does not
// support async streaming).
Stream *StreamRef `json:"stream,omitempty"`
}
AsyncRequest is the backend-neutral unit persisted by an AsyncBackend. Caller and Depth preserve delegation metadata across queue boundaries.
type Deployment ¶
Deployment is the minimal read-only deployment view needed by LocalDirectory. *deploy.Result implements this interface.
type Directory ¶
type Directory interface {
List(ctx context.Context) ([]Target, error)
Get(ctx context.Context, id string) (Target, error)
}
Directory discovers delegation targets independently of execution.
type IdempotencyRetentionProvider ¶
IdempotencyRetentionProvider optionally exposes an AsyncBackend's finite terminal replay and status-query window.
type LocalDirectory ¶
type LocalDirectory struct {
// contains filtered or unexported fields
}
Directory exposes the agents assembled by deploy.Build as local delegation targets. It may be constructed before Build and bound exactly once after it.
func (*LocalDirectory) Bind ¶
func (d *LocalDirectory) Bind(result Deployment) error
Bind installs Build's instances. The deployment snapshot is immutable after a successful bind and borrows the instances; the result retains lifecycle ownership. The directory as a whole is not frozen: the live dynamic view may be attached once (BindTargetSource) and pinned on generation retirement (FreezeTargets).
func (*LocalDirectory) BindDeployment ¶ added in v0.1.23
func (d *LocalDirectory) BindDeployment(view deploy.View) error
BindDeployment implements deploy.Binder: the directory resource binds itself to the assembled deployment once agents are ready. Binding is idempotent per instance (see Bind).
func (*LocalDirectory) BindTargetSource ¶ added in v0.1.24
func (d *LocalDirectory) BindTargetSource(source TargetSource) error
BindTargetSource attaches the live dynamic target view. It is set-once for the directory's lifetime: binding twice — including after FreezeTargets, which only swaps the active view and keeps the bound source — returns a Conflict error.
func (*LocalDirectory) FreezeTargets ¶ added in v0.1.24
func (d *LocalDirectory) FreezeTargets(instances map[string]*agent.Agent)
FreezeTargets replaces the live dynamic source with a fixed instance set. Idempotent; used when a generation retires. The bound source is retained so UnfreezeTargets can restore it.
func (*LocalDirectory) List ¶
func (d *LocalDirectory) List(context.Context) ([]Target, error)
List returns targets in deploy.Result.InstanceNames order followed by the dynamic targets (frozen set when retired, otherwise the live source) sorted by id.
func (*LocalDirectory) UnfreezeTargets ¶ added in v0.1.24
func (d *LocalDirectory) UnfreezeTargets()
UnfreezeTargets restores the live dynamic source bound by BindTargetSource, discarding the frozen view. Idempotent.
type LocalService ¶
type LocalService struct {
// contains filtered or unexported fields
}
LocalService executes local sync delegations and coordinates optional async storage/workers.
func NewService ¶
func NewService(directory *LocalDirectory, backend AsyncBackend, opts ...Option) (*LocalService, error)
NewService constructs a local service. Successful responses in every mode retain one shared idempotency key and request fingerprint. Async Accepted responses use the shorter of the service retention and a positive backend retention declaration, so replay cannot outlive backend queryability. If the backend also implements WorkSource, bounded workers start immediately. The backend remains owned by the deploy Result or caller.
func (*LocalService) BindSessionManager ¶ added in v0.1.23
func (s *LocalService) BindSessionManager(manager *session.Manager) error
BindSessionManager implements session.ManagerBinder: the runtime hands this service the session manager that owns subagent session lifecycle. Binding is set-once: a second bind is a conflict. The write is serialized by stateMu; reads happen through sessionManager.
func (*LocalService) Close ¶
func (s *LocalService) Close() error
Close rejects new operations, cancels service-owned workers, and waits for every admitted operation and worker to finish. It is idempotent.
func (*LocalService) Run ¶
func (s *LocalService) Run(ctx context.Context, req AsyncRequest) (Response, error)
Run executes a backend-neutral work item through the same depth, timeout, host-propagation, and concurrency limits as a sync call.
func (*LocalService) Start ¶
func (s *LocalService) Start() error
Start begins asynchronous workers when the backend supports WorkSource. Repeated calls are safe and do not create duplicate workers.
type Option ¶
type Option func(*serviceConfig) error
Option configures a local Service.
func WithDeferredWorkers ¶
func WithDeferredWorkers() Option
WithDeferredWorkers defers asynchronous worker startup until Start. This is useful when a lifecycle owner must finish binding all dependencies before background work begins.
func WithIdempotencyRetention ¶
WithIdempotencyRetention sets how long successful responses remain safely replayable. The retention must be positive.
func WithMaxConcurrency ¶
WithMaxConcurrency bounds all local agent executions, including sync calls and work claimed by asynchronous workers.
func WithMaxDepth ¶
WithMaxDepth sets the largest allowed delegation depth. A top-level delegation executes at depth one.
func WithSessionInitializer ¶ added in v0.8.1
func WithSessionInitializer(initializer SessionInitializer) Option
WithSessionInitializer registers a per-run hook that stamps application-owned session state onto the subagent's freshly minted session, before its turn starts or resumes. It runs wherever the delegated run has a session identity: on the session path, and on [LocalService.runAtLegacy] when a SessionProvider minted one.
A delegation that would run without any identity is rejected instead of skipped: the hook was configured to narrow the run, and a run that cannot receive its policy must not proceed under a wider default.
A hook error fails the delegation rather than degrading to a default, so a policy that could not be applied never runs under a wider one.
func WithSessionProvider ¶ added in v0.1.23
func WithSessionProvider(provider SessionProvider) Option
WithSessionProvider sets the identity policy for delegated subagent sessions. When nil and a session manager is bound, the service mints a fresh ContextID per delegation.
func WithStreamEscrowTTL ¶ added in v0.1.30
WithStreamEscrowTTL bounds how long an async delegation's stream escrow may sit unclaimed (or between claims) before the service drops it. Claimed entries are refreshed and released at terminal completion, so a long-running job is unaffected by a short TTL; the TTL only guards abandoned entries. Zero uses the service default.
func WithStreamTargetExporter ¶ added in v0.1.30
func WithStreamTargetExporter(exporter StreamTargetExporter) Option
WithStreamTargetExporter registers the caller-side exporter that describes live sinks as serializable [StreamTarget]s on async submit. When set, the exporter is consulted for each inherited sink and the first describable target is persisted alongside the escrow ref, so cross-process workers can re-materialize the destination through WithStreamTargetResolver even when no in-process escrow entry survives.
func WithStreamTargetResolver ¶ added in v0.1.30
func WithStreamTargetResolver(resolver StreamTargetResolver) Option
WithStreamTargetResolver registers the worker-side resolver that materializes a serializable StreamTarget (persisted in an async AsyncRequest) into a live stream sink. Resolvers MUST whitelist target kinds; the resolver is only consulted when no in-process escrow entry exists for the request.
func WithTimeout ¶
WithTimeout caps each local agent execution. Zero leaves the caller's deadline unchanged.
func WithWorkerHost ¶
WithWorkerHost sets the stable base Host used by asynchronous workers. Service adds its delegation capability without replacing optional capabilities such as EventBusProvider. The caller retains Host ownership.
type RandomSessionProvider ¶ added in v0.1.23
type RandomSessionProvider struct{}
RandomSessionProvider mints a unique ContextID for every delegation and never persists: each delegated run is an ephemeral session with no history or resume state.
func (RandomSessionProvider) CreateContextID ¶ added in v0.1.23
func (RandomSessionProvider) CreateContextID(context.Context, AsyncRequest) (string, error)
CreateContextID implements SessionProvider.
func (RandomSessionProvider) Persistent ¶ added in v0.1.23
func (RandomSessionProvider) Persistent() bool
Persistent implements SessionProvider.
type Request ¶
type Request struct {
Mode Mode `json:"mode"`
Target string `json:"target"`
Input string `json:"input"`
Metadata map[string]string `json:"metadata,omitempty"`
// Attributes are caller-declared run attributes for the delegated run
// (execution policy keys, tenant hints, …). Core treats them as
// opaque: they are copied onto the subagent's run attributes, below
// the lineage keys the service owns. Declaring a lineage key
// (tool.call_id) is a validation error rather than a silent override:
// the key identifies the one tool call behind this delegation.
//
// Declare them explicitly; the caller's own run attributes are not
// propagated, because deployments keep run-scoped payloads there
// (e.g. checkpoint recovery blobs) that must not leak into a
// subagent. Unlike Metadata they never become graph inputs, but like
// Metadata they do take part in identity: both idempotent replay and
// resume of a parked run compare the map verbatim, so a retry under a
// different attribute map is a different request. The lineage keys are
// the exception — a retry is a new tool call, so resume identity
// ignores them.
Attributes map[string]string `json:"attributes,omitempty"`
IdempotencyKey string `json:"idempotency_key,omitempty"`
}
Request is the portable input accepted by a Service.
type Response ¶
type Response struct {
ID string `json:"id"`
Status Status `json:"status"`
Output string `json:"output,omitempty"`
Error string `json:"error,omitempty"`
Metadata map[string]string `json:"metadata,omitempty"`
}
Response is a snapshot of delegated work.
type RunIDNotifier ¶ added in v0.1.30
type RunIDNotifier interface {
// NoteRunID records runID for the work item identified by its
// stream escrow ref. Unknown refs are no-ops; errors are
// best-effort (recorded, never fail the run).
NoteRunID(ctx context.Context, ref, runID string) error
}
RunIDNotifier is an optional AsyncBackend capability: it lets a claimed async work item record the subagent run id as soon as the run starts, so operational views can correlate a delegation id with its run before the terminal response arrives.
type Runner ¶
type Runner interface {
Run(ctx context.Context, req AsyncRequest) (Response, error)
}
Runner is the restricted execution seam a queue-owned worker may use.
type Service ¶
type Service interface {
Delegate(ctx context.Context, req Request) (Response, error)
Get(ctx context.Context, id string) (Response, error)
}
Service starts delegated work and retrieves its latest response. Implementations must declare and guarantee a finite idempotency retention window. Within that window, requests with the same non-empty idempotency key and business fields must safely replay the same operation, and its response must remain queryable; reusing the key for a semantically different request must return a conflict-classified error. After the declared window expires, the key may start a new operation: this contract is bounded idempotency, not permanent exactly-once execution.
type ServiceProvider ¶
type ServiceProvider interface {
DelegationService() Service
}
ServiceProvider is the optional Host capability exposing delegation.
type ServiceSettings ¶
type ServiceSettings struct {
MaxConcurrency *int `json:"max_concurrency,omitempty"`
MaxDepth *int `json:"max_depth,omitempty"`
Timeout *string `json:"timeout,omitempty"`
IdempotencyRetention *string `json:"idempotency_retention,omitempty"`
DeferWorkers bool `json:"defer_workers,omitempty"`
}
ServiceSettings is the strict settings subtree of the local service factory. Zero fields leave the service defaults.
type SessionInitializer ¶ added in v0.8.1
SessionInitializer runs once per delegated run, after the subagent's session identity is minted and before the turn starts or resumes. It is the seam for per-session state the application owns — sandbox mode, think level, model hint — which core deliberately does not model. Returning an error fails the delegation: a policy that could not be applied must not silently fall back to a wider default. A run on the manager-less path is initialized too when a SessionProvider supplied the identity.
type SessionProvider ¶ added in v0.1.23
type SessionProvider interface {
// CreateContextID returns the subagent session's ContextID. AgentID is
// filled by the service from the validated request target, so a
// provider can never introduce an identity mismatch. Returning an
// error fails the delegation; returning an empty ContextID is a
// validation error.
CreateContextID(ctx context.Context, req AsyncRequest) (string, error)
// Persistent reports whether the provider's ContextID is stable and
// should survive as a resumable session. Providers deriving stable
// ContextIDs (e.g. by caller+target) return true; providers minting a
// fresh ContextID per delegation return false.
Persistent() bool
}
SessionProvider decides a delegated subagent's session ContextID and whether that identity is stable and needs persistence. Implementations are injected by the application. A nil provider falls back to the service default: mint a fresh ContextID per delegation, but only when a session manager is bound (see LocalService.runAt).
type Status ¶
type Status string
Status describes the backend-neutral lifecycle of delegated work.
type StreamPolicySnapshot ¶ added in v0.1.30
type StreamPolicySnapshot struct {
Visibility session.Visibility `json:"visibility,omitempty"`
Authority session.Authority `json:"authority,omitempty"`
AckMode session.AckMode `json:"ack_mode,omitempty"`
MaxUnacked int `json:"max_unacked,omitempty"`
QueueSize int `json:"queue_size,omitempty"`
DeliveryTimeout int64 `json:"delivery_timeout_ms,omitempty"`
}
StreamPolicySnapshot is a serializable projection of the caller's stream attachment policy, carried alongside a StreamTarget so the worker can materialize the attachment with the same tuning. It is populated from the caller's first sink spec; authority/ack fields are informational and the worker always downgrades inherited attachments to observers (see inheritedSinkSpecs).
type StreamRef ¶ added in v0.1.30
type StreamRef struct {
// Ref is the service-side escrow key. Empty when no in-process
// escrow exists.
Ref string `json:"ref,omitempty"`
// Policy snapshots the caller's attachment tuning.
Policy StreamPolicySnapshot `json:"policy,omitempty"`
// Target describes the delivery destination for resolver-based
// materialization. Empty when the escrow path is used. At most
// one target is persisted: cross-process delivery is
// single-destination by contract.
Target *StreamTarget `json:"target,omitempty"`
}
StreamRef is the queue-crossing reference to an async delegation's stream attachment. In-process backends use Ref (an escrow key that the service resolves to the caller's live sinks); cross-process backends use Target with a runtime-provided resolver.
type StreamTarget ¶ added in v0.1.30
type StreamTarget struct {
// Kind is the target vocabulary understood by the resolver
// (e.g. "conversation", "bus"). Resolvers MUST reject unknown
// kinds — targets originate from persisted backend records and
// must never drive arbitrary sink construction.
Kind string `json:"kind"`
// ID is the resolver-specific destination identifier.
ID string `json:"id"`
}
StreamTarget is a serializable description of where an async subagent's stream envelopes should be delivered. It replaces the live (non-serializable) sink across the queue boundary: the caller's runtime knows how to describe its sinks as targets, and the worker's runtime resolves them back into live sinks through StreamTargetResolver.
AsyncRequest.Stream.Target is single-valued (see StreamRef): the in-process escrow preserves every inherited sink, but the cross-process path can restore exactly one destination. The exporter prefers broadcast (bus) targets when several sinks are describable.
type StreamTargetExporter ¶ added in v0.1.30
type StreamTargetExporter func(spec session.SinkSpec) (StreamTarget, bool)
StreamTargetExporter describes a caller-side live sink as a serializable StreamTarget at async submit time, so cross-process backends can re-materialize the same destination worker-side through a StreamTargetResolver. It returns ok=false for sinks that are not [StreamTargetProvider]s (e.g. plain closures with no durable destination). Cross-process delivery restores at most one target — see StreamTarget.
type StreamTargetProvider ¶ added in v0.1.30
type StreamTargetProvider interface {
StreamTarget() (StreamTarget, bool)
}
StreamTargetProvider is implemented by stream sinks that can describe their durable destination as a serializable StreamTarget. [StreamTargetExporter]s recognize providers instead of concrete sink types, so decorators (logging middleware, proxies) can pass the description through without breaking recognition.
type StreamTargetResolver ¶ added in v0.1.30
type StreamTargetResolver func(ctx context.Context, target StreamTarget) (agent.StreamSink, error)
StreamTargetResolver materializes a live stream sink for a serializable StreamTarget on the worker side. Resolvers MUST whitelist target kinds and never construct sinks from free-form persisted data.
type Target ¶
type Target struct {
ID string `json:"id"`
Description string `json:"description,omitempty"`
Modes []Mode `json:"modes,omitempty"`
Metadata map[string]string `json:"metadata,omitempty"`
}
Target describes a backend-neutral delegation destination. Modes is an explicit allowlist; an empty Modes list means unrestricted support for every defined delegation mode.
type TargetSource ¶ added in v0.1.24
type TargetSource interface {
// Dynamic resolves one dynamic target by id. Deployment targets
// are served from the directory's own snapshot and never returned
// here. The id is the AgentID — in the runtime path the
// registration name — and implementations must resolve it as such.
Dynamic(id string) (*agent.Agent, bool)
// DynamicNames lists the dynamic target ids (AgentIDs).
DynamicNames() []string
}
TargetSource is the live view of dynamically registered targets that a directory merges with its deployment snapshot. The runtime's agent registry implements it, so registration and unregistration take effect without re-binding the directory. Implementations must be safe for concurrent use.
type TargetViewBinder ¶ added in v0.1.24
type TargetViewBinder interface {
// BindTargetSource attaches the live dynamic source. It is
// set-once: a second bind returns a Conflict error.
BindTargetSource(source TargetSource) error
}
TargetViewBinder is implemented by directory resources that want the runtime's live target source attached. The runtime calls it once per generation before the swap.
type TargetViewFreezer ¶ added in v0.1.24
type TargetViewFreezer interface {
// FreezeTargets pins the live dynamic source to a fixed instance
// set. Freezing is a one-shot commit: callers must guarantee that
// every later failure path can either proceed without the live
// view or pair the freeze with UnfreezeTargets, or the directory
// will silently diverge from the runtime registry.
FreezeTargets(instances map[string]*agent.Agent)
// UnfreezeTargets restores the live dynamic source after a
// rollback. Idempotent; safe to call on a never-frozen directory.
UnfreezeTargets()
}
TargetViewFreezer is implemented by directory resources that must pin their dynamic view when the generation retires, so in-flight delegations keep resolving the instances that generation served.
Generation semantics: the delegation service uses the resolved instance for target validation and telemetry only; actual execution goes through the session manager's per-generation resolver. After a reload the retired directory may therefore validate against a frozen instance while the delegated turn starts on the new generation's re-bound instance — "the generation is determined at Session.Start", matching the runtime's resolver contract.
type Work ¶
type Work struct {
ID string `json:"id"`
LeaseToken string `json:"lease_token"`
Request AsyncRequest `json:"request"`
Context context.Context `json:"-"`
}
Work is one claimed asynchronous request. LeaseToken uniquely identifies this claim generation and must be supplied to WorkSource.Complete. Context optionally carries the backend-owned execution lease; canceling it must stop the claimed execution.
type WorkSource ¶
type WorkSource interface {
Claim(ctx context.Context) (Work, error)
Complete(ctx context.Context, id, leaseToken string, response Response) error
}
WorkSource is the optional worker side of an AsyncBackend. When implemented, Service starts bounded workers that claim backend-neutral work and complete it through the same backend. Claim must return a unique, non-empty lease token and unblock when ctx is canceled. Complete must only apply a terminal response when the token identifies the current lease; stale completions are ignored.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package hostwrap bridges core/delegation and the runtime host factory seam.
|
Package hostwrap bridges core/delegation and the runtime host factory seam. |
|
Package kanban provides an in-memory core/delegation AsyncBackend and WorkSource.
|
Package kanban provides an in-memory core/delegation AsyncBackend and WorkSource. |
|
resource
Package resource adapts kanban delegation backends to deployment resources.
|
Package resource adapts kanban delegation backends to deployment resources. |
|
Package delegation exposes backend-neutral delegate, delegation_status, and delegation_targets tools.
|
Package delegation exposes backend-neutral delegate, delegation_status, and delegation_targets tools. |