protocol

package
v1.3.1 Latest Latest
Warning

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

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

Documentation

Overview

Package protocol implements the eight `agents.*` Protocol methods the Console Agents page (Phase 73e / D-124) consumes:

  • agents.list — paginated, faceted agent catalog projection.
  • agents.get — one agent's full registration-identity projection (identity / hosting / status / health / AgentConfig).
  • agents.tools — the agent's tool bindings + per-binding OAuth.
  • agents.memory — the agent's memory strategy + TTL + scope.
  • agents.governance — per-identity-tier ceilings + spend + limits.
  • agents.skills — the agent's attached skills.
  • agents.permissions — the agent's permission model (V1: implicit).
  • agents.metrics — the registry-wide rollup the page hero shows.

The seam (CLAUDE.md §4.4)

The Service depends on the `Projector` interface, not on a concrete Agent Registry. The V1 production implementation is `RegistryProjector` (registry_projector.go) — a thin read-only projection over a `registry.AgentRegistry`. A future projector that joins richer operational metadata (live task counts, real governance accumulators) slots in behind the same interface without reshaping the Service.

Identity is mandatory (CLAUDE.md §6 rule 9)

Every method takes the wire request's `IdentityScope`. An incomplete triple fails closed with `ErrIdentityRequired` — there is no identity-downgrading knob. The Service NEVER reads identity from a package-level global; the triple flows in via the request. The registry filters by the (tenant, user, session) tuple, NEVER by `agent_id` — `agent_id` is a registration identity, not a WHERE-clause isolation key (D-059, CLAUDE.md §6 clarifying note).

No `agents.*` control method

The five agent-control verbs the Agents page exposes (Pause / Drain / Restart / Force-Stop / Deregister) are NOT `agents.*` methods — they are the EXISTING shipped `registry.*` control verbs (D-066), gated on the elevated control-scope claim. Phase 73e mints NO control method; the page invokes the shipped registry control surface. All eight `agents.*` methods here are READ-ONLY projections (CLAUDE.md §13).

Concurrent reuse (D-025)

A constructed *Service is immutable after NewService and safe to share across N concurrent goroutines: it holds only the Projector reference + a logger; every method's per-call state lives in the call's arguments and locals, never on the Service.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrIdentityRequired — the request carried an incomplete identity
	// triple. RFC §5.5 / CLAUDE.md §6 rule 9 — fails closed.
	ErrIdentityRequired = errors.New("registry/protocol: identity scope incomplete")
	// ErrAgentNotFound — the requested agent_id is not registered in
	// the registry visible to the caller's identity scope.
	ErrAgentNotFound = errors.New("registry/protocol: agent not found")
	// ErrInvalidRequest — the request was structurally invalid (an
	// empty agent id, an out-of-range page size).
	ErrInvalidRequest = errors.New("registry/protocol: invalid request")
	// ErrMisconfigured — NewService was called with a nil Projector.
	ErrMisconfigured = errors.New("registry/protocol: NewService missing a mandatory dependency")
	// ErrControlScopeRequired — a fleet-control verb (Pause / Drain /
	// Restart / ForceStop / Deregister) was called without the elevated
	// `auth.ScopeAdmin` control claim (D-066). Fails closed.
	ErrControlScopeRequired = errors.New("registry/protocol: fleet-control requires the elevated control-scope claim")
	// ErrControlUnsupported — a fleet-control verb was called on a Service
	// built without a Controller (WithController). The dev/server wiring
	// always injects one; this guards a misconfiguration rather than
	// nil-panicking (CLAUDE.md §5).
	ErrControlUnsupported = errors.New("registry/protocol: fleet-control not wired on this Service")
)

Sentinel errors the Service returns. The wire handler maps each onto a canonical Protocol Code + HTTP status; in-process callers compare with errors.Is.

Functions

This section is empty.

Types

type ConfigSource

type ConfigSource interface {
	// Config returns the agent's AgentConfig projection.
	Config(ctx context.Context, id identity.Identity, agentID string) (prototypes.AgentConfig, error)
	// Tools returns the agent's tool bindings.
	Tools(ctx context.Context, id identity.Identity, agentID string) ([]prototypes.AgentToolBinding, error)
	// Memory returns the agent's memory binding.
	Memory(ctx context.Context, id identity.Identity, agentID string) (prototypes.AgentMemoryBinding, error)
	// Governance returns the agent's governance posture.
	Governance(ctx context.Context, id identity.Identity, agentID string) (prototypes.AgentGovernance, error)
	// Skills returns the agent's attached skills.
	Skills(ctx context.Context, id identity.Identity, agentID string) ([]prototypes.AgentSkillBinding, error)
}

