Help us shape the future of Go! Take the 2026 Go Developer Survey

node

package
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Oct 18, 2026 License: Apache-2.0 Imports: 94 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// HeaderMeshEgressPort carries the requested TCP destination port when a
	// CONNECT tunnel is forwarded across /libp2p-http.
	HeaderMeshEgressPort = "X-Mesh-Egress-Port"
	// HeaderMeshTunnelUpgrade marks an HTTP/1.1 request over /libp2p-http as a
	// raw TCP CONNECT tunnel.
	HeaderMeshTunnelUpgrade = "mesh-tcp-tunnel"
)
View Source
const (
	// HeaderMeshMCPTool lets an external proxy (or ext_proc filter) pass the
	// extracted MCP tool name during an ext_authz check.
	HeaderMeshMCPTool = envoy.HeaderMeshMCPTool

	// ExtProcMethodPath is the gRPC HTTP/2 path for Envoy ExternalProcessor.Process.
	ExtProcMethodPath = envoy.ExtProcMethodPath
)
View Source
const (
	// Cache sizes
	RateLimiterSize       = 1000
	RevocationCacheSize   = 10000
	VerificationCacheSize = 1000

	// Freshness checks
	FreshnessThreshold = 5 * time.Minute

	// Key pruning
	KeyPruningInterval = 1 * time.Hour
	// DefaultControlPlaneSyncInterval bounds how long a running node can lag
	// the control plane on keys, bans and policy when no gossip event reaches
	// it. It must sit well inside the control plane's --key-grace-period
	// (1h by default): a successor key can only be adopted while the key it
	// replaces still vouches for it, and one attempt per window is a race.
	// Four attempts per default window is the trade against load on large
	// meshes, where an operator raising the grace period can raise this too.
	DefaultControlPlaneSyncInterval = 15 * time.Minute
)
View Source
const (
	DefaultDiscoveryInterval    = "30s"
	DefaultConfigFile           = "agentmesh-node.yaml"
	DefaultRouterConnectTimeout = 5 * time.Second
	// A router pod that restarts is back in well under a minute; the first
	// redial waits a moment for it, and six doublings reach past where the
	// connection monitor's own interval takes over.
	DefaultRouterRedialDelay    = 2 * time.Second
	DefaultRouterRedialAttempts = 6
	// DefaultRouterAuthAttempts with DefaultRouterRedialDelay doubling
	// between them waits 14 s in all beyond the dials themselves: enough
	// for a router that is busy admitting a fleet, short enough that a
	// member with no router at all still reports it within a minute.
	DefaultRouterAuthAttempts = 4
	// DefaultRouters is how many routers a node keeps a session with: one
	// is enough to be on the mesh, the second is there for when the first
	// restarts. Every session costs a router a connection, so a node does
	// not keep one with every router it knows of.
	DefaultRouters = 2
	// DefaultRouterShunDuration is how long a node stays off a router that
	// sent it away or did not come back: past a rollout of the router, short
	// enough that one back for good is used again.
	DefaultRouterShunDuration = 5 * time.Minute
	// DefaultSocketName is the local API socket the node creates in its data directory.
	DefaultSocketName = "agentmesh.sock"
)
View Source
const (
	ConnLowWaterMark  = 100
	ConnHighWaterMark = 400
)

The node's connection budget: the connection manager trims down to the low watermark once the high one is passed, and the resource manager refuses past the high one. A node that publishes a service is called by many members, each over a connection of its own, so the budget is sized for a provider rather than for a leaf that talks to a few peers.

View Source
const (
	StateDirIdentityFile   = "identity.key"
	StateDirCredentialFile = "credential.json"
)

The state directory is the layout the native SDKs keep a member in, and what `agentmesh-node state export` writes and `agentmesh-node state import` reads: the private key in the libp2p PrivateKey encoding and the api.MemberCredential as protojson with proto field names. Files are owner-only; unknown fields in the credential are an error, as on every Agent Mesh surface.

View Source
const DefaultSecretsDir = "/etc/agentmesh/secrets"

DefaultSecretsDir is where a node looks for the credentials the control plane names in egress destinations when --secrets-dir is not given.

View Source
const PeerstoreKeyPrivateIPFailed = "private_ip_failed"

PeerstoreKeyPrivateIPFailed is the key used in the libp2p Peerstore to track if a peer's private IP was previously found to be unreachable or slower than a relay. This allows the node to "try once and remember", avoiding a 15-second timeout on subsequent discovery or tool calls when dialing unroutable private networks.

View Source
const (
	// StoreFile is the node database inside the data directory.
	StoreFile = "agent.db"
)

Variables

View Source
var (
	// Renewal timing defaults
	DefaultRenewalFallback = (api.BiscuitTokenTTL * 8) / 10 // 80% of TTL (19.2h)
	RenewalBuffer          = api.BiscuitTokenTTL / 5        // 20% of TTL (4.8h)
	RenewalThreshold       = api.BiscuitTokenTTL / 4        // 25% of TTL (6h)
)

ConnsPerSourceIP is how many inbound connections one source address may hold at once. Members share addresses (pod SNAT, Cloud NAT, an office, a fleet on one host), and libp2p's default of 8 made a provider refuse the ninth caller behind any of them with nothing in its logs or metrics.

View Source
var ErrAuthRejected = errors.New("auth rejected")

ErrAuthRejected marks a service-level authorization denial from a remote peer, as opposed to a transport/connectivity failure. Callers use errors.Is to tell "you're not allowed" apart from "the service is unreachable" so that discovery (find_remote_tools) can hide forbidden services instead of leaking their names.

View Source
var ErrFatalAuth = errors.New("fatal authentication error")
View Source
var ErrProviderNotGranted = errors.New("provider not granted the service")

ErrProviderNotGranted marks a provider whose credential does not grant serving the service the call names: it is enrolled and reachable, and not who the policy says serves that name.

View Source
var ErrProviderUnreachable = errors.New("provider unreachable")

ErrProviderUnreachable marks a label-gate failure in which the provider could not be reached or did not answer, as against one in which it answered and its credential did not satisfy the requirement. The first is the mesh's state and a caller may retry it; the second is a verdict.

View Source
var ErrStoreLocked = errors.New("another agentmesh-node instance is using this data directory")

ErrStoreLocked reports that another process already holds the data directory, which for a node data directory means a node is running.

View Source
var NewFileTokenSource = cpclient.NewFileTokenSource

NewFileTokenSource creates a TokenSource that reads path on every FetchToken call.

Functions

func CallerBiscuitFromContext

func CallerBiscuitFromContext(ctx context.Context) []byte

CallerBiscuitFromContext returns the caller Biscuit attached to ctx, or nil.

func FetchControlPlaneInfo

func FetchControlPlaneInfo(ctx context.Context, controlPlaneURL string) (*api.ControlPlaneInfoResponse, error)

FetchControlPlaneInfo retrieves the latest configuration from the control plane's /info endpoint.

func FetchControlPlaneKeys

func FetchControlPlaneKeys(ctx context.Context, controlPlaneURL string, trusted []ed25519.PublicKey) ([]ed25519.PublicKey, error)

FetchControlPlaneKeys retrieves the full set of currently valid control plane public keys from /keys, the same catch-up path routers use. Enrollment only hands out the newest key, so this is how a node learns keys still in their rotation grace period, or rotations it missed while offline. The set is accepted only if signed by a key in trusted.

