virtualagent

package
v1.28.4 Latest Latest
Warning

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

Go to latest
Published: Aug 15, 2026 License: Apache-2.0 Imports: 12 Imported by: 0

Documentation

Overview

Package virtualagent owns Harbor's canonical virtual-agent profile representation: the bounded, non-recursive overlay a configured top-level agent applies to a planner-spawned child run, the immutable profile map frozen at the parent's run start, and the pinned binding persisted on the child task so a restart reproduces the exact profile.

What a virtual agent is

A virtual agent is NOT a registered agent. It never appears in `agents.list`, is never a `control.start` target, and its key never joins the isolation tuple. `Task.AgentID` stays the owning top-level agent; the profile is a per-run CONFIGURATION projection only, exactly like the agent-config control plane's other sections.

The canonical representation (YAML and AgentConfig revisions)

A profile is declared either in the boot YAML (`virtual_agents:`) or in an immutable AgentConfig revision's `virtual_agents` section. Both doors decode into the SAME canonical Profile / Overlay shapes in this package, normalized by the SAME functions, and hashed by the SAME Profile.Hash — a YAML-declared profile and a revision-pinned profile with identical content are byte-identical in canonical form.

The overlay is bounded and non-recursive

An overlay MAY narrow the child's model parameters, skills (intersection), tool exposure (union into the exclusion set) and limits (max-steps / token-budget), and MAY add trusted specialist instructions. It CANNOT widen resources or guardrails, attach capabilities, own providers / hooks / memory, recurse into another profile, or target A2A — those fields do not exist in Overlay, so no value can express them (structurally impossible, not merely validated). Omission is byte-compatible: a run that never selects a profile behaves exactly as before.

Freeze, bind, pin

The parent's run start resolves the effective profile map (revision section over YAML), validates it, and FREEZES it against the parent's active config revision id + digest. A planner spawn selecting a profile validates key-unknown / overlay-invalid / stale-live-revision BEFORE anything persists; the accepted spawn carries a Binding (the owning agent, key, label, parent, config revision id + digest, profile hash) onto the task record. The child's run start re-resolves the current map and validates the pin: a moved config revision, an edited profile definition, or a tampered binding fails the child run LOUD — a restart reproduces the exact profile or does not run at all. A virtual-profile run cannot itself spawn a virtual profile (non-recursive).

Index

Constants

View Source
const (
	// MaxKeyLength bounds a profile key in bytes.
	MaxKeyLength = 128
	// MaxLabelLength bounds a profile label in bytes.
	MaxLabelLength = 200
	// MaxModelLength bounds the overlay model name in bytes.
	MaxModelLength = 128
	// MaxSkillEntries bounds the overlay skill-narrowing set size.
	MaxSkillEntries = 100
	// MaxToolListEntries bounds each overlay tool-exclusion list size.
	MaxToolListEntries = 500
	// MaxInstructionsBytes bounds the additive specialist-instruction
	// text (trusted, operator-authored — bounded, never unbounded).
	MaxInstructionsBytes = 16 * 1024
	// MaxMaxTokens bounds the overlay max-tokens value.
	MaxMaxTokens = 1_000_000
	// MaxMaxSteps bounds the overlay max-steps value.
	MaxMaxSteps = 100_000
	// MaxMaxTokenBudget bounds the overlay token-budget value.
	MaxMaxTokenBudget = 10_000_000
	// DefaultMaxProfiles bounds the operator-owned virtual profile map.
	DefaultMaxProfiles = 32
)

Size bounds. Single-sourced here; the config validator and the agentcfg normalization call into this package rather than carrying literal copies.

Variables

