Documentation
¶
Index ¶
- Constants
- Variables
- func CallerBiscuitFromContext(ctx context.Context) []byte
- func FetchControlPlaneInfo(ctx context.Context, controlPlaneURL string) (*api.ControlPlaneInfoResponse, error)
- func FetchControlPlaneKeys(ctx context.Context, controlPlaneURL string, trusted []ed25519.PublicKey) ([]ed25519.PublicKey, error)
- func GetDefaultDataDir() (string, error)
- func GetOrGenerateKey(s *Store) crypto.PrivKey
- func NewMCPHandler(node *AgentMeshNode) http.Handler
- func NewMCPServer(node *AgentMeshNode) *mcp.Server
- func NewUnauthenticatedMCPHandler(controlPlaneURL string) http.Handler
- func NewUnauthenticatedMCPServer(controlPlaneURL string) *mcp.Server
- func ProbeGCPMetadata(ctx context.Context, endpoint string, httpClient *http.Client) bool
- func ReadStateDir(dir string) (privKey []byte, c *api.MemberCredential, err error)
- func ReportNodeCatalog(ctx context.Context, controlPlaneURL string, biscuitToken []byte, ...) error
- func SetAllowInsecureControlPlane(allow bool)
- func StartMetricsServer(node *AgentMeshNode, addr string) (*http.Server, error)
- func StartSidecarServer(node *AgentMeshNode, addr, socketPath, token, certFile, keyFile, caFile string) (*http.Server, error)
- func StartUnauthSidecarServer(controlPlaneURL, addr, socketPath, certFile, keyFile string) (*http.Server, error)
- func WithCallerBiscuit(ctx context.Context, biscuitBytes []byte) context.Context
- func WriteStateDir(dir string, privKey []byte, c *api.MemberCredential) error
- type A2AService
- type AgentMeshNode
- func (n *AgentMeshNode) AttachedRouters() int
- func (n *AgentMeshNode) Authorize(rawToken []byte, req RequestContext, pubKey ed25519.PublicKey) error
- func (n *AgentMeshNode) CallMCPTool(ctx context.Context, targetPeer peer.ID, toolName string, params any, ...) (*mcp.CallToolResult, error)
- func (n *AgentMeshNode) ConnectAndAuthWithRouter(ctx context.Context, addr multiaddr.Multiaddr) error
- func (n *AgentMeshNode) ConnectMCPSession(ctx context.Context, targetPeer peer.ID, targetService string, ...) (*mcp.ClientSession, func(), error)
- func (n *AgentMeshNode) DeviceLogin(ctx context.Context, deviceAuthURL, tokenURL, clientID, audience string, ...) (string, error)
- func (n *AgentMeshNode) DiscoverEndpoints(ctx context.Context, issuerURL string) (tokenURL, authURL string, err error)
- func (n *AgentMeshNode) DiscoverEndpointsWithDevice(ctx context.Context, issuerURL string) (*OIDCEndpoints, error)
- func (n *AgentMeshNode) DiscoverRemoteServices(ctx context.Context, serviceType api.ServiceType, serviceName string) ([]*api.DiscoveredProvider, error)
- func (n *AgentMeshNode) DiscoverRemoteServicesStream(ctx context.Context, serviceType api.ServiceType, serviceName string) (<-chan *api.DiscoveredProvider, error)
- func (n *AgentMeshNode) DiscoverTokenURL(ctx context.Context, issuerURL string) (string, error)
- func (n *AgentMeshNode) Enroll(ctx context.Context, controlPlaneURL string, jwt string) error
- func (n *AgentMeshNode) EnrollBootstrap(ctx context.Context, controlPlaneURL string, bootstrapToken string) error
- func (n *AgentMeshNode) ExchangeSubjectJWT(ctx context.Context, subjectToken, subjectTokenType string, ...) (*api.TokenExchangeResponse, error)
- func (n *AgentMeshNode) FetchJWT(ctx context.Context, tokenURL, clientID, clientSecret string) (string, error)
- func (n *AgentMeshNode) FindProvidersByName(ctx context.Context, serviceType api.ServiceType, serviceName string) ([]peer.AddrInfo, error)
- func (n *AgentMeshNode) FindProvidersByType(ctx context.Context, serviceType api.ServiceType) ([]peer.AddrInfo, error)
- func (n *AgentMeshNode) GetIdentity() []byte
- func (n *AgentMeshNode) GetRequestIdentity(ctx context.Context) []byte
- func (n *AgentMeshNode) HandleAuthHandshake(s network.Stream)
- func (n *AgentMeshNode) HandleGoAway(ctx context.Context, s network.Stream)
- func (n *AgentMeshNode) HandleMCPStream(s network.Stream, reqCtx RequestContext)
- func (n *AgentMeshNode) InteractiveLogin(ctx context.Context, authURL, tokenURL, clientID, audience string, ...) (string, error)
- func (n *AgentMeshNode) InteractiveLoginWithDeviceAuth(ctx context.Context, ...) (string, error)
- func (n *AgentMeshNode) InteractiveLoginWithMode(ctx context.Context, ...) (string, error)
- func (n *AgentMeshNode) IsBiscuitRevoked(b *biscuit.Biscuit) bool
- func (n *AgentMeshNode) IsConnected() bool
- func (n *AgentMeshNode) IsServiceRegistered(serviceName string) bool
- func (n *AgentMeshNode) ListLocalServices(typeFilter api.ServiceType) []*api.ServiceInfo
- func (n *AgentMeshNode) LoadControlPlaneURL() (string, error)
- func (n *AgentMeshNode) LoadMeshConfig() ([]byte, []string, error)
- func (n *AgentMeshNode) MintBorderJWT(ctx context.Context, callerBiscuit []byte, destination, audience string) (*api.STSTokenResponse, error)
- func (n *AgentMeshNode) ReEnrollWithRefreshToken(ctx context.Context) error
- func (n *AgentMeshNode) RefreshEnrollment(ctx context.Context) error
- func (n *AgentMeshNode) RefreshJWT(ctx context.Context, tokenURL, clientID, clientSecret, refreshToken string) (string, string, error)
- func (n *AgentMeshNode) RefreshRouters(ctx context.Context) error
- func (n *AgentMeshNode) RegisterService(ctx context.Context, req *api.RegisterServiceRequest) error
- func (n *AgentMeshNode) RegisterStaticServices(ctx context.Context, services []api.ServiceConfig) error
- func (n *AgentMeshNode) RevokeBiscuitID(revocationID string, expiry time.Time)
- func (n *AgentMeshNode) RevokeBiscuitToken(rawToken []byte, expiry time.Time) (string, error)
- func (n *AgentMeshNode) SaveMeshConfig(pubKey []byte, addrs []string) error
- func (n *AgentMeshNode) SetIdentityCache(b []byte)
- func (n *AgentMeshNode) SetTokenSource(ts TokenSource)
- func (n *AgentMeshNode) Start(ctx context.Context) error
- func (n *AgentMeshNode) StartIngressServer(ctx context.Context) error
- func (n *AgentMeshNode) StartRenewalLoop(ctx context.Context, issuerURL, clientID, clientSecret, jwtPath string)
- func (n *AgentMeshNode) StartRenewalLoopWithSource(ctx context.Context, src TokenSource)
- func (n *AgentMeshNode) SyncControlPlane(ctx context.Context) error
- func (n *AgentMeshNode) Teardown() error
- func (n *AgentMeshNode) TopUp(ctx context.Context) int
- func (n *AgentMeshNode) UnregisterService(ctx context.Context, serviceName string) error
- func (n *AgentMeshNode) UpdateRelays(addrs []multiaddr.Multiaddr)
- func (n *AgentMeshNode) VerifyBiscuitToken(biscuitBytes []byte, reqCtx RequestContext) error
- func (n *AgentMeshNode) VerifyLocalBiscuit(rawToken []byte) (*identity.VerifiedBiscuitClaims, error)
- func (n *AgentMeshNode) VerifyPeerLabels(ctx context.Context, peerID peer.ID, required map[string]string) error
- func (n *AgentMeshNode) VerifyProvider(ctx context.Context, peerID peer.ID, required map[string]string, ...) error
- func (n *AgentMeshNode) WantRouters() int
- func (n *AgentMeshNode) WithBiscuitAuth(next func(network.Stream, RequestContext)) network.StreamHandler
- type AuthMode
- type CallRemoteToolParams
- type ClientCredentialsTokenSource
- type CloudTokenExchanger
- type DescribeRemoteToolParams
- type Directory
- type DiscoverRemoteServicesParams
- type EgressFacts
- type EgressService
- func (s *EgressService) Handler() http.Handler
- func (s *EgressService) Info() *api.ServiceInfo
- func (s *EgressService) Init(ctx context.Context) error
- func (s *EgressService) ServeTunnel(ctx context.Context, w http.ResponseWriter, r *http.Request, reqPort int)
- func (s *EgressService) SetExchanger(ex CloudTokenExchanger)
- func (s *EgressService) Teardown() error
- type FileTokenSource
- type FindRemoteToolsParams
- type GCPMetadataTokenSource
- type GetMeshInfoParams
- type HTTPRequestFacts
- type InferenceEngine
- type InferenceService
- func (s *InferenceService) ActiveRequests() uint32
- func (b *InferenceService) Handler() http.Handler
- func (b *InferenceService) Info() *api.ServiceInfo
- func (s *InferenceService) Init(ctx context.Context) error
- func (s *InferenceService) Models(ctx context.Context) ([]string, error)
- func (b *InferenceService) Teardown() error
- type ListLocalServicesParams
- type MCPService
- func (m *MCPService) HandleStreamPassThrough(s network.Stream, reqCtx RequestContext)
- func (b *MCPService) Handler() http.Handler
- func (b *MCPService) Info() *api.ServiceInfo
- func (m *MCPService) Init(ctx context.Context) error
- func (m *MCPService) Probe(ctx context.Context) error
- func (m *MCPService) Teardown() error
- func (m *MCPService) Tools(ctx context.Context) ([]string, error)
- type NodeConfigComplete
- type OIDCEndpoints
- type Options
- type Reachability
- type RefreshError
- type RefreshTokenSource
- type RequestContext
- type Service
- type ServiceRegistry
- func (r *ServiceRegistry) Get(name string) (Service, bool)
- func (r *ServiceRegistry) GetTyped(t api.ServiceType, name string) (Service, bool)
- func (r *ServiceRegistry) List(typeFilter api.ServiceType) []*api.ServiceInfo
- func (r *ServiceRegistry) Register(ctx context.Context, svc Service) error
- func (r *ServiceRegistry) ReprovideAll(ctx context.Context) int
- func (r *ServiceRegistry) TeardownAll()
- func (r *ServiceRegistry) Unregister(ctx context.Context, name string) error
- func (r *ServiceRegistry) WithdrawAll(ctx context.Context)
- type StdioBridge
- type Store
- func (s *Store) Close() error
- func (s *Store) Credential() (*api.MemberCredential, error)
- func (s *Store) LoadControlPlaneURL() (string, error)
- func (s *Store) LoadIdentity() ([]byte, error)
- func (s *Store) LoadIdentityExpiration() (int64, error)
- func (s *Store) LoadIdentityKeySet() ([]ed25519.PublicKey, error)
- func (s *Store) LoadKey() ([]byte, error)
- func (s *Store) LoadMeshConfig() ([]byte, []string, error)
- func (s *Store) LoadOIDCConfig() (string, string, string, error)
- func (s *Store) LoadRefreshToken() (string, error)
- func (s *Store) LoadTrustedKeys() ([]TrustedKey, error)
- func (s *Store) ResetMeshIdentity() error
- func (s *Store) SaveControlPlaneURL(url string) error
- func (s *Store) SaveIdentity(biscuit []byte) error
- func (s *Store) SaveIdentityExpiration(exp int64) error
- func (s *Store) SaveIdentityKeySet(keys []ed25519.PublicKey) error
- func (s *Store) SaveKey(key []byte) error
- func (s *Store) SaveMeshConfig(pubKey []byte, addrs []string) error
- func (s *Store) SaveOIDCConfig(issuer, clientID, audience string) error
- func (s *Store) SaveRefreshToken(token string) error
- func (s *Store) SaveTrustedKeys(keys []TrustedKey) error
- func (s *Store) SetCredential(c *api.MemberCredential) error
- type StreamTransport
- func (t *StreamTransport) Close() error
- func (t *StreamTransport) Connect(ctx context.Context) (mcp.Connection, error)
- func (t *StreamTransport) Read(ctx context.Context) (jsonrpc.Message, error)
- func (t *StreamTransport) Send(data []byte) error
- func (t *StreamTransport) SessionID() string
- func (t *StreamTransport) Write(ctx context.Context, msg jsonrpc.Message) error
- type TokenSource
- type TokenSourceConfig
- type TrustedKey
Constants ¶
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" )
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 )
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 )
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" )
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.
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.
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.
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.
const (
// StoreFile is the node database inside the data directory.
StoreFile = "agent.db"
)
Variables ¶
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) )
var ConnsPerSourceIP = p2plimits.DefaultConnsPerSourceIP(ConnHighWaterMark)
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.
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.
var ErrFatalAuth = errors.New("fatal authentication error")
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.
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.
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.
var NewFileTokenSource = cpclient.NewFileTokenSource
NewFileTokenSource creates a TokenSource that reads path on every FetchToken call.
Functions ¶
func CallerBiscuitFromContext ¶
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 GetOrGenerateKey ¶
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 ¶
NewUnauthenticatedMCPHandler creates an HTTP handler for the unauthenticated MCP server.
func NewUnauthenticatedMCPServer ¶
NewUnauthenticatedMCPServer creates a minimal MCP server that instructs the client on how to authenticate.
func ProbeGCPMetadata ¶
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 ¶
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) Info ¶
func (b *A2AService) Info() *api.ServiceInfo
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.
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 (*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 ¶
DiscoverTokenURL discovers the token URL from the OIDC issuer.
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 ¶
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.
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 ¶
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 ¶
func (s *ClientCredentialsTokenSource) FetchToken(ctx context.Context) (string, error)
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 ¶
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 ¶
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) Info ¶
func (b *InferenceService) Info() *api.ServiceInfo
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) 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.
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 ¶
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
// 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.
type Reachability ¶
type Reachability string
Reachability is the value of Options.Reachability and of --reachability.
const ( ReachabilityPrivate Reachability = "private" ReachabilityAuto Reachability = "auto" )
type RefreshError ¶
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 (*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 (*Store) LoadIdentity ¶
func (*Store) LoadIdentityExpiration ¶
func (*Store) LoadIdentityKeySet ¶
LoadIdentityKeySet returns the set saved by SaveIdentityKeySet, or nil when nothing recorded it.
func (*Store) LoadMeshConfig ¶
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) LoadRefreshToken ¶
func (*Store) LoadTrustedKeys ¶
func (s *Store) LoadTrustedKeys() ([]TrustedKey, error)
func (*Store) ResetMeshIdentity ¶
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 (*Store) SaveIdentity ¶
func (*Store) SaveIdentityExpiration ¶
func (*Store) SaveIdentityKeySet ¶
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) SaveMeshConfig ¶
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 (*Store) SaveRefreshToken ¶
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) 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) 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.
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.
Source Files
¶
- a2a_service.go
- auth_gate.go
- backend_env.go
- backend_target.go
- config.go
- connection_monitor.go
- controlplane.go
- controlplane_client.go
- controlplane_sync.go
- debug_handlers.go
- dial_ranker.go
- directory_client.go
- dnstcp.go
- egress.go
- egress_inspect.go
- egress_metrics.go
- egress_tunnel.go
- enroll.go
- ext_authz.go
- gate.go
- identity_evidence.go
- inference_engine.go
- inference_metrics.go
- inference_service.go
- labels_gate.go
- log_buffer.go
- mcp.go
- mcp_handlers.go
- mcp_service.go
- middleware.go
- node.go
- node_metrics.go
- oidc.go
- openai_facade.go
- openai_scorer.go
- options.go
- resource_limits.go
- routers.go
- service.go
- service_registry.go
- sidecar.go
- sidecar_metrics.go
- statedir.go
- stdio_bridge.go
- store.go
- sts.go
- tokensource.go