func GetDefaultDataDir

func GetDefaultDataDir() (string, error)

func GetOrGenerateKey

func GetOrGenerateKey(s *Store) crypto.PrivKey

GetOrGenerateKey retrieves a persistent private key or creates one if it's the first run

func NewMCPHandler

func NewMCPHandler(node *AgentMeshNode) http.Handler

NewMCPHandler creates a new HTTP handler for the MCP server using the official SDK.

func NewMCPServer

func NewMCPServer(node *AgentMeshNode) *mcp.Server

NewMCPServer creates a new MCP server instance with all tools registered.

func NewUnauthenticatedMCPHandler

func NewUnauthenticatedMCPHandler(controlPlaneURL string) http.Handler

NewUnauthenticatedMCPHandler creates an HTTP handler for the unauthenticated MCP server.

func NewUnauthenticatedMCPServer

func NewUnauthenticatedMCPServer(controlPlaneURL string) *mcp.Server

NewUnauthenticatedMCPServer creates a minimal MCP server that instructs the client on how to authenticate.

func ProbeGCPMetadata

func ProbeGCPMetadata(ctx context.Context, endpoint string, httpClient *http.Client) bool

ProbeGCPMetadata reports whether the GCE/Cloud Run metadata server is reachable and answers with Metadata-Flavor: Google.

func ReadStateDir

func ReadStateDir(dir string) (privKey []byte, c *api.MemberCredential, err error)

ReadStateDir reads a member from dir.

func ReportNodeCatalog

func ReportNodeCatalog(ctx context.Context, controlPlaneURL string, biscuitToken []byte, services []*api.ServiceInfo) error