View Source
var (
	// ErrInvalidKey — a profile key is empty, over-long, or outside the
	// restricted identifier charset.
	ErrInvalidKey = errors.New("virtualagent: invalid profile key")
	// ErrInvalidOverlay — the overlay violates a bounded narrow-only
	// invariant (an unknown dimension is structurally impossible; this
	// covers bounds / charset / narrowing-shape violations).
	ErrInvalidOverlay = errors.New("virtualagent: invalid overlay")
	// ErrInvalidProfile — the profile envelope (key / label / parent /
	// overlay) failed validation.
	ErrInvalidProfile = errors.New("virtualagent: invalid profile")
	// ErrInvalidMap — the profile map failed validation (owner mismatch,
	// duplicate key, an invalid member).
	ErrInvalidMap = errors.New("virtualagent: invalid profile map")
	// ErrUnknown — a spawn selected a profile key absent from the frozen
	// map. Fails BEFORE persistence.
	ErrUnknown = errors.New("virtualagent: unknown profile key")
	// ErrInvalid — a spawn selected a profile whose overlay failed
	// re-validation at the dispatch boundary. Fails BEFORE persistence.
	ErrInvalid = errors.New("virtualagent: invalid selected profile")
	// ErrStale — the selected profile is stale: the live parent-config
	// revision no longer matches the frozen map's pinned revision (at
	// spawn), or the persisted binding no longer matches the current
	// revision / profile definition (at child run start). Fails before
	// persistence at spawn; fails the child run LOUD at run start.
	ErrStale = errors.New("virtualagent: stale profile pin")
	// ErrRecursion — a run that IS a virtual-profile run tried to spawn
	// another virtual-profile child. The overlay is non-recursive.
	ErrRecursion = errors.New("virtualagent: virtual profile recursion")
	// ErrNoMap — a spawn selected a profile in a run whose effective
	// agent is not the profile-owning top-level agent (no frozen map).
	ErrNoMap = errors.New("virtualagent: no virtual-agent profile map in this run")
	// ErrTampered — the persisted binding disagrees with the resolved
	// profile (label / parent / hash mismatch). Fails the child run LOUD.
	ErrTampered = errors.New("virtualagent: tampered profile binding")
	// ErrMissing — the persisted binding's key is absent from the current
	// profile map. Fails the child run LOUD.
	ErrMissing = errors.New("virtualagent: bound profile key is missing from the current map")
)

Sentinel errors. Callers compare via errors.Is.

Functions

func BlockName

func BlockName(k Key) string

BlockName returns the ExtraSystemBlocks block name a profile's specialist instructions render under: `virtual_agent.<key>`. The name is stable and key-unique so a transcript reader can attribute the block, and a future profile edit that removes the block drops it.

func ClampMax

func ClampMax(v int, parent *int) int

ClampMax returns v clamped to at most parent. When parent is nil (the parent resolved no ceiling), v is returned unchanged. Used for the never-widen limits (max-tokens / max-steps / token-budget).

func IntersectStrings

func IntersectStrings(base, keep []string) []string

IntersectStrings returns the sorted intersection of base and keep — the narrow-only skills operation. A nil/empty keep returns nil (no narrowing).

func OverlayClampMaxSteps

func OverlayClampMaxSteps(parentCap int, overlay *int) int

OverlayClampMaxSteps clamps an overlay max-steps against the parent driver's run-loop cap. The overlay may only ever tighten the cap.

func OverlayClampMaxTokens

func OverlayClampMaxTokens(parentResolved *int, overlay *int) *int

OverlayClampMaxTokens clamps an overlay max-tokens against the parent's RESOLVED effective ceiling. When the parent resolved none (nil), the overlay value is used as-is; when the overlay is nil, the parent's value is preserved.

func OverlayClampTokenBudget

func OverlayClampTokenBudget(parent int, overlay *int) int

OverlayClampTokenBudget clamps an overlay token budget against the parent's resolved budget. A zero / nil parent budget means "no budget" (compression off); an overlay budget then introduces a limit (a narrowing), and a parent budget caps the overlay at it.

func UnionStrings

func UnionStrings(a, b []string) []string

UnionStrings returns the sorted union of two exclusion sets — the narrow-only tools operation (it can only hide more).

func ValidateBinding

func ValidateBinding(b Binding) error

ValidateBinding checks the structural invariants of a persisted binding (all fields non-empty + bounded; the digest is a 64-hex SHA-256). Callers additionally verify the binding against the frozen / current map — this is the shape check only.

func ValidateKey

func ValidateKey(k Key) error

ValidateKey checks the key charset + length bounds.

func ValidateMap

func ValidateMap(m Map) error

ValidateMap checks the owner + every member's parent-owner binding.

func ValidateOverlay

func ValidateOverlay(o Overlay) error

ValidateOverlay checks the bounded narrow-only invariants. Unknown dimensions are structurally unrepresentable; this validates bounds / charset / reasoning-effort values and the narrowing shape (list members bounded, never an enable set).

func ValidateProfile

func ValidateProfile(p Profile) error

ValidateProfile checks the profile envelope (key / label / parent / overlay bounds).

func WithFrozenMap

func WithFrozenMap(ctx context.Context, f *FrozenMap) context.Context

WithFrozenMap attaches the parent run's frozen profile map to ctx so the dispatch executor can validate planner spawn selectors against it. Per-run state in ctx — never on a shared artifact.

func WithRunBinding

func WithRunBinding(ctx context.Context, b *Binding) context.Context