ConfigSource is the optional join seam the RegistryProjector uses to resolve an agent's configuration-derived projections — the AgentConfig, tool bindings, memory binding, governance posture, and attached skills. The Agent Registry (D-059) stores only the version_hash of an agent's AgentConfig, not the config itself; the configuration-derived tabs of the Console Agents page therefore need a join over the subsystems that DO own that data (the tool catalog, the memory configs, the Phase 36 governance accumulators, the skills catalog).

ConfigSource is OPTIONAL on the projector. When it is nil, the configuration-derived methods return an HONEST empty projection — an empty tool-binding list, a zero-value memory binding, etc. — which the Console renders as a real "nothing configured for this agent" empty state. This is NOT a stubbed success (CLAUDE.md §13): the methods still validate identity and the agent's existence; they simply report that no configuration join is wired. Production wiring (`harbor dev`) supplies a ConfigSource so the tabs carry live data.

Every method takes the verified identity tuple so the implementation scopes its reads — NEVER by agent_id (D-059).

type Controller added in v1.3.0

type Controller interface {
	Pause(ctx context.Context, agentID, reason string) error
	Drain(ctx context.Context, agentID, reason string) error
	Restart(ctx context.Context, agentID, reason string) error
	ForceStop(ctx context.Context, agentID, reason string) error
	Deregister(ctx context.Context, agentID string) error
}

Controller is the mutate seam the five fleet-control verbs depend on (Phase 108l / D-184). The V1 production implementation is the in-process `*registry.Registry`, whose control methods self-enforce `registry.HasControlScope(ctx)` and emit the `agent.*` events. Every method takes the verified identity (folded into ctx by the handler) plus the control-scope claim (attached by the Service before the call) — agent_id is the target handle, never an isolation key (D-059).

type Option

type Option func(*Service)

Option configures NewService.

func WithController added in v1.3.0

func WithController(c Controller) Option

WithController injects the fleet-control mutate seam (Phase 108l / D-184). Without it, the five control verbs fail closed with ErrControlUnsupported. The production wiring passes the in-process `*registry.Registry`.

func WithLogger

func WithLogger(l *slog.Logger) Option

WithLogger sets the slog.Logger the Service logs projector failures to. A nil logger routes to slog.Default().

type Projector

type Projector interface {
	// ListAgents returns every agent visible to id, in agent_id order.
	// The Service applies the facet filter + pagination on top.
	ListAgents(ctx context.Context, id identity.Identity) ([]prototypes.Agent, error)
	// GetAgent returns the full projection for agentID, or
	// ErrAgentNotFound.
	GetAgent(ctx context.Context, id identity.Identity, agentID string) (prototypes.AgentGetResponse, error)
	// AgentTools returns the agent's tool bindings, or ErrAgentNotFound.
	AgentTools(ctx context.Context, id identity.Identity, agentID string) ([]prototypes.AgentToolBinding, error)
	// AgentMemory returns the agent's memory binding, or
	// ErrAgentNotFound.
	AgentMemory(ctx context.Context, id identity.Identity, agentID string) (prototypes.AgentMemoryBinding, error)
	// AgentGovernance returns the agent's governance posture, or
	// ErrAgentNotFound.
	AgentGovernance(ctx context.Context, id identity.Identity, agentID string) (prototypes.AgentGovernance, error)
	// AgentSkills returns the agent's attached skills, or
	// ErrAgentNotFound.
	AgentSkills(ctx context.Context, id identity.Identity, agentID string) ([]prototypes.AgentSkillBinding, error)
	// AgentPermissions returns the agent's permission model, or
	// ErrAgentNotFound.
	AgentPermissions(ctx context.Context, id identity.Identity, agentID string) (prototypes.AgentPermissions, error)
	// Metrics returns the registry-wide rollup for id's scope.
	Metrics(ctx context.Context, id identity.Identity) (prototypes.AgentMetrics, error)
}

Projector is the read seam the Service depends on. The V1 production implementation is RegistryProjector. Every method takes the verified identity triple so the implementation scopes its reads by the (tenant, user, session) tuple — NEVER by agent_id (D-059).