ReportNodeCatalog self-reports this node's locally registered services to the control plane's /nodes/catalog endpoint, so an admin can see mesh-wide service topology (see catalog.go's HandleNodeCatalog for why this exists instead of the control plane discovering it via DHT/P2P itself).

func SetAllowInsecureControlPlane

func SetAllowInsecureControlPlane(allow bool)

SetAllowInsecureControlPlane records the operator's --insecure-control-plane choice: plaintext http:// to a non-loopback control plane is then accepted.

func StartMetricsServer

func StartMetricsServer(node *AgentMeshNode, addr string) (*http.Server, error)

StartMetricsServer serves /metrics, /healthz and /readyz on addr with no authentication, for a scraper and a kubelet that hold no sidecar token. The sidecar's own /metrics stays token-gated: this listener exists so a socket-only node, which has no TCP port at all, can still be observed. It is off unless an operator names the address, since nothing on it is gated.

func StartSidecarServer

func StartSidecarServer(node *AgentMeshNode, addr, socketPath, token, certFile, keyFile, caFile string) (*http.Server, error)

StartSidecarServer serves the node's local API on a TCP address, on a Unix socket, or on both. An empty addr disables the TCP listener; an empty socketPath disables the socket.

func StartUnauthSidecarServer

func StartUnauthSidecarServer(controlPlaneURL, addr, socketPath, certFile, keyFile string) (*http.Server, error)

StartUnauthSidecarServer serves the enrollment-only API of a node that has no identity yet, on a TCP address, on a Unix socket, or on both.

func WithCallerBiscuit

func WithCallerBiscuit(ctx context.Context, biscuitBytes []byte) context.Context

WithCallerBiscuit attaches a verified caller Biscuit (such as a narrowed Task Biscuit or an exchanged Delegated Session Biscuit) to ctx so outbound mesh and egress handlers use it instead of the node's standing identity.

func WriteStateDir

func WriteStateDir(dir string, privKey []byte, c *api.MemberCredential) error

WriteStateDir writes a member to dir, creating it owner-only.

Types

type A2AService

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

A2AService proxies Agent2Agent (A2A) JSON-RPC/REST traffic to a local agent process. URL backends only: a command backend would wire the A2A route to an MCP stdio bridge no A2A client can talk to.

func (*A2AService) Handler

func (b *A2AService) Handler() http.Handler

func (*A2AService) Info

func (b *A2AService) Info() *api.ServiceInfo

func (*A2AService) Init

func (s *A2AService) Init(ctx context.Context) error

func (*A2AService) Probe

func (s *A2AService) Probe(ctx context.Context) error

Probe asks the backend for its agent card, which is the protocol's own definition of ready: an A2A agent is up exactly when it serves its card. Gating advertisement on it lets a service be declared before its agent is (a sandbox that has not bound its port yet probes as down and stays out of discovery). Deliberately not cached, like the MCP probe.

func (*A2AService) Teardown

func (b *A2AService) Teardown() error

Teardown kills the command backend's process, if any. The bridge's stdout reader reaps it, and has already done so for a backend that exited on its own, so an already-finished process is not an error.

type AgentMeshNode

type AgentMeshNode struct {
	Host         host.Host
	Directory    Directory
	PubSub       *pubsub.PubSub
	Store        *Store
	RouterPeerID peer.ID

	MeshPolicyRules []biscuit.Rule

	MeshPolicyMu sync.RWMutex

	BoundHTTPAddr   string
	BoundSocketPath string
	AllowLoopback   bool

	BiscuitTimeout time.Duration
	// contains filtered or unexported fields
}

func NewAgentMeshNode

func NewAgentMeshNode(cfg Options) (*AgentMeshNode, error)

NewAgentMeshNode creates a new Agent instance secured with the 4-layer pipeline. NewAgentMeshNode initializes options and structures without starting background tasks or network interfaces.

func (*AgentMeshNode) AttachedRouters

func (n *AgentMeshNode) AttachedRouters() int

AttachedRouters is how many routers the node keeps a live session with.

func (*AgentMeshNode) Authorize

func (n *AgentMeshNode) Authorize(rawToken []byte, req RequestContext, pubKey ed25519.PublicKey) error

func (*AgentMeshNode) CallMCPTool

func (n *AgentMeshNode) CallMCPTool(ctx context.Context, targetPeer peer.ID, toolName string, params any, requiredLabels map[string]string) (*mcp.CallToolResult, error)

CallMCPTool opens a stream to a remote peer, performs the handshake, and calls a tool. requiredLabels, when non-empty, fail-closed verifies the peer's control-plane-attested labels (see checkPeerLabels) before the tool is invoked; nil means no caller requirement, though the operator's egress floor, if configured, is still enforced.

func (*AgentMeshNode) ConnectAndAuthWithRouter

func (n *AgentMeshNode) ConnectAndAuthWithRouter(ctx context.Context, addr multiaddr.Multiaddr) error

ConnectAndAuthWithRouter connects to and authenticates with every router behind addr: one peer for a direct address, every router behind the name for a dnsaddr. They are dialed at once and all are waited for; it succeeds when at least one admitted this node.

func (*AgentMeshNode) ConnectMCPSession

func (n *AgentMeshNode) ConnectMCPSession(ctx context.Context, targetPeer peer.ID, targetService string, requiredLabels map[string]string) (*mcp.ClientSession, func(), error)

func (*AgentMeshNode) DeviceLogin

func (n *AgentMeshNode) DeviceLogin(ctx context.Context, deviceAuthURL, tokenURL, clientID, audience string, requestRefresh bool) (string, error)

DeviceLogin performs OAuth 2.0 Device Authorization Grant (RFC 8628).

func (*AgentMeshNode) DiscoverEndpoints

func (n *AgentMeshNode) DiscoverEndpoints(ctx context.Context, issuerURL string) (tokenURL, authURL string, err error)

DiscoverEndpoints discovers both token and authorization endpoints.

func (*AgentMeshNode) DiscoverEndpointsWithDevice

func (n *AgentMeshNode) DiscoverEndpointsWithDevice(ctx context.Context, issuerURL string) (*OIDCEndpoints, error)

DiscoverEndpointsWithDevice discovers token, authorization and device authorization endpoints.

func (*AgentMeshNode) DiscoverRemoteServices

func (n *AgentMeshNode) DiscoverRemoteServices(ctx context.Context, serviceType api.ServiceType, serviceName string) ([]*api.DiscoveredProvider, error)

DiscoverRemoteServices dispatches to the named or type-only path based on whether serviceName is provided.

func (*AgentMeshNode) DiscoverRemoteServicesStream

func (n *AgentMeshNode) DiscoverRemoteServicesStream(ctx context.Context, serviceType api.ServiceType, serviceName string) (<-chan *api.DiscoveredProvider, error)

DiscoverRemoteServicesStream performs service discovery and streams results down the returned channel. The channel is closed automatically when discovery completes or the context is cancelled.

func (*AgentMeshNode) DiscoverTokenURL

func (n *AgentMeshNode) DiscoverTokenURL(ctx context.Context, issuerURL string) (string, error)

DiscoverTokenURL discovers the token URL from the OIDC issuer.

func (*AgentMeshNode) Enroll

func (n *AgentMeshNode) Enroll(ctx context.Context, controlPlaneURL string, jwt string) error

func (*AgentMeshNode) EnrollBootstrap

func (n *AgentMeshNode) EnrollBootstrap(ctx context.Context, controlPlaneURL string, bootstrapToken string) error

EnrollBootstrap enrolls the node with the control plane using a pre-shared bootstrap token. If the enrollment status is PENDING, it polls the status endpoint until approved or rejected.

func (*AgentMeshNode) ExchangeSubjectJWT

func (n *AgentMeshNode) ExchangeSubjectJWT(ctx context.Context, subjectToken, subjectTokenType string, taskRule *api.TaskAuthorizationRule, seal bool) (*api.TokenExchangeResponse, error)

ExchangeSubjectJWT calls POST /token/exchange on the Control Plane to verify an external JWT (OIDC, K8s SA, SPIFFE JWT-SVID) and mint a short-lived Delegated Session Biscuit bound to this node. Unattenuated, unsealed exchanges are cached in memory by SHA-256 of the subject JWT.

func (*AgentMeshNode) FetchJWT

func (n *AgentMeshNode) FetchJWT(ctx context.Context, tokenURL, clientID, clientSecret string) (string, error)

FetchJWT fetches a JWT token using the Client Credentials flow.

func (*AgentMeshNode) FindProvidersByName

func (n *AgentMeshNode) FindProvidersByName(ctx context.Context, serviceType api.ServiceType, serviceName string) ([]peer.AddrInfo, error)

FindProvidersByName returns peers hosting a specific {type, name} service.

func (*AgentMeshNode) FindProvidersByType

func (n *AgentMeshNode) FindProvidersByType(ctx context.Context, serviceType api.ServiceType) ([]peer.AddrInfo, error)

FindProvidersByType returns peers hosting at least one service of the given type.

func (*AgentMeshNode) GetIdentity

func (n *AgentMeshNode) GetIdentity() []byte

GetIdentity returns the node's biscuit identity, caching it in memory.

func (*AgentMeshNode) GetRequestIdentity

func (n *AgentMeshNode) GetRequestIdentity(ctx context.Context) []byte

GetRequestIdentity returns the caller Biscuit from ctx when present, falling back to the node's own enrolled Biscuit identity.

func (*AgentMeshNode) HandleAuthHandshake

func (n *AgentMeshNode) HandleAuthHandshake(s network.Stream)

HandleAuthHandshake is the core libp2p stream handler for /mesh/auth/1.0.0. This is the "Admission Office" of the mesh node.

func (*AgentMeshNode) HandleGoAway

func (n *AgentMeshNode) HandleGoAway(ctx context.Context, s network.Stream)

HandleGoAway takes a router's word that it will no longer hold this node: the node lets the router go, stays off it for the time the router named and attaches elsewhere now, rather than when the connection dies. Only a router the node holds is listened to; anyone may open the stream.

func (*AgentMeshNode) HandleMCPStream

func (n *AgentMeshNode) HandleMCPStream(s network.Stream, reqCtx RequestContext)

HandleMCPStream is the libp2p stream handler for the MCP protocol. It routes the authenticated stream to the appropriate backend service, or serves the internal MCP catalog if the TargetService is empty/catalog.

func (*AgentMeshNode) InteractiveLogin

func (n *AgentMeshNode) InteractiveLogin(ctx context.Context, authURL, tokenURL, clientID, audience string, requestRefresh bool, headless bool) (string, error)

InteractiveLogin prompts the user to go to a URL and enter a code.

func (*AgentMeshNode) InteractiveLoginWithDeviceAuth

func (n *AgentMeshNode) InteractiveLoginWithDeviceAuth(ctx context.Context, authURL, tokenURL, deviceAuthURL, clientID, audience string, requestRefresh bool, headless bool) (string, error)

InteractiveLoginWithDeviceAuth authenticates using AuthModeAuto: it prefers the OAuth Device Authorization Grant in headless mode when the provider exposes a device authorization endpoint, and otherwise uses the loopback browser flow with a device fallback.

func (*AgentMeshNode) InteractiveLoginWithMode

func (n *AgentMeshNode) InteractiveLoginWithMode(ctx context.Context, authURL, tokenURL, deviceAuthURL, clientID, audience string, requestRefresh bool, headless bool, mode AuthMode) (string, error)

InteractiveLoginWithMode authenticates the user using an explicit AuthMode, letting callers (e.g. CUJ harnesses) force a deterministic flow instead of relying on headless environment detection.

func (*AgentMeshNode) IsBiscuitRevoked

func (n *AgentMeshNode) IsBiscuitRevoked(b *biscuit.Biscuit) bool

IsBiscuitRevoked checks whether any block of b has been revoked.

func (*AgentMeshNode) IsConnected

func (n *AgentMeshNode) IsConnected() bool

func (*AgentMeshNode) IsServiceRegistered

func (n *AgentMeshNode) IsServiceRegistered(serviceName string) bool

func (*AgentMeshNode) ListLocalServices

func (n *AgentMeshNode) ListLocalServices(typeFilter api.ServiceType) []*api.ServiceInfo

ListLocalServices returns services registered on this node. If typeFilter is SERVICE_TYPE_UNSPECIFIED, all services are returned.

func (*AgentMeshNode) LoadControlPlaneURL

func (n *AgentMeshNode) LoadControlPlaneURL() (string, error)

func (*AgentMeshNode) LoadMeshConfig

func (n *AgentMeshNode) LoadMeshConfig() ([]byte, []string, error)

func (*AgentMeshNode) MintBorderJWT

func (n *AgentMeshNode) MintBorderJWT(ctx context.Context, callerBiscuit []byte, destination, audience string) (*api.STSTokenResponse, error)

MintBorderJWT calls POST /sts/token on the Control Plane to verify a caller Biscuit for an egress destination and mint a short-lived ES256 JWT for cloud STS federation. Minted JWTs are cached in memory until 10s before expiry.

func (*AgentMeshNode) ReEnrollWithRefreshToken

func (n *AgentMeshNode) ReEnrollWithRefreshToken(ctx context.Context) error

ReEnrollWithRefreshToken re-enrolls over HTTP with a JWT from the stored refresh token, keeping the PeerID. Must not touch n.Host: startup recovery runs it before the host exists, and the mobile app on a never-started node.

func (*AgentMeshNode) RefreshEnrollment

func (n *AgentMeshNode) RefreshEnrollment(ctx context.Context) error

RefreshEnrollment trades the expiring biscuit token for a new one using a cryptographic challenge.

func (*AgentMeshNode) RefreshJWT

func (n *AgentMeshNode) RefreshJWT(ctx context.Context, tokenURL, clientID, clientSecret, refreshToken string) (string, string, error)

RefreshJWT refreshes the OIDC token using the stored refresh token.

func (*AgentMeshNode) RefreshRouters

func (n *AgentMeshNode) RefreshRouters(ctx context.Context) error

RefreshRouters re-reads the routers from the control plane.

func (*AgentMeshNode) RegisterService

func (n *AgentMeshNode) RegisterService(ctx context.Context, req *api.RegisterServiceRequest) error

func (*AgentMeshNode) RegisterStaticServices

func (n *AgentMeshNode) RegisterStaticServices(ctx context.Context, services []api.ServiceConfig) error

func (*AgentMeshNode) RevokeBiscuitID

func (n *AgentMeshNode) RevokeBiscuitID(revocationID string, expiry time.Time)

RevokeBiscuitID records a Biscuit revocation ID (base64url- or hex-encoded) as revoked until expiry.

func (*AgentMeshNode) RevokeBiscuitToken

func (n *AgentMeshNode) RevokeBiscuitToken(rawToken []byte, expiry time.Time) (string, error)

RevokeBiscuitToken revokes the outermost block of a Biscuit token locally. Revoking the final block's RevocationId invalidates that task token and any further attenuated descendants without revoking the parent token.

func (*AgentMeshNode) SaveMeshConfig

func (n *AgentMeshNode) SaveMeshConfig(pubKey []byte, addrs []string) error

func (*AgentMeshNode) SetIdentityCache

func (n *AgentMeshNode) SetIdentityCache(b []byte)

SetIdentityCache explicitly updates the cached identity.

func (*AgentMeshNode) SetTokenSource

func (n *AgentMeshNode) SetTokenSource(ts TokenSource)

SetTokenSource configures the live platform/OIDC token source presented as TokenRefreshRequest.jwt during RefreshEnrollment.

func (*AgentMeshNode) Start

func (n *AgentMeshNode) Start(ctx context.Context) error

Start initializes the libp2p host, DHT, connects to the routers, and starts runtime components.

func (*AgentMeshNode) StartIngressServer

func (n *AgentMeshNode) StartIngressServer(ctx context.Context) error

func (*AgentMeshNode) StartRenewalLoop

func (n *AgentMeshNode) StartRenewalLoop(ctx context.Context, issuerURL, clientID, clientSecret, jwtPath string)

func (*AgentMeshNode) StartRenewalLoopWithSource

func (n *AgentMeshNode) StartRenewalLoopWithSource(ctx context.Context, src TokenSource)

func (*AgentMeshNode) SyncControlPlane

func (n *AgentMeshNode) SyncControlPlane(ctx context.Context) error

SyncControlPlane is the node's single pull from the control plane. Each part is attempted even when another fails, so a policy outage does not stop a key rotation from landing; the errors are reported together. Called once before Start, so the node dials the routers the control plane knows now and enforces the bans it holds now, and then by the sync loop.

A 401 to this node's own calls means the control plane no longer knows it (a control plane that lost its store but kept its keys); with a bootstrap token at hand the node enrolls again and the pull is repeated once.

func (*AgentMeshNode) Teardown

func (n *AgentMeshNode) Teardown() error

Teardown withdraws the node's records from the directory, detaches all registered services and closes the libp2p host. Store is owned by the caller and is not closed here.

func (*AgentMeshNode) TopUp

func (n *AgentMeshNode) TopUp(ctx context.Context) int

TopUp attaches to more routers from what the node knows and returns how many it then keeps.

func (*AgentMeshNode) UnregisterService

func (n *AgentMeshNode) UnregisterService(ctx context.Context, serviceName string) error

func (*AgentMeshNode) UpdateRelays

func (n *AgentMeshNode) UpdateRelays(addrs []multiaddr.Multiaddr)

UpdateRelays updates the current relays used by AutoRelay.

func (*AgentMeshNode) VerifyBiscuitToken

func (n *AgentMeshNode) VerifyBiscuitToken(biscuitBytes []byte, reqCtx RequestContext) error

VerifyBiscuitToken checks revocation, cache, and evaluates the token against trusted keys and local policies.

func (*AgentMeshNode) VerifyLocalBiscuit

func (n *AgentMeshNode) VerifyLocalBiscuit(rawToken []byte) (*identity.VerifiedBiscuitClaims, error)

VerifyLocalBiscuit verifies a raw Biscuit against the node's revocation cache, banned peer cache, and trusted Control Plane keys, returning its extracted claims and TaskAuthorizationRule chain.

func (*AgentMeshNode) VerifyPeerLabels

func (n *AgentMeshNode) VerifyPeerLabels(ctx context.Context, peerID peer.ID, required map[string]string) error

VerifyPeerLabels is VerifyProvider for a peer reached for no named service: its catalog, or a call that names the peer alone.

func (*AgentMeshNode) VerifyProvider

func (n *AgentMeshNode) VerifyProvider(ctx context.Context, peerID peer.ID, required map[string]string, service string) error

VerifyProvider ensures the peer is a provider this node may send a request to: it holds a control-plane-attested credential bound to it, with labels satisfying every pair of the caller's requirement and every pair of the operator's egress floor, and, when the call names a service ("<type>://<name>"), one that grants serving it: a member that announced a name it may not serve is refused here whatever the directory says. Positive verdicts are cached.

The gate runs whenever either exists. A caller that requires nothing is still held to the floor — the whole point of a floor is that the party being constrained does not get to opt out of it by saying nothing.

func (*AgentMeshNode) WantRouters

func (n *AgentMeshNode) WantRouters() int

WantRouters is how many routers the node keeps.

func (*AgentMeshNode) WithBiscuitAuth

func (n *AgentMeshNode) WithBiscuitAuth(next func(network.Stream, RequestContext)) network.StreamHandler

WithBiscuitAuth enforces a Protobuf handshake on a stream before calling the next handler.

type AuthMode

type AuthMode string

AuthMode selects how interactive enrollment authenticates the user.

const (
	// AuthModeAuto prefers device flow in headless environments (when the
	// provider advertises one) and the loopback browser flow otherwise, with an
	// automatic device fallback when the browser can't be opened.
	AuthModeAuto AuthMode = "auto"
	// AuthModeDevice forces the OAuth 2.0 Device Authorization Grant (RFC 8628).
	AuthModeDevice AuthMode = "device"
	// AuthModeOOB forces the out-of-band code-paste flow.
	AuthModeOOB AuthMode = "oob"
	// AuthModeBrowser forces the loopback browser (authorization code) flow.
	AuthModeBrowser AuthMode = "browser"
)

func ParseAuthMode

func ParseAuthMode(s string) (AuthMode, error)

ParseAuthMode validates a user-provided --auth-mode value. An empty string maps to AuthModeAuto.

type CallRemoteToolParams

type CallRemoteToolParams struct {
	PeerID         string         `json:"peer_id" jsonschema:"The Peer ID of the target agent"`
	ToolName       string         `json:"tool_name" jsonschema:"The name of the server to call"`
	Arguments      map[string]any `` /* 177-byte string literal not displayed */
	RequiredLabels string         `` /* 224-byte string literal not displayed */
}

CallRemoteToolParams defines the parameters for the call_remote_tool tool.

Arguments is a JSON object whose shape matches the target server's input_schema (use describe_remote_tool to fetch it). Earlier revisions took a stringified JSON blob here; that footgun is gone.

type ClientCredentialsTokenSource

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

ClientCredentialsTokenSource fetches a JWT via OAuth2 client_credentials against an OIDC issuer.

func NewClientCredentialsTokenSource

func NewClientCredentialsTokenSource(n *AgentMeshNode, issuerURL, clientID, clientSecret string) *ClientCredentialsTokenSource

NewClientCredentialsTokenSource creates a TokenSource that exchanges client credentials at issuerURL's token endpoint.

func (*ClientCredentialsTokenSource) FetchToken

FetchToken discovers the OIDC token endpoint and fetches a fresh JWT.

type CloudTokenExchanger

type CloudTokenExchanger = credprovider.Exchanger

CloudTokenExchanger is an alias for credprovider.Exchanger.

type DescribeRemoteToolParams

type DescribeRemoteToolParams struct {
	PeerID   string `json:"peer_id" jsonschema:"Peer ID of the node hosting the server. Required."`
	ToolName string `` /* 135-byte string literal not displayed */
}

DescribeRemoteToolParams defines parameters for the describe_remote_tool sidecar tool.

type Directory

type Directory interface {
	// Provide announces this member as a provider of key, at the
	// addresses it announces, to a router it is attached to; the router
	// keeps the record and places it on the routers closest to the key.
	// service is what the record is about, "<type>://<name>", and "" for
	// the member's own record under its peer key.
	Provide(ctx context.Context, key []byte, service string) error
	// Withdraw removes this member's record under key from the router it is
	// attached to and from the routers the record was placed on.
	Withdraw(ctx context.Context, key []byte) error
	// FindProviders is who provides key, up to limit, with their addresses.
	FindProviders(ctx context.Context, key []byte, limit int) ([]peer.AddrInfo, error)
	// FindPeer is where p is reached; routing.ErrNotFound when nobody knows.
	FindPeer(ctx context.Context, p peer.ID) (peer.AddrInfo, error)
}

Directory is the mesh's directory as a member sees it: where it announces what it serves and where it is reached, and where it looks peers and services up. The routers the member is attached to answer for it over api.DirectoryProtocolID; the member keeps no DHT of its own.

type DiscoverRemoteServicesParams

type DiscoverRemoteServicesParams struct {
	Type   string `json:"type" jsonschema:"Required. One of: mcp, inference, a2a."`
	Name   string `json:"name,omitempty" jsonschema:"Optional service name. Omit to list all services of the given type."`
	Limit  int    `json:"limit,omitempty" jsonschema:"Optional limit for pagination. Defaults to 20."`
	Offset int    `json:"offset,omitempty" jsonschema:"Optional offset for pagination. Defaults to 0."`
}

DiscoverRemoteServicesParams defines the parameters for the discover_remote_services tool.

type EgressFacts

type EgressFacts struct {
	Host string
	Port int
}

EgressFacts is the destination of an egress request.

type EgressService

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

EgressService serves egress://<name>: this node is the HTTP origin for one destination outside the mesh. The destination, where to forward, and which credential to present are the control plane's decision (an EgressDestination that selected this node); the node holds no policy of its own about it. Every request reaches the handler only after Authorize ran with the caller's credential and the method, path, host and port facts.

func (*EgressService) Handler

func (s *EgressService) Handler() http.Handler

func (*EgressService) Info

func (s *EgressService) Info() *api.ServiceInfo

func (*EgressService) Init

func (s *EgressService) Init(ctx context.Context) error

Init builds the reverse proxy and confirms the named credential is readable, so a destination whose credential the platform did not deliver is refused here, visibly, instead of answering 502 to every request.

func (*EgressService) ServeTunnel

func (s *EgressService) ServeTunnel(ctx context.Context, w http.ResponseWriter, r *http.Request, reqPort int)

ServeTunnel handles a named TCP CONNECT tunnel on an EGRESS_MODE_TCP EgressService. It enforces the ports allow-list before hijacking, reads the client's TLS ClientHello and verifies that SNI matches destination.Name (and that ECH is absent) before dialing upstream, and audits bytes in each direction and duration.

func (*EgressService) SetExchanger

func (s *EgressService) SetExchanger(ex CloudTokenExchanger)

SetExchanger overrides the CloudTokenExchanger on s (used by tests and custom brokers).

func (*EgressService) Teardown

func (s *EgressService) Teardown() error

type FileTokenSource

type FileTokenSource = cpclient.FileTokenSource

FileTokenSource reads a JWT from a file path (e.g. a Kubernetes projected ServiceAccount token volume or a SPIRE spiffe-helper JWT-SVID file).

type FindRemoteToolsParams

type FindRemoteToolsParams struct {
	Intent      string `` /* 170-byte string literal not displayed */
	PeerID      string `json:"peer_id,omitempty" jsonschema:"Restrict the search to a single peer. Empty means search the whole mesh."`
	ServiceName string `` /* 166-byte string literal not displayed */
	ToolName    string `` /* 223-byte string literal not displayed */
}

FindRemoteToolsParams defines the parameters for the find_remote_tools tool.

type GCPMetadataTokenSource

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

GCPMetadataTokenSource fetches a Google-signed OIDC ID token from the GCE or Cloud Run instance metadata server.

func NewGCPMetadataTokenSource

func NewGCPMetadataTokenSource(audience, endpoint string, httpClient *http.Client) *GCPMetadataTokenSource

NewGCPMetadataTokenSource creates a TokenSource targeting the GCE/Cloud Run service account identity metadata endpoint with format=full.

func (*GCPMetadataTokenSource) FetchToken

func (s *GCPMetadataTokenSource) FetchToken(ctx context.Context) (string, error)

FetchToken requests an OIDC identity token from the GCP metadata server.

type GetMeshInfoParams

type GetMeshInfoParams struct{}

GetMeshInfoParams defines the parameters for the get_mesh_info tool.

type HTTPRequestFacts

type HTTPRequestFacts struct {
	Method string
	Path   string
}

HTTPRequestFacts is what an HTTP request contributes to policy.

type InferenceEngine

type InferenceEngine interface {
	// Models returns the model IDs the backend currently serves.
	Models(ctx context.Context) ([]string, error)
}

InferenceEngine is the connector between Agent Mesh and an inference backend. Implementations adapt one backend family; the service and facade layers stay backend-agnostic.

type InferenceService

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

InferenceService provides intelligent LLM gateway features: traffic routing and token usage tracking for OpenAI-compatible endpoints.

func (*InferenceService) ActiveRequests

func (s *InferenceService) ActiveRequests() uint32

ActiveRequests reports in-flight requests, a load hint for announcements.

func (*InferenceService) Handler

func (b *InferenceService) Handler() http.Handler

func (*InferenceService) Info

func (b *InferenceService) Info() *api.ServiceInfo

func (*InferenceService) Init

func (s *InferenceService) Init(ctx context.Context) error

func (*InferenceService) Models

func (s *InferenceService) Models(ctx context.Context) ([]string, error)

Models returns the model IDs the backend serves, cached briefly since both the discovery announcer and the OpenAI facade call it repeatedly.

func (*InferenceService) Teardown

func (b *InferenceService) Teardown() error

Teardown kills the command backend's process, if any. The bridge's stdout reader reaps it, and has already done so for a backend that exited on its own, so an already-finished process is not an error.

type ListLocalServicesParams

type ListLocalServicesParams struct {
	Type string `json:"type,omitempty" jsonschema:"Optional service type filter (mcp, inference, a2a). Empty means all types."`
}

ListLocalServicesParams defines the parameters for the list_local_services tool.

type MCPService

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

MCPService extends baseService to handle MCP protocol proxying.

func (*MCPService) HandleStreamPassThrough

func (m *MCPService) HandleStreamPassThrough(s network.Stream, reqCtx RequestContext)

HandleStreamPassThrough connects to the backend and proxies JSON-RPC messages.

func (*MCPService) Handler

func (b *MCPService) Handler() http.Handler

func (*MCPService) Info

func (b *MCPService) Info() *api.ServiceInfo

func (*MCPService) Init

func (m *MCPService) Init(ctx context.Context) error

Init initializes the base service.

func (*MCPService) Probe

func (m *MCPService) Probe(ctx context.Context) error

Probe reports whether the backend actually speaks MCP, by completing an initialize against it.

Deliberately weaker than Tools: a backend serving only resources or prompts has no tools and is still a working MCP server, so an empty tool list is no reason to withhold it. Failing to initialize is — that is a backend which is down, or was never an MCP server to begin with.

The result is deliberately not cached. Callers are the registry's advertise path, which asks once per service per reprovide, so the cost is negligible; caching would make a backend that has just come up wait out the TTL, which is the delay this gating exists to avoid.

func (*MCPService) Teardown

func (m *MCPService) Teardown() error

Teardown chains to baseService.Teardown.

func (*MCPService) Tools

func (m *MCPService) Tools(ctx context.Context) ([]string, error)

Tools lists the backend's tool names (sorted), cached briefly since the discovery announcer polls it on every tick.

type NodeConfigComplete

type NodeConfigComplete struct {
	Policies []biscuit.Policy
	Checks   []biscuit.Check
	Rules    []biscuit.Rule
	Services []api.ServiceConfig
	Labels   map[string]string

	// EgressRequireLabels is the operator's egress floor (api.Egress). Nil
	// means no floor, so a caller's requirement — or the absence of one —
	// stands on its own, as it always has.
	EgressRequireLabels map[string]string
}

func CompleteNodeConfig

func CompleteNodeConfig(config api.NodeConfig) (*NodeConfigComplete, error)

CompleteNodeConfig validates the services and labels and parses the Datalog of a decoded node config. Shared with the mobile FFI so both report the same errors.

func LoadNodeConfig

func LoadNodeConfig(path string) (*NodeConfigComplete, error)

LoadNodeConfig loads the node configuration from the specified path. If the file is missing, it returns an empty initialized config.

type OIDCEndpoints

type OIDCEndpoints struct {
	TokenURL      string
	AuthURL       string
	DeviceAuthURL string
}

OIDCEndpoints contains discovered OIDC endpoint URLs.

type Options

type Options struct {
	PrivKey            crypto.PrivKey
	ControlPlanePubKey ed25519.PublicKey
	RouterAddrs        []multiaddr.Multiaddr
	Store              *Store

	DiscoveryInterval string
	ListenAddrs       []string
	EnableRelay       bool
	NodeConfig        *NodeConfigComplete
	KeyGracePeriod    time.Duration
	AllowLoopback     bool
	// AnnouncePrivateAddrs controls whether RFC1918/ULA addresses are published
	// to the mesh. Nil means true: private meshes reach each other over exactly
	// those addresses. Set false on nodes that are only reachable via routers or
	// public addresses, so peers do not learn the host's internal topology.
	AnnouncePrivateAddrs *bool
	// Reachability is how the node decides whether peers can dial it
	// directly. ReachabilityPrivate, the default, assumes they cannot: the
	// node always holds a relay reservation with the routers and is reached
	// through them, which works behind any NAT and needs nothing configured.
	// ReachabilityAuto lets AutoNAT v2 decide from dial-backs by the routers:
	// a node they can reach on a public address advertises that address and
	// holds no reservation, so direct dials replace relayed ones and the
	// routers carry only the members that need them. Auto is only right
	// where the routers sit on the public side of every NAT the node is
	// behind: a router in the same cluster or LAN can reach a node that the
	// rest of the mesh cannot, and would make it unreachable.
	Reachability         Reachability
	MonitorBootstrap     time.Duration
	MonitorInterval      time.Duration
	AutoRelayMinInterval time.Duration
	AutoRelayBootDelay   time.Duration
	AutoRelayBackoff     time.Duration
	// RouterConnectTimeout bounds each router address's dial (connect + stream open).
	RouterConnectTimeout time.Duration
	// RouterRedialDelay is how long after a router session drops the node
	// waits before dialing that router again; each further attempt waits
	// twice as long, up to RouterRedialAttempts of them. Zero uses the
	// default; negative disables the redial, leaving a dropped router to the
	// connection monitor.
	RouterRedialDelay    time.Duration
	RouterRedialAttempts int
	// RouterAuthAttempts is how many times Start, and the handshake after
	// an enrollment, dial the routers before giving up, RouterRedialDelay
	// doubling between attempts. Zero uses the default.
	RouterAuthAttempts int
	// Routers is how many routers the node keeps a session with, out of
	// those the control plane lists; every router when there are fewer.
	// Zero uses DefaultRouters. A session that drops is redialled, and a
	// router that does not come back is replaced from the list.
	Routers int
	// RouterSelector names labels a router must attest for the node to
	// attach to it, every pair; RouterPrefer names labels whose routers the
	// node attaches to first, the more pairs attested the earlier. Among
	// routers equal on preference the node takes the ones with the most
	// room. Both are matched against the labels /info lists for a router,
	// which are the ones the control plane attested at its enrollment.
	RouterSelector map[string]string
	RouterPrefer   map[string]string
	// RouterShunDuration is how long the node stays off a router that told
	// it to go away or that did not come back on redial. Zero uses the
	// default.
	RouterShunDuration time.Duration
	// BiscuitTimeout bounds Datalog evaluation when verifying biscuit tokens.
	BiscuitTimeout time.Duration
	// DHT Options
	DHTLookupLimit       int
	DiscoveryConcurrency int
	// RequiredRole restricts enrollment and startup to only accept tokens containing this role.
	RequiredRole string
	// ControlPlaneSyncInterval is how often the node pulls what it reads from
	// the control plane: signing keys, ban set and router addresses, mesh
	// policy. Zero uses the default; negative disables the loop.
	ControlPlaneSyncInterval time.Duration
	// ControlPlaneSyncJitter is the maximum random delay before a sync that a
	// gossip event asked for, so a fleet told at once does not pull at once.
	// Zero uses a tenth of ControlPlaneSyncInterval: the spread has to grow
	// with the fleet's cadence, or a policy update on a large mesh is a
	// stampede.
	ControlPlaneSyncJitter time.Duration
	// BootstrapTokenPath is the file the node's bootstrap (join) token is
	// read from. A node that has it can enroll again on its own when the
	// control plane answers 401 to an authenticated call, which is what a
	// control plane that lost its store (a new Cloud Run revision without a
	// database) does; the token is read again each time so a rotated token
	// is picked up. Empty leaves recovery to the renewal loop.
	BootstrapTokenPath string
	// BackendProbeTimeout bounds how long a command-spawned service backend
	// (agentmesh-node.yaml's `command`, spawned as a local subprocess) is given to
	// answer before the service is registered but withheld from
	// advertisement. Zero uses the library default (2s). Raise this for
	// backends with slower cold-start/import costs than that - the default
	// is tight enough that even simple interpreted-language MCP servers can
	// miss it on first spawn.
	BackendProbeTimeout time.Duration
	// SecretsDir is where the node resolves the credential names the control
	// plane assigns with egress destinations: one file per name, put there by
	// the platform (a Secret volume, a vault agent). Zero uses DefaultSecretsDir.
	SecretsDir string
	// CatalogReportInterval specifies how often the node self-reports its
	// locally registered services to the control plane (POST
	// /nodes/catalog), so an admin can see mesh-wide service topology
	// without the control plane needing DHT/P2P access to every node
	// itself. Zero uses the default.
	CatalogReportInterval time.Duration
	// CatalogReportInitialDelay is how long after Start the first catalog
	// report is sent, so services configured at startup have registered by
	// then. Zero uses the default.
	CatalogReportInitialDelay time.Duration
	// TokenSource is the optional live platform/OIDC token provider presented
	// as TokenRefreshRequest.jwt during RefreshEnrollment.
	TokenSource TokenSource
}

Options holds all configuration options for a AgentMeshNode.

func (*Options) Default

func (o *Options) Default()

Default applies default values to Options if they are not specified.

func (*Options) Validate

func (o *Options) Validate() error

Validate verifies that the required options are provided and valid.

type Reachability

type Reachability string

Reachability is the value of Options.Reachability and of --reachability.

const (
	ReachabilityPrivate Reachability = "private"
	ReachabilityAuto    Reachability = "auto"
)

type RefreshError

type RefreshError struct {
	StatusCode int
	Message    string
}

func (*RefreshError) Error

func (e *RefreshError) Error() string

type RefreshTokenSource

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

RefreshTokenSource exchanges a stored OIDC refresh token for a fresh JWT.

func NewRefreshTokenSource

func NewRefreshTokenSource(n *AgentMeshNode, clientSecret string) *RefreshTokenSource

NewRefreshTokenSource creates a TokenSource backed by the node's persisted OIDC refresh token.

func (*RefreshTokenSource) FetchToken

func (s *RefreshTokenSource) FetchToken(ctx context.Context) (string, error)

FetchToken exchanges the stored refresh token for a new ID/access token.

type RequestContext

type RequestContext struct {
	PeerID   peer.ID
	User     string
	Group    string
	Protocol string
	Target   string

	// HTTP is set when the node handles the request as HTTP: the method as
	// received and the path as the backend sees it. Injected as method() and
	// path() facts, taken from the wire and never from the caller's token. A
	// tunnel the node opens without terminating HTTP carries Method "CONNECT"
	// and an empty Path. Nil on a stream that carries no HTTP request.
	HTTP *HTTPRequestFacts

	// Egress is set on a request for an egress destination: the hostname and
	// port the node connects to, injected as host() and port() facts.
	Egress *EgressFacts

	// Local marks a request this node makes for one of its own clients over the
	// local API, for a destination it serves itself. The caller is then this
	// node, evaluated on its own credential, and the target check is satisfied
	// because a node is always allowed to reach itself. Never set from the wire.
	Local bool

	// MCPTool is set when evaluating a specific MCP tools/call invocation.
	MCPTool string

	// AllowMCPStreamInit is set when an MCP request is a session handshake or
	// discovery method (initialize, ping, tools/list).
	AllowMCPStreamInit bool

	// TaskRules holds the verified TaskAuthorizationRule chain extracted from
	// the caller's Biscuit during stream authentication so downstream stream
	// handlers (such as MCP pass-through) can enforce tool-level constraints.
	TaskRules []*api.TaskAuthorizationRule
}

RequestContext carries the security metadata for a specific stream request

type Service

type Service interface {
	Info() *api.ServiceInfo
	Init(ctx context.Context) error
	Handler() http.Handler
	Teardown() error
}

Service is the contract the ServiceRegistry and ingress server use. Implementations own all type-specific behaviour; the registry stays type-agnostic.

func NewServiceFromRequest

func NewServiceFromRequest(req *api.RegisterServiceRequest) (Service, error)

type ServiceRegistry

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

ServiceRegistry is the type-agnostic owner of registered services.

func NewServiceRegistry

func NewServiceRegistry(d directoryProvider, backendProbeTimeout time.Duration) *ServiceRegistry

NewServiceRegistry constructs a registry bounding backend probes by backendProbeTimeout. A zero or negative value falls back to defaultDHTProbeTimeout, so callers can pass an unset Options.BackendProbeTimeout straight through without an explicit zero-check.

func (*ServiceRegistry) Get

func (r *ServiceRegistry) Get(name string) (Service, bool)

Get returns the service registered under name, if any.

func (*ServiceRegistry) GetTyped

func (r *ServiceRegistry) GetTyped(t api.ServiceType, name string) (Service, bool)

GetTyped returns the service registered under name only if it is of type t. Dispatch after authorization must use this: the policy was evaluated on t://name, and a service of another type under that name is not what the caller was granted.

func (*ServiceRegistry) List

func (r *ServiceRegistry) List(typeFilter api.ServiceType) []*api.ServiceInfo

List returns the ServiceInfo for every registered service, optionally filtered by type. SERVICE_TYPE_UNSPECIFIED means "all types."

func (*ServiceRegistry) Register

func (r *ServiceRegistry) Register(ctx context.Context, svc Service) error

Register initialises a service, advertises it on the DHT, and inserts it into the map. Init runs before Provide so a failed handler-build never briefly advertises an unservable name.

A backend that does not answer is registered but not advertised, rather than rejected: backends routinely start after the node does, and the reprovide loop picks them up once they answer.

registering a name again replaces the instance and tears the old one down

func (*ServiceRegistry) ReprovideAll

func (r *ServiceRegistry) ReprovideAll(ctx context.Context) int

ReprovideAll re-provides all registered services to the DHT concurrently and reports how many were withheld because their backend did not answer. A service whose backend has stopped answering falls out of the DHT by not being reprovided, and returns on a later tick once it answers again.

func (*ServiceRegistry) TeardownAll

func (r *ServiceRegistry) TeardownAll()

TeardownAll calls Teardown on every registered service and clears the map. Per-service errors are logged; iteration continues.

func (*ServiceRegistry) Unregister

func (r *ServiceRegistry) Unregister(ctx context.Context, name string) error

Unregister removes the service from the map, withdraws its records from the directory and calls Teardown. The record by type stays while another service of that type is registered. Unknown names are a no-op.

func (*ServiceRegistry) WithdrawAll

func (r *ServiceRegistry) WithdrawAll(ctx context.Context)

WithdrawAll withdraws every registered service's records from the directory, by name and by type, as a node does before it leaves the mesh.

type StdioBridge

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

StdioBridge backs the POST HTTP ingress route for a command-backed service (registered via baseService.Init), which is what a mesh caller's /mesh/{peer}/mcp/{service} request lands on. Probes and tool listings go through MCPService.backendTransport and a subprocess of their own instead.

One backend process serves every authorized caller, so the bridge owns the JSON-RPC id space: each request's id is replaced with a bridge-assigned one before it reaches the backend and restored on the way out, and a response is delivered only to the request it answers. Two callers sending the same id can no longer receive each other's replies. There is no broadcast (SSE) side: with a shared process, a server-initiated message cannot be attributed to a caller, so it is not delivered to any of them.

Stdio MCP is one session per process, and a server written with the Go or TypeScript SDK refuses a second initialize on it. Every caller opens its own session, so the bridge performs the handshake once, on behalf of the first caller, and answers every later initialize from the backend's reply. What is lost is per-caller capability negotiation: all callers see what the first one negotiated.

func (*StdioBridge) ServeHTTP

func (b *StdioBridge) ServeHTTP(w http.ResponseWriter, r *http.Request)

func (*StdioBridge) Start

func (b *StdioBridge) Start()

type Store

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

Store is the node's persistent state: its private key and its api.MemberCredential, in a bbolt database whose file lock also tells a second agentmesh-node that this data directory is in use.

func NewStore

func NewStore(dir string) (*Store, error)

func (*Store) Close

func (s *Store) Close() error

func (*Store) Credential

func (s *Store) Credential() (*api.MemberCredential, error)

Credential returns a copy of everything the node persists besides its private key. A node that has not enrolled holds an empty message.

func (*Store) LoadControlPlaneURL

func (s *Store) LoadControlPlaneURL() (string, error)

func (*Store) LoadIdentity

func (s *Store) LoadIdentity() ([]byte, error)

func (*Store) LoadIdentityExpiration

func (s *Store) LoadIdentityExpiration() (int64, error)

func (*Store) LoadIdentityKeySet

func (s *Store) LoadIdentityKeySet() ([]ed25519.PublicKey, error)

LoadIdentityKeySet returns the set saved by SaveIdentityKeySet, or nil when nothing recorded it.

func (*Store) LoadKey

func (s *Store) LoadKey() ([]byte, error)

func (*Store) LoadMeshConfig

func (s *Store) LoadMeshConfig() ([]byte, []string, error)

LoadMeshConfig returns the first trusted control plane key, which is the one enrollment handed out until a rotation retires it, and the router addresses.

func (*Store) LoadOIDCConfig

func (s *Store) LoadOIDCConfig() (string, string, string, error)

func (*Store) LoadRefreshToken

func (s *Store) LoadRefreshToken() (string, error)

func (*Store) LoadTrustedKeys

func (s *Store) LoadTrustedKeys() ([]TrustedKey, error)

func (*Store) ResetMeshIdentity

func (s *Store) ResetMeshIdentity() error

ResetMeshIdentity clears everything about a node's mesh membership (its Biscuit, mesh/control-plane config, and OIDC session state) so it can join a different mesh. It keeps the long-lived libp2p key (node_private_key), so the node's PeerID survives the switch.

func (*Store) SaveControlPlaneURL

func (s *Store) SaveControlPlaneURL(url string) error

func (*Store) SaveIdentity

func (s *Store) SaveIdentity(biscuit []byte) error

func (*Store) SaveIdentityExpiration

func (s *Store) SaveIdentityExpiration(exp int64) error

func (*Store) SaveIdentityKeySet

func (s *Store) SaveIdentityKeySet(keys []ed25519.PublicKey) error

SaveIdentityKeySet records the control plane public keys known when the stored identity was issued. A key that later appears outside this set is a rotation the identity predates, which is why it survives restarts.

func (*Store) SaveKey

func (s *Store) SaveKey(key []byte) error

func (*Store) SaveMeshConfig

func (s *Store) SaveMeshConfig(pubKey []byte, addrs []string) error

SaveMeshConfig records what enrollment handed out: the control plane key that signed the biscuit and the routers to join through. The key enters the trusted set, and seeds the issuance set when nothing recorded it yet. Later calls, from the sync that follows router changes, pass the key LoadMeshConfig returned and only move the addresses.

func (*Store) SaveOIDCConfig

func (s *Store) SaveOIDCConfig(issuer, clientID, audience string) error

func (*Store) SaveRefreshToken

func (s *Store) SaveRefreshToken(token string) error

func (*Store) SaveTrustedKeys

func (s *Store) SaveTrustedKeys(keys []TrustedKey) error

SaveTrustedKeys persists the full set of control plane public keys the node currently trusts, so keys learned from rotation events or /keys survive restarts.

func (*Store) SetCredential

func (s *Store) SetCredential(c *api.MemberCredential) error

SetCredential replaces everything the node persists besides its private key; `agentmesh-node state import` uses it.

type StreamTransport

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

StreamTransport implements the mcp.Transport interface for a libp2p stream.

func NewStreamTransport

func NewStreamTransport(s network.Stream) *StreamTransport

NewStreamTransport creates a new StreamTransport for the given stream.

func (*StreamTransport) Close

func (t *StreamTransport) Close() error

Close closes the stream.

func (*StreamTransport) Connect

func (t *StreamTransport) Connect(ctx context.Context) (mcp.Connection, error)

Connect satisfies the mcp.Transport interface. For a stream, it's already connected.

func (*StreamTransport) Read

Read reads a message from the stream.

func (*StreamTransport) Send

func (t *StreamTransport) Send(data []byte) error

Send sends a message over the stream.

func (*StreamTransport) SessionID

func (t *StreamTransport) SessionID() string

SessionID satisfies the mcp.Connection interface.

func (*StreamTransport) Write

func (t *StreamTransport) Write(ctx context.Context, msg jsonrpc.Message) error

Write writes a message to the stream.

type TokenSource

type TokenSource = cpclient.TokenSource

TokenSource fetches a fresh platform or OIDC JWT for enrollment, continuous attestation at POST /refresh, or fallback re-enrollment.

func ResolveTokenSource

func ResolveTokenSource(ctx context.Context, cfg TokenSourceConfig) (TokenSource, bool, error)

ResolveTokenSource selects the TokenSource for enrollment and renewal based on the node's configuration. The returned continuousRefresh boolean is true when the source is a non-interactive workload credential (--jwt-path, --oidc-issuer, or GCP metadata) that should also be presented on every POST /refresh call via TokenRefreshRequest.jwt.

type TokenSourceConfig

type TokenSourceConfig struct {
	Node             *AgentMeshNode
	IssuerURL        string
	ClientID         string
	ClientSecret     string
	JWTPath          string
	CloudProvider    string
	Audience         string
	MetadataEndpoint string
	HTTPClient       *http.Client
}

TokenSourceConfig configures how agentmesh-node resolves its platform/OIDC JWT source.

type TrustedKey

type TrustedKey struct {
	Key        ed25519.PublicKey
	ReceivedAt time.Time
}

Jump to

Keyboard shortcuts

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