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
- Variables
- func CheckExpectedRevision(opts SetOptions, active Revision, hasActive bool) error
- func ContentHash(p ConfigPayload) (string, error)
- func MCPConnectionFingerprint(d MCPConnectionDescriptor) string
- func MCPReattachFailureClasses() []string
- func Register(name string, factory Factory)
- func RegisteredDrivers() []string
- type Config
- type ConfigPayload
- func (p ConfigPayload) BasePrompt() (string, bool)
- func (p ConfigPayload) ConnectionDescriptors() []MCPConnectionDescriptor
- func (p ConfigPayload) DisabledTools() []string
- func (p ConfigPayload) ExtraSystemBlockList() []NamedBlock
- func (p ConfigPayload) LLMParamsView() (*LLMParams, bool)
- func (p ConfigPayload) NamingView() (*NamingSection, bool)
- func (p ConfigPayload) OAuthProviderDescriptors() []OAuthProviderDescriptor
- func (p ConfigPayload) PausedServers() []string
- func (p ConfigPayload) RunCompletionHookView() (*RunCompletionHook, bool)
- func (p ConfigPayload) ServerLoadingModes() map[string]string
- func (p ConfigPayload) SkillNames() []string
- func (p ConfigPayload) ToolLoadingModes() map[string]string
- func (p ConfigPayload) UserPrompt() (string, bool)
- type ConfigRevertedPayload
- type ConfigRevisedPayload
- type ConfigScope
- type ConnectionsDiff
- type ConnectionsSection
- type Deps
- type Diff
- type ExtraSystemBlocks
- type ExtraSystemBlocksDiff
- type Factory
- type HooksDiff
- type HooksSection
- type LLMParams
- type LLMParamsDiff
- type LLMProviderDescriptor
- type LLMProviderSetPayload
- type LoadingModeChange
- type MCPConnectionDescriptor
- type MCPConnectionLifecyclePayload
- type MCPConnectionPausedPayload
- type MCPConnectionRemovedPayload
- type MCPConnectionResumedPayload
- type MCPCredentialInjectionDescriptor
- type MCPDiscoveryOriginsSetPayload
- type MCPTransport
- type NamedBlock
- type NamingDiff
- type NamingSection
- type OAuthProviderDescriptor
- type OAuthProviderSetPayload
- type OAuthProvidersDiff
- type OAuthProvidersSection
- type PromptLayers
- type PromptLayersDiff
- type Registry
- type Revision
- type RunCompletionHook
- type SetOptions
- type SkillsDiff
- type SkillsSelection
- type ToolExposure
- type ToolExposureDiff
Constants ¶
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" // EventTypeMCPConnectionRemoved — emitted when an admin removes a // runtime-added MCP server connection (agent_config.remove_mcp_connection): // a new revision drops the named descriptor and prunes that server's // tool-exposure residue. The physical teardown (deregister the server's // tools + close its transport) happens at the NEXT run's projection // boundary — this event marks the desired-state removal, not the transport // close. Carries the agent id, the removed server id, the recording // revision id, and the author identity — never a secret. EventTypeMCPConnectionRemoved events.EventType = "mcp.connection.removed" // EventTypeMCPDiscoveryOriginsSet — emitted when an admin FULL-REPLACES a // runtime-added MCP connection's OAuth-discovery cross-origin allow-list // (agent_config.set_mcp_discovery_origins). Carries the agent id, the // connection id, the recording revision id, and the granted / revoked origin // deltas — all NON-SECRET (public https origins are an allow-list, never a // credential). This is the admin-scope audit event the write emits as one // fail-closed unit with the mutation (CLAUDE.md §7). EventTypeMCPDiscoveryOriginsSet events.EventType = "mcp.connection.discovery_origins_set" // EventTypeOAuthProviderInstalled — emitted when an admin installs (upserts) // a Protocol-installed OAuth provider (agent_config.set_oauth_provider): a // new revision records the ZERO-URL descriptor AND the provider is installed // live into the owner-tagged provider set. Carries the agent id, the provider // name, the credential-broker name, the recording revision id, and the author // identity — all NON-SECRET. NO URL, NO env-var name, NO secret is ever // carried (there is none on the descriptor). Emitted as one fail-closed unit // with the mutation (CLAUDE.md §7). EventTypeOAuthProviderInstalled events.EventType = "agent_config.oauth_provider.installed" // EventTypeOAuthProviderRemoved — emitted when an admin uninstalls a // Protocol-installed OAuth provider (agent_config.remove_oauth_provider): a // new revision drops the descriptor AND the provider is uninstalled live // (CLOSED). Carries the agent id, the provider name, the recording revision // id, and the author identity — all NON-SECRET. Emitted as one fail-closed // unit with the mutation. EventTypeOAuthProviderRemoved events.EventType = "agent_config.oauth_provider.removed" // EventTypeMCPConnectionReattached — emitted when the RUN-START attach leg // re-establishes a runtime-added MCP connection the reconciling owner's // active config revision DECLARES but the live registry did not carry (a // fresh process on the same state store, or a rollback that re-declares a // previously-removed connection). It is deliberately NOT // EventTypeMCPConnectionAdded: that type's godoc binds it to an admin add, // and a reconcile has no admin request. A consumer also distinguishes the // two families structurally — an admin add's Author quadruple carries an // EMPTY RunID, a reconcile's carries the reconciling run's. Payload: // MCPConnectionLifecyclePayload with State "online"; never a secret. EventTypeMCPConnectionReattached events.EventType = "mcp.connection.reattached" // EventTypeMCPConnectionReattachFailed — emitted when the run-start attach // leg could NOT re-establish a DECLARED connection. The run is never failed // by it and the sweep is never aborted, but the shortfall is never silent // either: the outcome is REPORTED with a stable class so an operator surface // can tell "unreachable third party" from "refused by current boot policy". // Payload: MCPConnectionLifecyclePayload, where State carries the stable // class (one of the MCPReattachClass* constants) and Reason carries the // scrubbed, length-bounded operator-facing reason. Never a secret. EventTypeMCPConnectionReattachFailed events.EventType = "mcp.connection.reattach_failed" // EventTypeLLMProviderInstalled — emitted when an admin installs (upserts) // / rotates a Protocol-installed, ZERO-URL inference provider binding // (agent_config.set_llm_provider): the binding is installed live into the // owner-tagged provider set so the runtime's LLM key is sourced from the // named coordinator broker. Carries the agent id, the binding name, the // provider, the inference-broker name, and the author identity — all // NON-SECRET. NO URL, NO env-var name, NO secret is ever carried (there is // none on the descriptor). Emitted as one fail-closed unit with the // mutation (CLAUDE.md §7). EventTypeLLMProviderInstalled events.EventType = "agent_config.llm_provider.installed" )
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).
const ( // MCPReattachClassTransportFailed — the dial, the initialize handshake, or // discovery failed. This is also the class a connection whose live transport // depended on operator-supplied static auth headers lands in: those headers // are secret and never persisted, so the re-attach dials without them and a // server that required them answers 401. RETRYABLE. MCPReattachClassTransportFailed = "transport_failed" // MCPReattachClassStdioNotAllowed — the declared stdio descriptor's argv[0] // is absent from the CURRENT boot stdio allowlist. The revision was written // while the command was allowlisted; boot policy has since tightened (or the // allowlist is empty, which refuses every stdio re-attach). Never spawned. MCPReattachClassStdioNotAllowed = "stdio_not_allowed" // MCPReattachClassInjectionDisabled — the declared descriptor carries a // per-user credential-injection mapping but the fail-closed // `tools.allow_wire_injection` opt-in is OFF. The dev opt-in is a // kill-switch: a mapping persisted while it was on is not rebuilt after a // restart with it off. MCPReattachClassInjectionDisabled = "injection_disabled" // MCPReattachClassOAuthBinding — the descriptor's `oauth_provider` (or // injection broker) NAME does not resolve, or the connection host is absent // from the provider's boot-declared downstream-sink allow-list. A NAME // resolution and an allow-list check only — no token participates. MCPReattachClassOAuthBinding = "oauth_binding" // MCPReattachClassOwnerConflict — the declared name is already live in the // registry under a DIFFERENT (tenant, agent) owner. The re-attach is refused // rather than evicting another owner's transport and tools. Only that owner's // detach or a rename clears it. MCPReattachClassOwnerConflict = "owner_conflict" // MCPReattachClassAmbiguousServerID — the declared name would make an // already-registered server's `<name>_<tool>` ids ambiguous. A naming // collision an operator must resolve. MCPReattachClassAmbiguousServerID = "ambiguous_server_id" )
The CLOSED set of run-start re-attach failure classes carried in MCPConnectionLifecyclePayload.State on EventTypeMCPConnectionReattachFailed. They live here, next to the event type, because they are part of the observable contract an operator surface reads — not an implementation detail of the runtime glue that emits them. Every class is non-secret and stable; adding one is an additive contract change, renaming one is breaking.
The split that matters to an operator: MCPReattachClassTransportFailed means "the third party did not answer" (retryable — the leg re-dials on a bounded backoff), every other class means "current boot policy or a live-registry collision refuses this descriptor" (NOT retryable by re-dialling — it is emitted once per attempted descriptor and only an operator action clears it).
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.
const ExpectNoActiveRevision = "-"
ExpectNoActiveRevision is the reserved SetOptions.ExpectedContentHash value meaning "I read this agent BEFORE it had any config, and I expect it STILL to have none." It succeeds only when the agent has no active revision, and is refused with ErrRevisionConflict the moment any revision exists.
Why a sentinel exists at all ¶
The composition protocol the expected-revision token serves is: read, modify, write back with the read revision's content hash, so a concurrent sibling's write is refused rather than silently reverted. That protocol had no expressible form at its OWN base case. On an agent with no config, `agent_config.get` answers `set:false` with no hash to echo, and every non-empty token was refused — so the only token a first contributor could send was the empty one, which means "unconditional". Two contributors composing onto a fresh agent therefore BOTH wrote unconditionally and the second silently reverted the first: exactly the lost update the token exists to prevent, on the one write where a caller had no way to opt out.
Why this value ¶
A content hash is ContentHash's output: exactly 64 lowercase hex characters. "-" is not a possible hash, so the sentinel can never collide with a real expectation no matter what payload is written — the property a sentinel living inside a hash-shaped field must have, and it is asserted by a test rather than argued.
Returning a zero-state token from the READ instead was considered and rejected: it changes `agent_config.get`'s response shape (a new field on every read, mirrored into the Console client and the generated reference) to carry a value that would still have to be a reserved non-hash string — the same sentinel, plus a wire-shape change, plus a second place for it to drift.
It is ADDITIVE. An absent token is still the unconditional write, and a 64-hex token still behaves exactly as it did.
Variables ¶
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 = 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") // ErrRevisionConflict — a conditional write declared an expected // content hash (SetOptions.ExpectedContentHash) and the agent's active // revision no longer carries it, or there is no active revision at all. // NOTHING is persisted: no revision record, no active-pointer move, no // emitted event. The caller re-reads the active revision and retries. ErrRevisionConflict = errors.New("agentcfg: revision conflict") )
Sentinel errors. Callers compare via errors.Is.
Functions ¶
func CheckExpectedRevision ¶ added in v1.25.0
func CheckExpectedRevision(opts SetOptions, active Revision, hasActive bool) error
CheckExpectedRevision evaluates opts against an active-revision snapshot. Persistence drivers use it at the authoritative write boundary. Protocol services also use it before a non-transactional side effect; that earlier check is an ordering guard and never replaces the driver's second check.
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 MCPConnectionFingerprint ¶ added in v1.25.0
func MCPConnectionFingerprint(d MCPConnectionDescriptor) string
MCPConnectionFingerprint returns the stable SHA-256 digest of one connection descriptor's canonical, NON-SECRET representation. It uses the same normalizer as persisted ConfigPayload values, so semantically identical descriptors compare equal across control writes, restart reconciliation and live registry publication.
func MCPReattachFailureClasses ¶ added in v1.24.0
func MCPReattachFailureClasses() []string
MCPReattachFailureClasses is the closed class set as a slice, so a consumer (and the phase's report guard) can enumerate it rather than re-listing it.
func Register ¶
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"`
OAuthProviders *OAuthProvidersSection `json:"oauth_providers,omitempty"`
LLMParams *LLMParams `json:"llm_params,omitempty"`
Hooks *HooksSection `json:"hooks,omitempty"`
Naming *NamingSection `json:"naming,omitempty"`
// ExtraSystemBlocks, when non-nil, pins the agent's ORDERED list of
// named additive prompt blocks. Absent (nil) contributes nothing and
// leaves the system prompt byte-identical.
ExtraSystemBlocks *ExtraSystemBlocks `json:"extra_system_blocks,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) ExtraSystemBlockList ¶ added in v1.25.0
func (p ConfigPayload) ExtraSystemBlockList() []NamedBlock
ExtraSystemBlockList returns the agent's ordered additive prompt blocks from a payload, or nil when the payload pins no blocks section. The returned slice is the payload's own (read-only) backing array — callers that mutate must copy first. A convenience for the run-start projection and the diff.
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) NamingView ¶ added in v1.12.0
func (p ConfigPayload) NamingView() (*NamingSection, bool)
NamingView returns the agent's session auto-naming 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. A convenience for the auto-naming run-start projection.
func (ConfigPayload) OAuthProviderDescriptors ¶ added in v1.14.0
func (p ConfigPayload) OAuthProviderDescriptors() []OAuthProviderDescriptor
OAuthProviderDescriptors returns the installed OAuth-provider descriptors from a payload, or nil when the payload pins no OAuth-providers section. A convenience for the install/uninstall consumer, the reconcile leg, and the diff.
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) RunCompletionHookView ¶ added in v1.10.0
func (p ConfigPayload) RunCompletionHookView() (*RunCompletionHook, bool)
RunCompletionHookView returns the agent's run-completion hook from a payload and whether it is set. A nil hooks section or a nil RunCompletion returns (nil, false). The returned pointer is the payload's own (read-only) section — callers that mutate must copy first. A convenience for the run-completion-hook run-start projection.
func (ConfigPayload) ServerLoadingModes ¶ added in v1.10.0
func (p ConfigPayload) ServerLoadingModes() map[string]string
ServerLoadingModes returns the agent's per-server loading-mode override map 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) ToolLoadingModes ¶ added in v1.10.0
func (p ConfigPayload) ToolLoadingModes() map[string]string
ToolLoadingModes returns the agent's per-tool loading-mode override map from a payload, or nil when the payload pins no tool-exposure section.
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 ¶
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
// OAuthProviders is the structured set-diff of the Protocol-installed
// OAuth-provider descriptors (by name).
OAuthProviders OAuthProvidersDiff
// LLMParams is the per-field delta of the per-agent LLM-parameter
// section (model / temperature / max-tokens / reasoning-effort).
LLMParams LLMParamsDiff
// Hooks is the per-field delta of the run-lifecycle-hook section
// (the run-completion hook's tool + timeout).
Hooks HooksDiff
// Naming is the per-field delta of the session auto-naming policy
// section.
Naming NamingDiff
// ExtraSystemBlocks is the structured delta of the ordered additive
// prompt blocks (added / removed / body-changed by name, plus the
// order-only reorder flag).
ExtraSystemBlocks ExtraSystemBlocksDiff
}
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 ExtraSystemBlocks ¶ added in v1.25.0
type ExtraSystemBlocks struct {
// Blocks is the ordered list. A slice, never a map: map iteration order
// is not a composition order.
Blocks []NamedBlock `json:"blocks"`
}
ExtraSystemBlocks is the ORDERED list of named, operator-authored additive prompt blocks pinned by a config revision. It exists so N independent capability sources can each contribute — and later remove — exactly their own text, without any of them having to re-derive the others' contributions from prose.
Order is SEMANTIC ¶
The declared slice order IS the render order, so the canonical form PRESERVES it and a re-ordering is a real new revision with a different ContentHash and a visible diff. This is the deliberate asymmetry with SkillsSelection.Names (sortDedup'd) and OAuthProvidersSection.Providers (sorted by name): for those, order is not semantic and a re-ordering must NOT perturb the hash. Sorting blocks would silently re-order an operator's prompt and hide the change from the diff.
Trust — argued from the write door ¶
The section has exactly ONE write door, and it sits in the admin method set — the same tier that writes PromptLayers.Base, which is already rendered verbatim and is strictly more powerful (it is the whole spine). Blocks therefore render VERBATIM, unescaped, each preceded by a plain-text `[name]` label. Contrast PromptLayers.User, which IS escaped precisely because a claim-free session path can write it.
The obligation this creates, stated rather than engineered away: ESCAPING IS NOT THE BOUNDARY HERE — the write door's authority tier is. A capability that wants to surface user-authored or model-authored text MUST NOT put it in a block; it uses the UNTRUSTED-framed memory tiers or PromptLayers.User instead.
type ExtraSystemBlocksDiff ¶ added in v1.25.0
type ExtraSystemBlocksDiff struct {
// Added are the block names present only in the to-revision.
Added []string
// Removed are the block names present only in the from-revision.
Removed []string
// Changed are the names present in both whose BODY differs.
Changed []string
// Reordered reports that the two revisions carry the SAME name set in a
// DIFFERENT order. Order is render order, so a pure re-ordering is a
// real prompt change and must be visible in the diff.
Reordered bool
}
ExtraSystemBlocksDiff is the structured delta of the additive prompt blocks across two revisions. Added / Removed / Changed are sorted so the diff is deterministic; Reordered is the ORDER-only signal that has no analogue on the sorted sibling sections, and it is the reason the normalizer must not sort.
func DiffExtraSystemBlocks ¶ added in v1.25.0
func DiffExtraSystemBlocks(from, to ConfigPayload) ExtraSystemBlocksDiff
DiffExtraSystemBlocks computes the structured delta of two block sections. Exported so the diff is one canonical implementation shared by the driver and tests. An absent section compares as an empty list.
func (ExtraSystemBlocksDiff) HasChanges ¶ added in v1.25.0
func (d ExtraSystemBlocksDiff) HasChanges() bool
Changed reports whether the blocks section differs between the two revisions, including an order-only change.
type Factory ¶
Factory builds a Registry from a Config + Deps. Drivers expose one Factory each via init() → Register.
type HooksDiff ¶ added in v1.10.0
type HooksDiff struct {
// SectionPresentChanged reports whether the hooks-section PRESENCE differs
// (absent vs present). A present-but-empty section (the explicit per-agent
// no-hook) renders no tool and no timeout, so WITHOUT this dimension
// a yaml-hook-on agent toggling to an explicit `{}` opt-out would be an
// invisible revision in agent_config.diff (a phantom revision in the
// Console diff view). Mirrors NamingDiff's tri-state Auto. Present renders
// "present"; absent renders "".
SectionPresentChanged bool
SectionPresentFrom string
SectionPresentTo string
// RunCompletionToolChanged reports whether the hook's target tool differs.
RunCompletionToolChanged bool
RunCompletionToolFrom string
RunCompletionToolTo string
// RunCompletionTimeoutChanged reports whether the hook's timeout differs.
RunCompletionTimeoutChanged bool
RunCompletionTimeoutFrom string
RunCompletionTimeoutTo string
}
HooksDiff is the per-field delta of the run-lifecycle-hook section across two revisions. Reports whether the run-completion hook's tool / timeout changed plus their from / to display values (an unset hook renders "").
func DiffHooks ¶ added in v1.10.0
func DiffHooks(from, to ConfigPayload) HooksDiff
DiffHooks computes the per-field delta of two run-lifecycle-hook states. Exported so the diff is one canonical implementation shared by the driver and tests. An ABSENT section renders no presence + empty tool/timeout; a PRESENT-but-empty section (explicit no-hook) renders presence "present" with empty tool/timeout — so absent→`{}` (and its inverse) registers as a change even though tool and timeout are empty on both sides.
type HooksSection ¶ added in v1.10.0
type HooksSection struct {
// RunCompletion pins the agent's run-completion hook when non-nil with a
// non-empty tool. Nil in a PRESENT section is the explicit no-hook.
RunCompletion *RunCompletionHook `json:"run_completion,omitempty"`
}
HooksSection is the run-lifecycle-hook section of the config envelope. Declared as its own section so a set REPLACES only this section, preserving the sibling sections (the section-merge invariant).
Section PRESENCE is authoritative (mirrors NamingSection): a NIL section means "no per-agent hook policy" (the yaml `runtime.hooks.run_completion` fleet default, then no hook, resolves at run start). A PRESENT section with a non-nil RunCompletion (non-empty tool) pins the agent's hook; a PRESENT section with a nil / empty-tool RunCompletion is an explicit per-agent NO-HOOK that OVERRIDES a yaml-on fleet default — normalization preserves any non-nil section (never an inert-drop).
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 LLMProviderDescriptor ¶ added in v1.17.0
type LLMProviderDescriptor struct {
// Name is the unique provider-binding name. Required.
Name string `json:"name"`
// Provider is the LLM provider the pulled key authenticates (e.g.
// "openai"). Required.
Provider string `json:"provider"`
// CredentialSource is validated to be exactly "remote" (broker-pull).
// Required.
CredentialSource string `json:"credential_source"`
// InferenceBroker names a boot-declared inference broker that pins every
// credential sink. Required; an unknown name fails loud. NON-SECRET.
InferenceBroker string `json:"inference_broker"`
// ModelAllow is the optional model-name allowlist. NON-SECRET.
ModelAllow []string `json:"model_allow,omitempty"`
}
LLMProviderDescriptor is the domain shape of one Protocol-installed, ZERO-URL inference provider binding — the transport shape the inference-plane provider installer seam consumes. It carries NO URL and NO env-var name: every sink-determining value lives on the boot-declared inference broker it references by non-secret name (the credential-plane invariant). Distinct from OAuthProviderDescriptor: a different credential plane (an LLM provider KEY, not an OAuth client credential).
type LLMProviderSetPayload ¶ added in v1.17.0
type LLMProviderSetPayload struct {
events.SafeSealed
// Author is the identity that performed the install / rotate.
Author identity.Quadruple
// AgentID is the agent whose installed inference-provider binding changed
// (a registration identity, NOT an isolation principal).
AgentID string
// ProviderName is the installed binding name.
ProviderName string
// Provider is the LLM provider the pulled key authenticates.
Provider string
// InferenceBroker is the boot-declared broker the binding references by
// name. NON-SECRET.
InferenceBroker string
// OccurredAt is the write instant.
OccurredAt time.Time
}
LLMProviderSetPayload is the typed payload for the Protocol-installed inference-provider install / rotate audit event. SafePayload — every field is operator-visible audit metadata; NO URL, NO env-var name, NO secret is ever carried (there is none on the zero-URL descriptor). The inference-broker name is a non-secret boot reference.
type LoadingModeChange ¶ added in v1.10.0
LoadingModeChange is one entry in a loading-mode override diff: the override at Key (a catalog name for a ToolLoadingChanges entry, a ToolSourceID for a ServerLoadingChanges entry) changed from From to To. An empty From/To means the override was absent (unset) on that side of the compare — a set→unset or unset→set transition still registers as a change.
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"`
// OAuthProvider names a declared OAuth provider to bind for per-identity
// southbound bearer injection on this connection's calls. NON-SECRET — a
// provider NAME selecting a config-declared acquisition strategy; the
// secret stays on the provider. Empty leaves the connection on its static
// (attach-time) headers. Set only for the http transport.
OAuthProvider string `json:"oauth_provider,omitempty"`
// MetaAnnotations is a static, NON-SECRET set of operator-declared
// key/values merged into the MCP `_meta` on every identity-stamped
// per-call RPC (the deployment's attribution vocabulary). Each key is a
// `_meta` PATH — a dotted key NESTS, exactly like `injection.meta_key`.
// Keys are stored as declared; the nesting is a merge-time semantic.
// Reserved / spec-prefixed keys (at the whole key OR any dot-segment),
// over-deep paths, and paths colliding with another declared path on the
// connection are rejected at validation.
MetaAnnotations map[string]string `json:"meta_annotations,omitempty"`
// OAuthDiscoveryAllowedOrigins is the explicit per-connection cross-origin
// allow-list of public https origins the MCP OAuth-requirement discovery
// walker may fetch authorization-server metadata from. NON-SECRET (an origin
// allow-list, never a secret) — it rides the revision spine (versioned /
// diffable / rollback-able) and is writable live over
// `agent_config.set_mcp_discovery_origins`. Empty leaves the
// authorization-server hop needs-allowance (partial discovery), never a
// network hole: a granted origin is still refused at dial time if it
// resolves private / loopback. Set only for the http transport.
OAuthDiscoveryAllowedOrigins []string `json:"oauth_discovery_allowed_origins,omitempty"`
// Injection, when set, binds this runtime-added connection to per-user
// credential INJECTION for a RECEIVER-STYLE MCP server (the acting principal's
// credential is pulled per outbound call from the named broker and delivered
// in the declared form). NON-SECRET — it NAMES a boot-declared broker and
// declares a target key/form; only the broker-pulled value is secret, and it
// never rides this descriptor. Carried over the wire only behind the
// fail-closed `tools.allow_wire_injection` opt-in; recorded here so the
// binding is part of the agent's versioned desired state (diff / rollback).
// Set only for the http transport; mutually exclusive with OAuthProvider.
Injection *MCPCredentialInjectionDescriptor `json:"injection,omitempty"`
// ArtifactByteEligible declares that this connection MAY receive
// artifact BYTES through egress substitution: the runtime resolving an
// artifact id the model authored and placing the resolved bytes into
// the outbound tool-call body. NON-SECRET (a boolean declaration).
//
// It is the containment boundary for the feature. The reachable
// artifact SET is unchanged by it — that stays the dispatching run's
// own (tenant, user, session) — but the RECIPIENT widens: a remote
// server may now be handed those bytes.
//
// Unlike its wire-writable siblings (the inline OAuth binding, the
// injection mapping) it sits behind NO fail-closed boot opt-in, and
// the asymmetry is deliberate: those gates exist because their fields
// determine where a CREDENTIAL is sent, a boot-declared-only plane,
// while this one determines where a user's OWN CONTENT is sent —
// inside the co-tenant-admin trust boundary a shared runtime has
// already accepted, with one-runtime-per-tenant as the stated remedy
// for a deployment needing hard isolation. A boot gate would also
// break the use case: a server attached over the control plane must be
// usable without a redeploy.
//
// Every substitution is recorded (`mcp.artifact_egressed`,
// fail-closed, before the wire request) — ids, sizes and a digest,
// never the bytes. Set only for the http transport.
ArtifactByteEligible bool `json:"artifact_byte_eligible,omitempty"`
// ArtifactParams maps this server's TOOL names to the parameters on
// those tools which carry artifact bytes. NON-SECRET (names only).
// Requires ArtifactByteEligible. Each mapped parameter is validated
// against the server's OWN discovered inputSchema at attach — it must
// be declared there, and declared string-typed — so Harbor never
// asserts an argument shape the server did not publish. Set only for
// the http transport.
ArtifactParams map[string][]string `json:"artifact_params,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, the stdio argv command or the http URL, the non-secret OAuth provider NAME, and the non-secret operator `_meta` annotations. Secret auth material (bearer headers, OAuth tokens, credentials, the minted downstream token) 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). The `oauth_provider` field is a NAME, not a secret — it selects a config-declared acquisition strategy.
func (MCPConnectionDescriptor) CloneArtifactParams ¶ added in v1.24.0
func (d MCPConnectionDescriptor) CloneArtifactParams() map[string][]string
CloneArtifactParams returns a defensive deep copy of the descriptor's artifact-parameter mapping (nil for nil / empty), so a persisted revision and a live attach never share a backing map or slice.
type MCPConnectionLifecyclePayload ¶
type MCPConnectionLifecyclePayload struct {
events.SafeSealed
// Author is the identity that drove the add. On a run-start re-attach there
// is no admin request: Author carries the RECONCILING RUN's quadruple, whose
// non-empty RunID is the machine-readable discriminator between the two
// families (an admin add's RunID is empty).
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"). On the run-start re-attach events it is
// "online" for a successful re-establishment and the stable failure CLASS
// (one of the MCPReattachClass* constants) for a refused / unreachable one —
// so a reader distinguishes "the third party is down" from "current boot
// policy refuses this descriptor" without parsing Reason.
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. On a re-attach
// failure it may additionally carry a suppressed-attempt count, so a
// backed-off retry window is bounded and reported rather than silent.
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) AND for the run-start re-attach leg's two events (reattached / reattach_failed), which reuse this shape verbatim rather than adding a payload type that would differ from it only by a doc comment. 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 MCPConnectionRemovedPayload ¶ added in v1.11.0
type MCPConnectionRemovedPayload struct {
events.SafeSealed
// Author is the identity that recorded the removal.
Author identity.Quadruple
// AgentID is the agent whose MCP connection was removed (a registration
// identity, NOT an isolation principal).
AgentID string
// ServerID is the MCP source id that was removed.
ServerID string
// RevisionID is the revision that dropped the descriptor + pruned residue.
RevisionID string
// OccurredAt is the removal instant.
OccurredAt time.Time
}
MCPConnectionRemovedPayload is the typed payload for EventTypeMCPConnectionRemoved. SafePayload — every field is operator-visible audit metadata; no secret-shaped content is carried. It mirrors the paused/resumed payload shape (the removal is the same class of desired-state edit).
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 MCPCredentialInjectionDescriptor ¶ added in v1.21.0
type MCPCredentialInjectionDescriptor struct {
// Provider names the declared OAuth-provider broker the per-user credential is
// pulled from. Required. NON-SECRET (a name).
Provider string `json:"provider"`
// Form selects the injection form: "header" / "basic" / "meta". Required.
Form string `json:"form"`
// Header is the target request header name for Form=="header". Required for
// that form; a redaction-covered credential key, never `Authorization`.
Header string `json:"header,omitempty"`
// BasicUsername is the username half for Form=="basic" (the pulled credential
// is the password half). Optional. NON-SECRET.
BasicUsername string `json:"basic_username,omitempty"`
// MetaKey is the target `_meta` key path for Form=="meta", dot-separated for
// nesting. Required for that form; no reserved segment; redaction-covered leaf.
MetaKey string `json:"meta_key,omitempty"`
}
MCPCredentialInjectionDescriptor is the NON-SECRET per-connection mapping that binds a runtime-added receiver-style MCP server to per-user credential injection, recorded in a config revision as part of the agent's versioned desired state. It NAMES the broker the per-user credential is pulled from and declares WHERE the pulled value is placed on the outbound request (a header, an `Authorization: Basic` value, or a `_meta` key). No secret material lives here — only the broker-pulled value (resolved per-call from the ctx identity) is secret. It mirrors the boot `config.MCPCredentialInjectionConfig` so the runtime-add path and the boot path share ONE injection engine.
func (*MCPCredentialInjectionDescriptor) Clone ¶ added in v1.21.0
func (d *MCPCredentialInjectionDescriptor) Clone() *MCPCredentialInjectionDescriptor
Clone returns a defensive copy of the injection descriptor (nil for nil).
type MCPDiscoveryOriginsSetPayload ¶ added in v1.14.0
type MCPDiscoveryOriginsSetPayload struct {
events.SafeSealed
// Author is the identity that performed the write.
Author identity.Quadruple
// AgentID is the agent whose connection allow-list changed (a registration
// identity, NOT an isolation principal).
AgentID string
// ServerID is the MCP source id whose allow-list was replaced.
ServerID string
// RevisionID is the revision that recorded the new allow-list.
RevisionID string
// Granted is the set of origins newly present versus the prior live set.
Granted []string
// Revoked is the set of origins dropped versus the prior live set.
Revoked []string
// OccurredAt is the write instant.
OccurredAt time.Time
}
MCPDiscoveryOriginsSetPayload is the typed payload for EventTypeMCPDiscoveryOriginsSet. SafePayload — every field is operator-visible audit metadata; the origin deltas are PUBLIC https origins (an allow-list), never a secret.
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 NamedBlock ¶ added in v1.25.0
type NamedBlock struct {
// Name addresses the block within the section. It is unique within the
// section and drawn from a restricted identifier charset so it stays
// legible in a transcript and in a diff. It is NEVER emitted as an XML
// tag — attribution here is a data-model property, not a prompt-syntax
// one, so the prompt's structural taxonomy never becomes a function of
// caller input.
Name string `json:"name"`
// Body is the block's prompt text. It renders VERBATIM (unescaped) in
// the operator-trusted additive position — see ExtraSystemBlocks for
// the trust argument and the obligation it creates.
Body string `json:"body"`
}
NamedBlock is one named, operator-authored unit of additive prompt text held in the ExtraSystemBlocks section. The Name is the ADDRESS a contributor uses to find and replace exactly its own contribution; the Body is rendered verbatim.
type NamingDiff ¶ added in v1.12.0
type NamingDiff struct {
AutoChanged bool
AutoFrom string
AutoTo string
AfterTurnsChanged bool
AfterTurnsFrom string
AfterTurnsTo string
RepeatEveryChanged bool
RepeatEveryFrom string
RepeatEveryTo string
MaxRepetitionsChanged bool
MaxRepetitionsFrom string
MaxRepetitionsTo string
MaxTitleLenChanged bool
MaxTitleLenFrom string
MaxTitleLenTo string
ModelChanged bool
ModelFrom string
ModelTo string
}
NamingDiff is the per-field delta of the session auto-naming policy section across two revisions. Each dimension reports whether it changed plus its from / to display values (an unset section renders every field as ""). Deterministic.
Auto is a TRI-STATE display string — "" (section ABSENT) / "false" / "true" — because section PRESENCE is semantic: a present bare `{auto: false}` section is an explicit per-agent opt-out that overrides a yaml-on fleet default, while an absent section falls through to yaml. A two-state bool would render absent and bare-opt-out identically, making exactly that revision invisible to `agent_config.diff` (a phantom revision in the Console diff view).
func DiffNaming ¶ added in v1.12.0
func DiffNaming(from, to ConfigPayload) NamingDiff
DiffNaming computes the per-field delta of two session auto-naming states. Exported so the diff is one canonical implementation shared by the driver and tests. An ABSENT section renders every dimension "" — including Auto (the tri-state), so absent→bare-`{auto:false}` ("" → "false") and its inverse register as changes even though every OTHER dimension is zero-valued on both sides.
func (NamingDiff) Changed ¶ added in v1.12.0
func (d NamingDiff) Changed() bool
Changed reports whether any auto-naming dimension differs between the two revisions.
type NamingSection ¶ added in v1.12.0
type NamingSection struct {
// Auto enables session auto-naming for the agent. False (the zero value)
// in a PRESENT section is an explicit off that overrides the yaml fleet
// default.
Auto bool `json:"auto,omitempty"`
// AfterTurns is the completed-run count at which the FIRST auto-name
// fires (fire on the Nth completed run). Zero resolves to the default
// (1) at run start; a negative value is rejected at set time.
AfterTurns int `json:"after_turns,omitempty"`
// RepeatEvery, when > 0, re-names every N completed turns after the
// first; 0 (the default) names once only. Negative is rejected at set
// time.
RepeatEvery int `json:"repeat_every,omitempty"`
// MaxRepetitions is the hard cap on the TOTAL number of auto-namings
// (including the first). It is REQUIRED ≥ 1 whenever RepeatEvery > 0 —
// no unlimited value exists, so unbounded periodic re-naming is
// unrepresentable. Ignored when RepeatEvery == 0 (naming happens once).
MaxRepetitions int `json:"max_repetitions,omitempty"`
// MaxTitleLen bounds the auto title (runes). Zero resolves to the
// default (80) at run start; a set value must be in [8, 200].
MaxTitleLen int `json:"max_title_len,omitempty"`
// Model, when set, is the model the auto-naming Complete call requests
// (validated against ModelProfiles at set time); empty uses the run's
// effective model.
Model string `json:"model,omitempty"`
}
NamingSection is the session auto-naming policy section of the config envelope. Declared as its own optional section so a set REPLACES only this section, preserving the sibling sections (the section-merge invariant). Opt-in, default off: a NIL section means "no per-agent policy" (the yaml `runtime.naming` fleet default, then off, resolves at run start). A PRESENT section is authoritative either way: Auto=true enables, Auto=false is an explicit per-agent OPT-OUT that overrides a yaml-on fleet default — section presence is the operator's signal, and normalization preserves any non-nil section verbatim (never an inert-drop).
type OAuthProviderDescriptor ¶ added in v1.14.0
type OAuthProviderDescriptor struct {
// Name is the unique provider name (the binding a connection's
// oauth_provider references). Required.
Name string `json:"name"`
// Driver is the OAuth flow driver — validated to be exactly
// "tokenexchange" (the only writable driver; the non-interactive PULL
// exchange). Required.
Driver string `json:"driver"`
// CredentialSource is the credential-source seam — validated to be exactly
// "remote" (broker-pull). An empty value is a LOUD reject (in config
// "" means the `env` source, which this shape forbids). Required.
CredentialSource string `json:"credential_source"`
// CredentialBroker names a boot-declared credential broker that
// pins the runtime's OWN credential custody. Required in BOTH the name-only
// and the dev-gated wire shape — the wire descriptor still names a boot broker
// so no credential-source URL or secret ever rides the wire. NON-SECRET.
CredentialBroker string `json:"credential_broker"`
// Scopes is the requested OAuth scope subset. NON-SECRET. Clamped to the
// broker's boot scope ceiling at build time — a scope outside the ceiling is
// dropped, never honoured (an installed descriptor can never widen scope).
// Optional.
Scopes []string `json:"scopes,omitempty"`
// TokenURL is the dev-gated wire-carried RFC-8693 token-exchange endpoint of
// the NEW server. Persisted (NON-SECRET, a URL); accepted only behind the
// `allow_wire_oauth_descriptor` boot opt-in and dialed through the
// token-exchange SSRF backstop. Empty for the name-only shape.
TokenURL string `json:"token_url,omitempty"`
// Audience is the dev-gated wire-carried exchanged-token audience of the NEW
// server. Persisted (NON-SECRET). Empty for the name-only shape.
Audience string `json:"audience,omitempty"`
// AllowedDownstreamHosts is the DERIVED downstream sink allow-list for a
// wire-installed provider — set by the runtime from the bound connection's
// own URL, NEVER from a wire field. Persisted (NON-SECRET) so a rollback /
// reconcile rebuilds the provider with the same derived sink. Empty for the
// name-only shape (its sink is the boot broker's).
AllowedDownstreamHosts []string `json:"allowed_downstream_hosts,omitempty"`
}
OAuthProviderDescriptor is the ZERO-URL, Protocol-installed OAuth provider descriptor recorded in a config revision so the provider is part of the agent's versioned desired state (diff / rollback). It carries NO URL of any kind, NO env-var name, and NO literal secret: the credential-plane invariant is that no admin-writable field may determine where a credential is sent, so every credential-sink-determining value (the token endpoint, the credential-pull endpoint, the allowed downstream hosts, the audience, and the scope ceiling) is pinned at boot on the NAMED credential broker (the boot broker's broker list) the descriptor references by non-secret NAME. The wire struct exposes NO field that is a URL or an env-var name; a decode carrying `token_url` / `auth_url` / `client_id_env` / `client_secret_env` / `remote` is rejected BY NAME (DisallowUnknownFields — the field cannot exist).
type OAuthProviderSetPayload ¶ added in v1.14.0
type OAuthProviderSetPayload struct {
events.SafeSealed
// Author is the identity that performed the install / uninstall.
Author identity.Quadruple
// AgentID is the agent whose installed-provider set changed (a registration
// identity, NOT an isolation principal).
AgentID string
// ProviderName is the installed / uninstalled provider name.
ProviderName string
// CredentialBroker is the boot-declared broker the installed provider
// references by name (empty on uninstall). NON-SECRET.
CredentialBroker string
// RevisionID is the recording revision id.
RevisionID string
// OccurredAt is the write instant.
OccurredAt time.Time
}
OAuthProviderSetPayload is the typed payload for the Protocol-installed OAuth-provider install / uninstall audit events. SafePayload — every field is operator-visible audit metadata; NO URL, NO env-var name, NO secret is ever carried (there is none on the zero-URL descriptor). The credential-broker name is a non-secret boot reference.
type OAuthProvidersDiff ¶ added in v1.14.0
type OAuthProvidersDiff struct {
// Added are the provider names present in the to-revision but not the
// from-revision.
Added []string
// Removed are the provider names present in the from-revision but not the
// to-revision.
Removed []string
}
OAuthProvidersDiff is the structured set-diff of the Protocol-installed OAuth-provider descriptors across two revisions, by name. Deterministic: every slice is sorted.
func DiffOAuthProviders ¶ added in v1.14.0
func DiffOAuthProviders(from, to ConfigPayload) OAuthProvidersDiff
DiffOAuthProviders computes the structured set-diff (by name) of two installed-provider states. Exported so the diff is one canonical implementation shared by the driver and tests.
func (OAuthProvidersDiff) Changed ¶ added in v1.14.0
func (d OAuthProvidersDiff) Changed() bool
Changed reports whether the installed-provider set differs between the two revisions.
type OAuthProvidersSection ¶ added in v1.14.0
type OAuthProvidersSection struct {
// Providers is the set of installed provider descriptors, keyed by Name.
// Canonicalised sorted-by-name with a name-unique invariant so a
// re-ordering does not perturb the content hash.
Providers []OAuthProviderDescriptor `json:"providers,omitempty"`
}
OAuthProvidersSection is the Protocol-installed OAuth-provider section of the config envelope: the set of ZERO-URL provider descriptors an admin has installed over the control plane. Declared as its own section so an install / uninstall REPLACES only this section, preserving every sibling (the section-merge invariant).
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.
//
// opts carries the optional precondition. Its zero value is the
// unconditional write. When opts.ExpectedContentHash is set, the
// precondition is evaluated BEFORE the idempotent-re-set
// short-circuit, so a stale expectation is never converted into a
// misleading success by a payload that happens to equal the current
// content; a failed precondition returns ErrRevisionConflict and
// persists nothing.
SetRevision(ctx context.Context, id identity.Quadruple, agentID string, scope ConfigScope, payload ConfigPayload, opts SetOptions) (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.
//
// opts carries the same optional precondition SetRevision takes: when
// opts.ExpectedContentHash is set, the CURRENTLY-ACTIVE revision must
// carry that content hash or the repoint is refused with
// ErrRevisionConflict and the pointer is left where it was.
Rollback(ctx context.Context, id identity.Quadruple, agentID, revisionID string, scope ConfigScope, opts SetOptions) (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).
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 RunCompletionHook ¶ added in v1.10.0
type RunCompletionHook struct {
// Tool is the catalog tool name the transcript is dispatched to. An empty
// tool normalises the RunCompletion to nil BUT preserves the enclosing
// hooks section (a present section with no tool is the explicit per-agent
// no-hook that overrides a yaml fleet hook at run start).
Tool string `json:"tool"`
// TimeoutMS is the dispatch timeout in milliseconds. Zero falls through
// to the runtime default at run start. Negative is rejected at set time.
TimeoutMS int `json:"timeout_ms,omitempty"`
}
RunCompletionHook is the durable, versioned run-completion hook configuration in a config revision: the catalog tool the run transcript is dispatched to at the run loop's terminal boundary, plus an optional dispatch timeout. It mirrors the static `runtime.hooks.run_completion` yaml; resolution at run start is agent-config over yaml over no hook.
type SetOptions ¶ added in v1.25.0
type SetOptions struct {
// ExpectedContentHash, when non-empty, requires the agent's ACTIVE
// revision to carry exactly this content hash at write time. A
// mismatch — or no active revision at all — fails with
// ErrRevisionConflict and persists nothing.
//
// The reserved value [ExpectNoActiveRevision] ("-") inverts the
// no-active-revision arm: it REQUIRES the agent to have no active
// revision, and is refused once one exists. It is what makes the
// read-modify-write composition protocol expressible at its base case,
// where a read answers `set:false` and there is no hash to echo. A real
// content hash is 64 lowercase hex characters, so the sentinel can never
// collide with one.
//
// The expectation is compared against the content hash, not the
// revision id, because a rollback repoints the active pointer WITHOUT
// changing the content: a revision-id token would raise a false
// conflict on the restore path. The guarded quantity is a value, so
// the token is a value.
//
// # The bound on the guarantee — read this before relying on it
//
// The comparison is atomic against every other spine writer IN THIS
// PROCESS, via the agent-config service's per-owner striped write
// lock, which is held across each door's whole read-modify-write.
//
// It is NOT atomic across Runtime processes sharing one StateStore.
// The StateStore has no compare-and-swap primitive — its own
// interface godoc says it does not enforce CAS — and the active
// pointer is written with a fresh event id on every save, so the slot
// is overwritten unconditionally. Two Runtime processes sharing one
// Postgres or SQLite store CAN STILL LOSE AN UPDATE, and this option
// does not claim otherwise. Closing that gap needs a conditional-write
// primitive on the StateStore interface across the persistence triad;
// it is a separate change and is not pretended here.
//
// What the bounded guarantee is still worth: the window it closes is
// the READ-TO-WRITE window — seconds to minutes for a human editing a
// config in the Console, and however long an agent takes to compose
// one. The window it cannot close cross-process is the driver's own
// read-modify-write, on the order of microseconds. Single-process the
// guard is exact; multi-process it is a large reduction in loss
// probability and not an elimination.
//
// # It constrains only the writer that supplies it
//
// An unconditional writer can still clobber a conditional one, by
// design: the token is a precondition on this write, never a lock on
// the agent. A caller wanting exclusivity needs every writer of that
// agent's config to participate, which is a deployment convention and
// not something the runtime enforces — making the token mandatory
// would break every caller that does not send one.
ExpectedContentHash string
}
SetOptions carries the optional preconditions a durable spine write (SetRevision / Rollback) may declare. The ZERO value is the unconditional write — byte-for-byte the behaviour that shipped before this option existed, on every door.
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"`
// ServerLoadingModes overrides the default LoadingMode ("always" |
// "deferred") for a server's TOOL-form descriptors, keyed by the
// catalog's ToolSourceID. See the precedence order above.
ServerLoadingModes map[string]string `json:"server_loading_modes,omitempty"`
// ToolLoadingModes overrides the effective LoadingMode for one exact
// catalog name ("always" | "deferred"), unconditionally. See the
// precedence order above.
ToolLoadingModes map[string]string `json:"tool_loading_modes,omitempty"`
}
ToolExposure is the forward-compatible tool/MCP-exposure section of the config envelope: the exclusion-based pause/disable sets (PausedServers / DisabledTools) plus the runtime loading-mode override maps (ServerLoadingModes / ToolLoadingModes).
Loading-mode precedence (pinned) ¶
Per descriptor, the effective LoadingMode resolves in this order:
- ToolLoadingModes[name] — exact, unconditional (works on tool / resource / prompt forms alike).
- ServerLoadingModes[source] — the server-wide default, applied ONLY to TOOL-form descriptors (tools.Tool.Form == tools.ToolFormTool); a server-level override never blanket-flips that server's wrapped resource/prompt descriptors.
- The boot `tools.entries[].loading_mode` (already materialized into the catalog's Tool.Loading at boot).
- The driver/registration default.
Layers 3-4 are already baked into the catalog's boot-effective tools.Tool.Loading, so a projection consumer applies exactly the top two layers over that boot-effective value (see internal/runtime/agentcfg/projection). Values are the closed set "always" | "deferred" — validated at the `agent_config.set_tool_exposure` wire edge BEFORE any registry write (CLAUDE.md §13: no invalid value is ever persisted). Loading is NOT capability-narrowing (a deferred tool stays reachable via `tool_search`), so it lives in the ADMIN tier only — the narrow-only user/session tiers gain no loading field.
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
// ServerLoadingChanges / ToolLoadingChanges are the structured deltas of
// the per-server / per-tool loading-mode override maps. Sorted by Key.
ServerLoadingChanges []LoadingModeChange
ToolLoadingChanges []LoadingModeChange
}
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. |