agentcfg

package
v1.8.0 Latest Latest
Warning

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

Go to latest
Published: Jun 27, 2026 License: Apache-2.0 Imports: 14 Imported by: 0

Documentation

Overview

Package agentcfg owns Harbor's agent-config control plane: a durable, identity-scoped, versioned desired-state registry where every edit to an agent's configuration (skills membership now; tool/MCP exposure and prompt layers as later consumers extend the envelope) is an immutable, content-addressed revision. The active configuration is a pointer to a revision; rollback is a repoint; diff is a server-side revision compare.

The seam (CLAUDE.md §4.4)

The Registry interface lives here; drivers live under internal/agentcfg/drivers/<driver>/; a factory + registry dispatches by name. The StateStore-backed driver reuses the §9 persistence triad for identity isolation, exactly as the governance tenant-override policy does — no new persistence subsystem.

Identity (CLAUDE.md §6)

Every record is scoped by the full (tenant, user, session) triple. The registry is KEYED by agent_id (the agent's registration identity), but agent_id is NEVER an isolation filter: the driver keys each agent's config under a synthetic identity whose tenant is the caller's verified tenant, so a tenant's config is invisible to another tenant.

Concurrent reuse (the concurrent-reuse contract)

A constructed Registry is a compiled artifact: immutable after construction and safe to share across N concurrent goroutines. Per-run state lives in ctx and the supplied arguments, never on the Registry.

Index

Constants

View Source
const (
	// EventTypeConfigRevised — emitted when a new agent-config revision is
	// written (any successful SetRevision, including the skills-control
	// consumer). Carries the agent id, the new + parent revision ids, the
	// content hash, and the author identity.
	EventTypeConfigRevised events.EventType = "agent.config.revised"

	// EventTypeConfigReverted — emitted when an admin rolls the active
	// pointer back to an existing revision. Carries the agent id, the
	// revision rolled back TO, the previously-active revision id, and the
	// author identity. Rollback never mutates a revision; the event marks
	// the active-pointer repoint.
	EventTypeConfigReverted events.EventType = "agent.config.reverted"

	// EventTypeMCPConnectionPaused — emitted when a tool-exposure edit newly
	// pauses an MCP server (the server is added to the active revision's
	// paused set). The transport stays warm — pause is projection-time, so
	// the server's tools are excluded from the next run and its App callbacks
	// are rejected against current state. Carries the agent id, the paused
	// server id, the recording revision id, and the author identity — never a
	// secret. Drives the operator-legible "paused by a system administrator"
	// overlay (the client renders the canonical event; it never reaches into
	// the App).
	EventTypeMCPConnectionPaused events.EventType = "mcp.connection.paused"

	// EventTypeMCPConnectionResumed — emitted when a tool-exposure edit newly
	// resumes an MCP server (the server is removed from the active revision's
	// paused set). Resume is an instant flag flip — no re-dial. Carries the
	// same operator-visible audit metadata as the paused event.
	EventTypeMCPConnectionResumed events.EventType = "mcp.connection.resumed"

	// EventTypeMCPConnectionPending — emitted when an admin add of a NEW MCP
	// server connection begins the attach lifecycle (dial → initialize →
	// discover → register). Marks the `pending` lifecycle transition before
	// the terminal added / failed / auth_required event. Carries the agent
	// id, the server name, and the author identity — never a secret.
	EventTypeMCPConnectionPending events.EventType = "mcp.connection.pending"

	// EventTypeMCPConnectionAdded — emitted when an admin add of a NEW MCP
	// server connection completes the attach lifecycle successfully: the
	// transport dialled, the initialize handshake succeeded, discovery ran,
	// and the server's tools were registered on the live catalog. Carries
	// the agent id, the server name, the recording revision id, and the
	// author identity — never a secret header / token / credential.
	EventTypeMCPConnectionAdded events.EventType = "mcp.connection.added"

	// EventTypeMCPConnectionFailed — emitted when an admin add of a NEW MCP
	// server connection FAILS at any attach step (unreachable, handshake /
	// version mismatch, malformed discovery). A half-attached server is NEVER
	// registered (fail loud, no silent drop). Carries the agent id, the
	// server name, and a SAFE failure reason — never a secret. No revision is
	// recorded for a failed add (the broken connection is not desired state).
	EventTypeMCPConnectionFailed events.EventType = "mcp.connection.failed"

	// EventTypeMCPConnectionAuthRequired — emitted when an admin add of a NEW
	// MCP server connection requires authorization: the attach parks on the
	// unified pause/resume primitive (the tool-side OAuth lineage) and a
	// resume completes the attach. Carries the agent id, the server name, the
	// recording revision id, the pause token, and the author identity — never
	// a secret / credential / auth code.
	EventTypeMCPConnectionAuthRequired events.EventType = "mcp.connection.auth_required"
)

agent-config canonical event types. Registered via init() so the canonical events registry stays the single source of truth (register at declaration time, publish at use time).

Both payloads are SafePayload (compose events.SafeSealed): the agent id, revision ids, content hash, and author identity are operator-visible audit metadata, never secret-shaped. The payload carries NO config content (no skill names, no prompt text) — only the revision identity — so the audit trail never leaks the desired-state body (CLAUDE.md §7).

View Source
const DefaultDriver = "statestore"

DefaultDriver is the production driver name. The StateStore-backed driver registers under it; it inherits the StateStore's own driver triad (in-mem / SQLite / Postgres) for identity isolation.

Variables

View Source
var (
	// ErrIdentityRequired — a method was called with an incomplete
	// identity triple or an empty agent id. Fails closed (CLAUDE.md §6).
	ErrIdentityRequired = errors.New("agentcfg: identity triple incomplete")
	// ErrInvalidConfig — a factory was called with a missing mandatory
	// dependency (a nil StateStore or EventBus).
	ErrInvalidConfig = errors.New("agentcfg: invalid configuration")
	// ErrUnknownDriver — Open was asked for a driver name no registered
	// factory handles.
	ErrUnknownDriver = errors.New("agentcfg: unknown driver")
	// ErrClosed — a method was called after Close.
	ErrClosed = errors.New("agentcfg: registry is closed")
	// ErrRevisionNotFound — Get / Diff / Rollback referenced a revision
	// id that has no record. Fails loud (CLAUDE.md §13 — no silent drop).
	ErrRevisionNotFound = errors.New("agentcfg: revision not found")
	// ErrStateUnavailable — a StateStore read/write failed.
	ErrStateUnavailable = errors.New("agentcfg: state store unavailable")
	// ErrInvalidPayload — the supplied ConfigPayload failed validation.
	ErrInvalidPayload = errors.New("agentcfg: invalid config payload")
	// ErrReservedUser — a user-scoped call carried a verified user id equal
	// to the reserved internal sentinel ("__agentcfg__"); fails closed so the
	// per-user key space can never alias onto the agent-level chain.
	ErrReservedUser = errors.New("agentcfg: user id collides with the reserved internal slot")
)

Sentinel errors. Callers compare via errors.Is.

Functions

func ContentHash

func ContentHash(p ConfigPayload) (string, error)

ContentHash computes the full hex-encoded SHA-256 over the canonical (sorted-key) JSON encoding of the normalised payload. Computing over a canonical form means an unrelated re-ordering of a set does not change the hash, and the idempotent re-set check is exact.

func Register

func Register(name string, factory Factory)

Register installs a driver factory under name. Drivers self-register from their package init(); the production driver aggregator blank-imports them. Re-registering the same name panics — the registration model is write-once-at-init.

func RegisteredDrivers

func RegisteredDrivers() []string

RegisteredDrivers returns a sorted list of registered driver names.

Types

type Config

type Config struct {
	// Driver names the registered factory. Empty → DefaultDriver.
	Driver string
}

Config selects the agentcfg driver. The StateStore-backed driver takes its persistence from Deps.State and ignores any DSN — the registry reuses the runtime's StateStore rather than opening its own.

type ConfigPayload

type ConfigPayload struct {
	PromptLayers *PromptLayers       `json:"prompt_layers,omitempty"`
	ToolExposure *ToolExposure       `json:"tool_exposure,omitempty"`
	Skills       *SkillsSelection    `json:"skills,omitempty"`
	Connections  *ConnectionsSection `json:"connections,omitempty"`
	LLMParams    *LLMParams          `json:"llm_params,omitempty"`
}

ConfigPayload is the forward-compatible config envelope. Every section is an optional pointer so later consumers extend the envelope without a schema break; only Skills is wired in the first wave.

func NormalizePayload

func NormalizePayload(p ConfigPayload) ConfigPayload

NormalizePayload returns a defensive, canonicalised copy of payload: the skills membership and the tool-exposure sets (paused servers, disabled tools) are sorted and de-duplicated so a re-ordering does not perturb the content hash and the stored form is stable. The prompt-layer section is copied verbatim (no nested mutation). It is exported so consumers (the skills + tool-exposure services) and the driver share one canonical form.

func (ConfigPayload) BasePrompt

func (p ConfigPayload) BasePrompt() (string, bool)

BasePrompt returns the agent's base prompt layer from a payload and whether it is set. A nil prompt-layer section or a nil Base returns ("", false). A convenience for the layered-prompt run-start projection.

func (ConfigPayload) ConnectionDescriptors

func (p ConfigPayload) ConnectionDescriptors() []MCPConnectionDescriptor

ConnectionDescriptors returns the agent's runtime-added MCP connection descriptors from a payload, or nil when the payload pins no connections section. A convenience for the add-connection consumer + the diff.

func (ConfigPayload) DisabledTools

func (p ConfigPayload) DisabledTools() []string

DisabledTools returns the agent's disabled tool set from a payload, or nil when the payload pins no tool-exposure section.

func (ConfigPayload) LLMParamsView

func (p ConfigPayload) LLMParamsView() (*LLMParams, bool)

LLMParamsView returns the agent's per-agent LLM-parameter section from a payload and whether it is set. A nil section returns (nil, false). The returned pointer is the payload's own (read-only) section — callers that mutate must copy first.

func (ConfigPayload) PausedServers

func (p ConfigPayload) PausedServers() []string

PausedServers returns the agent's paused MCP server set from a payload, or nil when the payload pins no tool-exposure section. A convenience for the tool-exposure consumer + the run-start projection.

func (ConfigPayload) SkillNames

func (p ConfigPayload) SkillNames() []string

SkillNames returns the agent's active skills membership from a payload, or nil when the payload pins no skills section. A convenience for the skills consumer.

func (ConfigPayload) UserPrompt

func (p ConfigPayload) UserPrompt() (string, bool)

UserPrompt returns the agent's user prompt layer from a payload and whether it is set. A nil prompt-layer section or a nil User returns ("", false).

type ConfigRevertedPayload

type ConfigRevertedPayload struct {
	events.SafeSealed
	// Author is the identity that performed the rollback.
	Author identity.Quadruple
	// AgentID is the agent whose active pointer was repointed.
	AgentID string
	// RevisionID is the revision the active pointer now points to.
	RevisionID string
	// FromRevisionID is the previously-active revision id (empty when the
	// agent had no active pointer before the rollback).
	FromRevisionID string
	// OccurredAt is the rollback instant.
	OccurredAt time.Time
}

ConfigRevertedPayload is the typed payload for EventTypeConfigReverted. SafePayload — operator-visible audit metadata only.

type ConfigRevisedPayload

type ConfigRevisedPayload struct {
	events.SafeSealed
	// Author is the identity that wrote the revision.
	Author identity.Quadruple
	// AgentID is the agent whose config was revised (a registration
	// identity, NOT an isolation principal).
	AgentID string
	// RevisionID is the new revision's id.
	RevisionID string
	// ParentRevisionID is the revision the new one descends from (empty
	// for the first revision).
	ParentRevisionID string
	// ContentHash is the new revision's content hash (for diff/audit
	// correlation; never the content itself).
	ContentHash string
	// OccurredAt is the revision's creation instant.
	OccurredAt time.Time
}

ConfigRevisedPayload is the typed payload for EventTypeConfigRevised. SafePayload — every field is operator-visible audit metadata; no config content is carried.

type ConfigScope added in v1.6.0

type ConfigScope uint8

ConfigScope is the durable-config ownership discriminator. One Registry implementation serves two keyings: the admin/tenant durable config (keyed under a synthetic per-agent slot) and the per-user durable config variant (keyed under the caller's real (tenant, user) with the agent id as a key).

It is named with the ConfigScope prefix to disambiguate from the unrelated tools/auth.BindingScope constants (ScopeAgent / ScopeUser = OAuth token binding) and from the Protocol JWT scope auth.ScopeAgentConfigUser. The isolation tuple is never widened: the real user is the isolation principal for the user variant; the agent id stays a key, never a WHERE-clause isolation filter (RFC §6.16 / CLAUDE.md §6 clarifying note).

const (
	// ConfigScopeAgent is the admin/tenant durable config, keyed under the
	// synthetic per-agent identity slot and the agentcfg.* record kinds. The
	// default (zero value).
	ConfigScopeAgent ConfigScope = iota
	// ConfigScopeUser is the per-user durable config variant, keyed under the
	// caller's real (tenant, user) with the agent id in the session slot and a
	// DISTINCT agentcfg.user.* record-kind prefix. The distinct prefix is the
	// structural guarantee the two key spaces can never alias.
	ConfigScopeUser
)

type ConnectionsDiff

type ConnectionsDiff struct {
	// Added are the connection names present in the to-revision but not the
	// from-revision.
	Added []string
	// Removed are the connection names present in the from-revision but not
	// the to-revision.
	Removed []string
}

ConnectionsDiff is the structured set-diff of the runtime-added MCP connection descriptors across two revisions, by name. Deterministic: every slice is sorted.

func DiffConnections

func DiffConnections(from, to ConfigPayload) ConnectionsDiff

DiffConnections computes the structured set-diff (by name) of two connection states. Exported so the diff is one canonical implementation shared by the driver and tests.

func (ConnectionsDiff) Changed

func (d ConnectionsDiff) Changed() bool

Changed reports whether the connections set differs between the two revisions.

type ConnectionsSection

type ConnectionsSection struct {
	// Servers is the set of runtime-added MCP connection descriptors,
	// keyed by Name. Canonicalised sorted-by-name with a name-unique
	// invariant so a re-ordering does not perturb the content hash.
	Servers []MCPConnectionDescriptor `json:"servers,omitempty"`
}

ConnectionsSection is the runtime-added MCP-connection section of the config envelope: the set of NON-SECRET connection descriptors an admin has added over the control plane. Declared as its own section so an add REPLACES only this section, preserving Skills / ToolExposure / PromptLayers (the bidirectional section-merge invariant).

type Deps

type Deps struct {
	State state.StateStore
	Bus   events.EventBus
	Clock func() time.Time
}

Deps carries the runtime dependencies an agentcfg driver needs. State (the persistence floor) and Bus (the audit/observability bus) are mandatory; a nil either fails the factory loud with ErrInvalidConfig. Clock is optional (defaults to time.Now).

type Diff

type Diff struct {
	// FromRevisionID / ToRevisionID name the compared revisions.
	FromRevisionID string
	ToRevisionID   string
	// Skills is the structured set-diff of the skills membership.
	Skills SkillsDiff
	// ToolExposure is the structured set-diff of the MCP-exposure /
	// per-tool policy.
	ToolExposure ToolExposureDiff
	// PromptLayers is the text delta of the base + user prompt layers.
	PromptLayers PromptLayersDiff
	// Connections is the structured set-diff of the runtime-added MCP
	// connection descriptors (by name).
	Connections ConnectionsDiff
	// LLMParams is the per-field delta of the per-agent LLM-parameter
	// section (model / temperature / max-tokens / reasoning-effort).
	LLMParams LLMParamsDiff
}

Diff is the server-side compare of two revision payloads. The first wave carries the structured skills set-diff; later consumers add a text diff for the prompt layer and structured diffs for tool exposure.

type Factory

type Factory func(cfg Config, deps Deps) (Registry, error)

Factory builds a Registry from a Config + Deps. Drivers expose one Factory each via init() → Register.

type LLMParams

type LLMParams struct {
	// Model, when set, is the model the agent's next run requests
	// (overriding the tenant-wide baseline / config default). An empty
	// string normalises to unset.
	Model *string `json:"model,omitempty"`
	// Temperature, when set, is the sampling temperature for the next run.
	Temperature *float64 `json:"temperature,omitempty"`
	// MaxTokens, when set, is the per-message output-token ceiling.
	MaxTokens *int `json:"max_tokens,omitempty"`
	// ReasoningEffort, when set, is the reasoning-effort hint
	// ("off" | "low" | "medium" | "high"). An empty string normalises to
	// unset.
	ReasoningEffort *string `json:"reasoning_effort,omitempty"`
}

LLMParams pins an agent's sampling defaults as a versioned config section. Every field is pointer-optional: an unset field falls through to the next resolution layer (the tenant-wide baseline, then the config default) — the per-agent layer overrides ONLY the dimensions it sets. This is sampling parameters only; additive system-prompt text lives in PromptLayers (there is one home for prompt text).

type LLMParamsDiff

type LLMParamsDiff struct {
	ModelChanged bool
	ModelFrom    string
	ModelTo      string

	TemperatureChanged bool
	TemperatureFrom    string
	TemperatureTo      string

	MaxTokensChanged bool
	MaxTokensFrom    string
	MaxTokensTo      string

	ReasoningEffortChanged bool
	ReasoningEffortFrom    string
	ReasoningEffortTo      string
}

LLMParamsDiff is the per-field delta of the per-agent LLM-parameter section across two revisions. Each dimension reports whether it changed plus its from / to values (formatted for display; an unset dimension is the empty string). Deterministic.

func DiffLLMParams

func DiffLLMParams(from, to ConfigPayload) LLMParamsDiff

DiffLLMParams computes the per-field delta of two per-agent LLM-parameter states. Exported so the diff is one canonical implementation shared by the driver and tests. An unset dimension is compared as the empty string; numeric dimensions are formatted canonically (so 0.7 vs unset registers a change to/from "").

func (LLMParamsDiff) Changed

func (d LLMParamsDiff) Changed() bool

Changed reports whether any LLM-parameter dimension differs between the two revisions.

type MCPConnectionDescriptor

type MCPConnectionDescriptor struct {
	// Name is the unique MCP source id (the tool-name prefix the planner
	// sees). Required.
	Name string `json:"name"`
	// Transport is the wire transport — "stdio" or "http".
	Transport MCPTransport `json:"transport"`
	// Command is the stdio argv (argv[0] is the binary; no shell). Set for
	// the stdio transport; empty for http.
	Command []string `json:"command,omitempty"`
	// URL is the http(s) endpoint. Set for the http transport; empty for
	// stdio.
	URL string `json:"url,omitempty"`
}

MCPConnectionDescriptor is the NON-SECRET shape of one runtime-added MCP server connection, recorded in a config revision so the connection is part of the agent's versioned desired state (diff / rollback). It carries ONLY the non-secret descriptor — the server name, the transport, and the stdio argv command or the http URL. Secret auth material (bearer headers, OAuth tokens, credentials) is NEVER part of this descriptor: it flows through the live attach + the tool-side OAuth / pause-resume path and is never persisted in a revision, a diff, or an event (CLAUDE.md §7).

type MCPConnectionLifecyclePayload

type MCPConnectionLifecyclePayload struct {
	events.SafeSealed
	// Author is the identity that drove the add.
	Author identity.Quadruple
	// AgentID is the agent the connection was added to (a registration
	// identity, NOT an isolation principal).
	AgentID string
	// ServerID is the MCP source id (name) of the connection being added.
	ServerID string
	// Transport is the connection transport ("stdio" / "http") — non-secret.
	Transport string
	// State is the lifecycle state the event marks ("pending" / "online" /
	// "failed" / "auth_required").
	State string
	// RevisionID is the recording revision id (set for online / auth_required;
	// empty for pending and for a failed add, which records no revision).
	RevisionID string
	// PauseToken is the unified-pause/resume token the auth_required attach
	// parked on (set only for the auth_required state); empty otherwise. It
	// is an opaque runtime handle, NOT a credential.
	PauseToken string
	// Reason is a SAFE, operator-facing failure reason (set only for the
	// failed state); never a secret or raw transport payload.
	Reason string
	// OccurredAt is the lifecycle-transition instant.
	OccurredAt time.Time
}

MCPConnectionLifecyclePayload is the typed payload for the runtime MCP-attach lifecycle events (pending / added / failed / auth_required). SafePayload — every field is operator-visible audit metadata; NO secret header / token / credential / auth code is ever carried (CLAUDE.md §7).

type MCPConnectionPausedPayload

type MCPConnectionPausedPayload struct {
	events.SafeSealed
	// Author is the identity that recorded the pause.
	Author identity.Quadruple
	// AgentID is the agent whose MCP exposure changed (a registration
	// identity, NOT an isolation principal).
	AgentID string
	// ServerID is the MCP source id newly paused.
	ServerID string
	// RevisionID is the tool-exposure revision that recorded the pause.
	RevisionID string
	// OccurredAt is the pause instant.
	OccurredAt time.Time
}

MCPConnectionPausedPayload is the typed payload for EventTypeMCPConnectionPaused. SafePayload — every field is operator-visible audit metadata; no secret-shaped content is carried.

type MCPConnectionResumedPayload

type MCPConnectionResumedPayload struct {
	events.SafeSealed
	// Author is the identity that recorded the resume.
	Author identity.Quadruple
	// AgentID is the agent whose MCP exposure changed.
	AgentID string
	// ServerID is the MCP source id newly resumed.
	ServerID string
	// RevisionID is the tool-exposure revision that recorded the resume.
	RevisionID string
	// OccurredAt is the resume instant.
	OccurredAt time.Time
}

MCPConnectionResumedPayload is the typed payload for EventTypeMCPConnectionResumed. SafePayload — operator-visible audit metadata only.

type MCPTransport

type MCPTransport string

MCPTransport is the closed set of transports a runtime-added MCP connection descriptor may declare. The control-plane add path supports MCP over stdio (an operator-supplied argv command) and http (a URL); other transports are out of scope for the runtime add.

const (
	// MCPTransportStdio — the server is an operator-supplied subprocess,
	// launched argv-form (NEVER via a shell). The most privileged add (an
	// RCE surface) — allowlist-gated at the control-plane edge.
	MCPTransportStdio MCPTransport = "stdio"
	// MCPTransportHTTP — the server is reachable over an HTTP(S) endpoint.
	MCPTransportHTTP MCPTransport = "http"
)

The canonical runtime-add MCP transports.

type PromptLayers

type PromptLayers struct {
	// Base is the admin-owned, versioned base prompt layer. When set it is
	// the run's base system prompt (overriding the agent's configured
	// default base); unset inherits the configured default.
	Base *string `json:"base,omitempty"`
	// User is the optional higher user-instruction layer that composes
	// ABOVE the base without mutating it (the composition order is the
	// security boundary — the agent-config authorization model).
	User *string `json:"user,omitempty"`
}

PromptLayers is the prompt-layer section of the config envelope: an operator-owned, versioned base prompt layer plus an optional user layer that composes ABOVE the base without mutating it. The composition order is the structural security boundary — because Base and User are distinct fields and the user layer is always appended below the base, a writer of only User can extend the operator's guidance but can never precede, replace, or weaken the operator base.

type PromptLayersDiff

type PromptLayersDiff struct {
	// BaseChanged reports whether the base layer text differs.
	BaseChanged bool
	// BaseFrom / BaseTo are the base layer text in the from / to revision.
	BaseFrom string
	BaseTo   string
	// UserChanged reports whether the user layer text differs.
	UserChanged bool
	// UserFrom / UserTo are the user layer text in the from / to revision.
	UserFrom string
	UserTo   string
}

PromptLayersDiff is the text delta of the base + user prompt layers across two revisions. An unset layer compares as the empty string, so a set→unset change registers as a change to "".

func DiffPromptLayers

func DiffPromptLayers(from, to ConfigPayload) PromptLayersDiff

DiffPromptLayers computes the text delta of two prompt-layer states. Exported so the diff is one canonical implementation shared by the driver and tests. An unset layer is compared as the empty string.

func (PromptLayersDiff) Changed

func (d PromptLayersDiff) Changed() bool

Changed reports whether either prompt layer differs between the two revisions.

type Registry

type Registry interface {
	// SetRevision writes a NEW immutable revision pinning payload and
	// advances the active pointer to it. An idempotent re-set of
	// byte-identical canonical content (relative to the current active
	// revision) is a no-op that returns the existing active revision.
	SetRevision(ctx context.Context, id identity.Quadruple, agentID string, scope ConfigScope, payload ConfigPayload) (Revision, error)
	// Active returns the agent's current active revision and whether one
	// exists. No active pointer returns (zero, false, nil).
	Active(ctx context.Context, id identity.Quadruple, agentID string, scope ConfigScope) (Revision, bool, error)
	// Get returns the revision identified by revisionID. A missing
	// revision fails loud with ErrRevisionNotFound.
	Get(ctx context.Context, id identity.Quadruple, agentID, revisionID string, scope ConfigScope) (Revision, error)
	// ListRevisions returns the agent's revision chain newest-first,
	// capped at limit (0 = no cap). Enumeration uses the elevated
	// maintenance scan and filters to the agent's identity slot.
	ListRevisions(ctx context.Context, id identity.Quadruple, agentID string, scope ConfigScope, limit int) ([]Revision, error)
	// Rollback writes a new active pointer to an existing revision
	// WITHOUT mutating or deleting any revision. A missing target fails
	// loud with ErrRevisionNotFound.
	Rollback(ctx context.Context, id identity.Quadruple, agentID, revisionID string, scope ConfigScope) (Revision, error)
	// Diff returns the deterministic compare of two existing revisions.
	Diff(ctx context.Context, id identity.Quadruple, agentID, fromRev, toRev string, scope ConfigScope) (Diff, error)
	// Close releases resources. Idempotent.
	Close(ctx context.Context) error
}

Registry is the durable, identity-scoped, versioned desired-state store. It is a compiled artifact: immutable after construction and safe for concurrent reuse (the concurrent-reuse contract).

func Open

func Open(_ context.Context, cfg Config, deps Deps) (Registry, error)

Open returns the Registry built by the factory whose name matches cfg.Driver (defaults to DefaultDriver when empty). Deps are validated: a missing StateStore or EventBus returns a wrapped ErrInvalidConfig before the factory runs — fail loudly, never silently degrade.

type Revision

type Revision struct {
	// RevisionID is the unique, time-ordered id of this revision.
	RevisionID string
	// ParentRevisionID is the revision this one descends from (the
	// previously-active revision). Empty for the first revision.
	ParentRevisionID string
	// ContentHash is the full hex-encoded SHA-256 over the revision's
	// canonical (sorted-key) payload encoding.
	ContentHash string
	// Author is the identity that wrote the revision (the audit anchor).
	Author identity.Quadruple
	// CreatedAt is the revision's creation instant (UTC).
	CreatedAt time.Time
	// Payload is the config envelope this revision pins.
	Payload ConfigPayload
}

Revision is an immutable, content-addressed agent-config record with a parent pointer. SetRevision never mutates an existing Revision; it writes a new one and advances the active pointer.

type SkillsDiff

type SkillsDiff struct {
	// Added are the skill names present in the to-revision but not the
	// from-revision.
	Added []string
	// Removed are the skill names present in the from-revision but not
	// the to-revision.
	Removed []string
}

SkillsDiff is the structured set-diff of the skills membership across two revisions. Deterministic: Added / Removed are sorted.

func DiffSkills

func DiffSkills(from, to []string) SkillsDiff

DiffSkills computes the structured set-diff of two skills memberships. Exported so the diff is one canonical implementation shared by the driver and tests.

func (SkillsDiff) Changed

func (d SkillsDiff) Changed() bool

Changed reports whether the skills membership differs between the two revisions.

type SkillsSelection

type SkillsSelection struct {
	// Names is the set of skill names active for the agent in this
	// revision. Order is not significant — the content hash is computed
	// over a canonical sorted, de-duplicated form so a re-ordering does
	// not perturb the hash.
	Names []string `json:"names"`
}

SkillsSelection is the membership set of skill names active for an agent in a revision. The revision records skill MEMBERSHIP (names), never skill bodies — the bodies stay in the SkillStore. Resolved at run start; applied next-turn.

type ToolExposure

type ToolExposure struct {
	// PausedServers names MCP servers excluded from the next run's
	// projection (resume is a flag flip, not a re-dial).
	PausedServers []string `json:"paused_servers,omitempty"`
	// DisabledTools names tools the per-tool policy excludes.
	DisabledTools []string `json:"disabled_tools,omitempty"`
}

ToolExposure is the forward-compatible tool/MCP-exposure section of the config envelope. Reserved for the MCP pause / per-tool policy consumer; declared now so the envelope evolves without a schema break. Not wired in the first wave.

type ToolExposureDiff

type ToolExposureDiff struct {
	// PausedAdded / PausedResumed are the MCP servers newly paused / newly
	// resumed (present-in-to-but-not-from / present-in-from-but-not-to).
	PausedAdded   []string
	PausedResumed []string
	// DisabledAdded / DisabledEnabled are the tools newly disabled / newly
	// re-enabled.
	DisabledAdded   []string
	DisabledEnabled []string
}

ToolExposureDiff is the structured set-diff of the MCP-exposure / per-tool policy across two revisions. Deterministic: every slice is sorted.

func DiffToolExposure

func DiffToolExposure(from, to ConfigPayload) ToolExposureDiff

DiffToolExposure computes the structured set-diff of two tool-exposure states. Exported so the diff is one canonical implementation shared by the driver and tests.

func (ToolExposureDiff) Changed

func (d ToolExposureDiff) Changed() bool

Changed reports whether the tool exposure differs between the two revisions.

Directories

Path Synopsis
Package conformance is the shared agentcfg.Registry driver conformance suite: a single set of behaviour assertions every driver must pass, so a future driver inherits the contract verbatim (the §11 conformance-suite pattern).
Package conformance is the shared agentcfg.Registry driver conformance suite: a single set of behaviour assertions every driver must pass, so a future driver inherits the contract verbatim (the §11 conformance-suite pattern).
drivers
statestore
Package statestore implements the StateStore-backed agentcfg Registry driver — the default driver for the agent-config control plane.
Package statestore implements the StateStore-backed agentcfg Registry driver — the default driver for the agent-config control plane.
Package sessionoverlay owns the SESSION-scoped safe-subset overlay of the agent-config control plane: the lower tier of the authorization matrix.
Package sessionoverlay owns the SESSION-scoped safe-subset overlay of the agent-config control plane: the lower tier of the authorization matrix.

Jump to

Keyboard shortcuts

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