WithRunBinding attaches the CURRENT run's own profile binding to ctx so the dispatch executor can enforce the non-recursion rule (a virtual-profile run cannot spawn another virtual profile). Attached only when the run IS a virtual-profile run.

Types

type Binding

type Binding struct {
	AgentID          string `json:"agent_id,omitempty"`
	Key              Key    `json:"key,omitempty"`
	Label            string `json:"label,omitempty"`
	Parent           string `json:"parent,omitempty"`
	ConfigRevisionID string `json:"config_revision_id,omitempty"`
	ConfigDigest     string `json:"config_digest,omitempty"`
	ProfileHash      string `json:"profile_hash,omitempty"`
	// Profile is the sealed canonical snapshot used to reconstruct the child
	// without consulting mutable configuration after admission.
	Profile Profile `json:"profile"`
}

Binding is the immutable per-task metadata that pins a virtual-agent profile: persisted on the child task at spawn (before the child runs) and re-validated at the child's run start so a restart reproduces the exact profile. `AgentID` is the owning TOP-LEVEL agent — it stays `Task.AgentID`; the binding never re-keys the task to a different agent and never joins the isolation tuple.

func CloneBinding

func CloneBinding(b Binding) Binding

CloneBinding returns a defensive copy suitable for crossing a persistence or task boundary. The snapshot's pointer and slice fields never alias the caller's binding.

func RunBindingFrom

func RunBindingFrom(ctx context.Context) *Binding

RunBindingFrom returns the current run's own profile binding (nil when the run is not a virtual-profile run).

type FrozenMap

type FrozenMap struct {
	Owner        string
	RevisionID   string
	ConfigDigest string
	// contains filtered or unexported fields
}

FrozenMap is the profile map frozen at the parent's run start: the canonical Map bound to the parent agent's active config revision id + digest. A spawn validates against the frozen map (unknown / invalid / stale), and the persisted Binding pins the frozen revision + digest + per-profile hash so the child's run start reproduces the exact profile — or fails loud.

A FrozenMap is per-run state carried on the run's ctx (the concurrent-reuse contract): never a field on a shared artifact.

func FrozenMapFrom

func FrozenMapFrom(ctx context.Context) *FrozenMap

FrozenMapFrom returns the frozen map attached to ctx (nil when absent).

func NewFrozenMap

func NewFrozenMap(m Map, revisionID, configDigest string, live LiveRevisionReader) (*FrozenMap, error)

NewFrozenMap freezes a validated canonical map against a parent-config revision. A nil map or an empty owner returns ErrInvalidMap. live is the optional staleness probe (nil disables the live re-check).

func (*FrozenMap) Bind

func (f *FrozenMap) Bind(p Profile) (Binding, error)

Bind constructs the binding for the frozen profile p under the map's owner: agent = parent = owner (the top-level agent), pinned to the frozen revision + digest + the profile's hash.

func (*FrozenMap) HashOf

func (f *FrozenMap) HashOf(k Key) (string, bool)

HashOf returns the frozen profile hash for key and whether it exists.

func (*FrozenMap) Profile

func (f *FrozenMap) Profile(k Key) (Profile, bool)

Profile returns the frozen profile for key and whether it exists.

func (*FrozenMap) VerifyCurrent

func (f *FrozenMap) VerifyCurrent(ctx context.Context) error

VerifyCurrent is the spawn-time staleness probe: it re-reads the live parent-config revision and returns ErrStale when it no longer matches the frozen pin. A nil live reader (the default in pure unit tests) trusts the frozen pin and returns nil.

func (*FrozenMap) VerifyPin

func (f *FrozenMap) VerifyPin(b Binding) (Profile, error)

VerifyPin is the child-run-start pin check: it validates a persisted binding against the CURRENT frozen map so a restart reproduces the exact profile. It returns:

  • ErrMissing when the bound key is absent from the current map,
  • ErrStale when the current parent-config revision/digest differs from the binding's pin,
  • ErrTampered when the current profile's hash (or label / parent) disagrees with the binding.

On nil error, the returned profile is the exact profile the child must run under.

type Key

type Key string

Key identifies one virtual-agent profile within its owner.

type LiveRevisionReader

type LiveRevisionReader func(ctx context.Context) (revisionID, digest string, err error)