type ProjectorOption

type ProjectorOption func(*RegistryProjector)

ProjectorOption configures NewRegistryProjector.

func WithConfigSource

func WithConfigSource(src ConfigSource) ProjectorOption

WithConfigSource wires the optional ConfigSource join. A nil source is treated as "WithConfigSource not supplied".

type RegistryProjector

type RegistryProjector struct {
	// contains filtered or unexported fields
}

RegistryProjector is the V1 production Projector — a read-only projection over a registry.AgentRegistry, optionally joined to a ConfigSource for the configuration-derived tabs. It is a D-025-safe compiled artifact: immutable after NewRegistryProjector, holding only interface references.

func NewRegistryProjector

func NewRegistryProjector(reg registry.AgentRegistry, opts ...ProjectorOption) (*RegistryProjector, error)

NewRegistryProjector builds the V1 production Projector. reg is mandatory — a nil fails loud with ErrMisconfigured (CLAUDE.md §5).

func (*RegistryProjector) AgentGovernance

func (p *RegistryProjector) AgentGovernance(ctx context.Context, id identity.Identity, agentID string) (prototypes.AgentGovernance, error)

AgentGovernance implements Projector.AgentGovernance.

func (*RegistryProjector) AgentMemory

AgentMemory implements Projector.AgentMemory.

func (*RegistryProjector) AgentPermissions

func (p *RegistryProjector) AgentPermissions(ctx context.Context, _ identity.Identity, agentID string) (prototypes.AgentPermissions, error)

AgentPermissions implements Projector.AgentPermissions. V1 default is the implicit permission model (page-agents.md §10): every authenticated user in the tenant can invoke the agent. The method still validates the agent exists; an explicit ACL surface is post-V1.

func (*RegistryProjector) AgentSkills

AgentSkills implements Projector.AgentSkills.

func (*RegistryProjector) AgentTools

AgentTools implements Projector.AgentTools.

func (*RegistryProjector) GetAgent

GetAgent implements Projector.GetAgent.

func (*RegistryProjector) ListAgents

ListAgents implements Projector.ListAgents.

func (*RegistryProjector) Metrics

Metrics implements Projector.Metrics — the registry-wide rollup. The V1 rollup counts Active Agents from the registry's identity-scoped List; Running Tasks / Total Cost / Total Tokens come from the ConfigSource's governance join when one is wired, else zero (an honest "not joined" rollup, not a faked number).

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service implements the thirteen `agents.*` Protocol methods (the eight read projections + the five fleet-control verbs). It is a D-025-safe compiled artifact — immutable after NewService.

func NewService

func NewService(projector Projector, opts ...Option) (*Service, error)

NewService builds the Agents Protocol service over a Projector. The projector is mandatory — a nil fails loud with ErrMisconfigured rather than building a Service that would nil-panic on the first request (CLAUDE.md §5). The returned *Service is immutable after construction (D-025) and safe for concurrent use by N goroutines.

func (*Service) Deregister added in v1.3.0

Deregister implements the `agents.deregister` fleet-control verb (Phase 108l). Irreversible; the reason is not carried to the registry (registry.Deregister takes no reason).

func (*Service) Drain added in v1.3.0

Drain implements the `agents.drain` fleet-control verb (Phase 108l).

func (*Service) ForceStop added in v1.3.0

ForceStop implements the `agents.force_stop` fleet-control verb (Phase 108l).

func (*Service) Get

Get implements the `agents.get` method — the full projection of one agent.

func (*Service) Governance

Governance implements the `agents.governance` method.

func (*Service) List

List implements the `agents.list` method. It validates identity, resolves the identity-scoped agent set from the Projector, applies the facet filter + free-text search + pagination, and computes the filtered-view aggregates.

func (*Service) Memory

Memory implements the `agents.memory` method.

func (*Service) Metrics

Metrics implements the `agents.metrics` method — the registry-wide rollup over the caller's identity scope.

func (*Service) Pause added in v1.3.0

Pause implements the `agents.pause` fleet-control verb (Phase 108l).

func (*Service) Permissions

Permissions implements the `agents.permissions` method.

func (*Service) Restart added in v1.3.0

Restart implements the `agents.restart` fleet-control verb (Phase 108l).

func (*Service) Skills

Skills implements the `agents.skills` method.

func (*Service) Tools

Tools implements the `agents.tools` method.

Jump to

Keyboard shortcuts

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