LiveRevisionReader is the per-run injected seam the frozen map uses to re-read the parent agent's CURRENT active config revision at spawn time (the staleness probe). The run-loop driver builds it over its agentcfg registry + the run's identity triple; it carries no identity because the driver already captured it. A nil function is a no-op stale check (the frozen map's pinned revision is trusted as-is).

type Map

type Map struct {
	Owner       string    `json:"owner,omitempty"`
	MaxProfiles int       `json:"max_profiles,omitempty"`
	Profiles    []Profile `json:"profiles,omitempty"`
}

Map is the canonical profile map owned by ONE configured top-level agent. The map's owner must equal the runtime's configured top-level agent id; every profile's Parent must equal the owner.

func NormalizeMap

func NormalizeMap(m Map) Map

NormalizeMap returns the canonical map form: profiles sorted by key (key-unique; the LAST duplicate wins, matching the agentcfg connection-section convention).

func (Map) ByKey

func (m Map) ByKey() map[Key]Profile

ByKey returns the keyed view of the map's profiles. Callers must not mutate the returned map or its profile values.

type Overlay

type Overlay struct {
	Model           *string  `json:"model,omitempty"`
	Temperature     *float64 `json:"temperature,omitempty"`
	MaxTokens       *int     `json:"max_tokens,omitempty"`
	ReasoningEffort *string  `json:"reasoning_effort,omitempty"`
	// Skills is a pointer so an EXPLICIT empty set (narrow to no skills)
	// is distinguishable from omission (no narrowing). nil = no skill
	// narrowing.
	Skills        *[]string `json:"skills,omitempty"`
	DisabledTools []string  `json:"disabled_tools,omitempty"`
	PausedServers []string  `json:"paused_servers,omitempty"`
	MaxSteps      *int      `json:"max_steps,omitempty"`
	TokenBudget   *int      `json:"token_budget,omitempty"`
	Instructions  string    `json:"instructions,omitempty"`
}

Overlay is the explicit bounded non-recursive overlay a profile applies over its parent's frozen configuration. Every dimension is narrow-only or additive:

  • Model / Temperature / MaxTokens / ReasoningEffort narrow the child's sampling parameters (the child's max-tokens ceiling is clamped to the parent's resolved ceiling — see OverlayClampMaxTokens).
  • Skills is an INTERSECTION: the child keeps only parent skills named here (nil = no narrowing).
  • DisabledTools / PausedServers are UNIONED into the exclusion set: they can only hide tools the parent exposed, never re-expose one.
  • MaxSteps / TokenBudget narrow the child's run limits (clamped to the parent's own cap).
  • Instructions adds trusted, operator-authored specialist guidance (rendered verbatim in the trusted additive position, bounded).

There is deliberately NO field for providers, hooks, memory, capabilities, a parent-profile reference, or an A2A target: those dimensions cannot be expressed, so they can never be widened, attached, or recursed into.

func NormalizeOverlay

func NormalizeOverlay(o Overlay) Overlay

NormalizeOverlay returns the canonical form: sorted / de-duplicated list members, trimmed instructions, preserved pointer presence. A nil or empty-nil list normalises to nil so omission is byte-compatible.

func (Overlay) IsZero

func (o Overlay) IsZero() bool

IsZero reports whether the overlay is entirely empty (no narrowing, no instructions) — the identity overlay that leaves a run byte-identical.

type Profile

type Profile struct {
	Key     Key     `json:"key"`
	Label   string  `json:"label,omitempty"`
	Parent  string  `json:"parent,omitempty"`
	Overlay Overlay `json:"overlay,omitempty"`
	// InputPatterns bounds which inherited artifact references a child may
	// receive. Matching is against the canonical filename and MIME type;
	// the model supplies IDs, never content or a URL.
	InputPatterns []string `json:"input_patterns,omitempty"`
	// InputCount is the maximum number of inherited input references.
	InputCount int `json:"input_count,omitempty"`
	// InputDisposition is the configuration-owned disposition applied to
	// every accepted input reference. Empty preserves the normal policy.
	InputDisposition string `json:"input_disposition,omitempty"`
	// OutputSchema is the configuration-owned terminal contract. Its hash is
	// pinned in the profile binding and is never accepted from the model.
	OutputSchema     json.RawMessage `json:"output_schema,omitempty"`
	OutputSchemaHash string          `json:"output_schema_hash,omitempty"`
}

Profile is the canonical virtual-agent profile shared by the boot YAML declaration and immutable AgentConfig revisions.

func NormalizeProfile

func NormalizeProfile(p Profile) Profile

NormalizeProfile returns the canonical profile form.

func (Profile) Hash

func (p Profile) Hash() (string, error)

Hash returns the deterministic SHA-256 hex digest of the profile's canonical (sorted-key JSON) representation. Two profiles with identical content — declared in YAML or in a revision — hash equal; any content change bumps the hash. This is the digest a Binding pins.

Jump to

Keyboard shortcuts

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