catalog

package
v0.74.7 Latest Latest
Warning

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

Go to latest
Published: Jul 17, 2026 License: BSD-3-Clause, AGPL-3.0 Imports: 1 Imported by: 0

Documentation

Overview

Package catalog defines the static set of Agent Network providers recognized by the management server. The catalog is consulted both to validate provider_id on create/update and to surface the available providers (and their models) to the dashboard.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func IsBedrockPathStyle

func IsBedrockPathStyle(providerID string) bool

IsBedrockPathStyle reports whether a provider uses the AWS Bedrock request shape — the model is carried in the URL path (/model/{modelId}/{action}, action being invoke, invoke-with-response-stream, converse, or converse-stream) rather than the body, so the proxy routes it by path.

func IsKnown

func IsKnown(id string) bool

IsKnown reports whether the given id refers to a catalog entry.

func IsVertexPathStyle

func IsVertexPathStyle(providerID string) bool

IsVertexPathStyle reports whether a provider uses the Google Vertex AI request shape — the model is carried in the URL path (/v1/projects/{p}/locations/{r}/publishers/{pub}/models/{model}:{action}) rather than the body, so the proxy routes it by path instead of by model.

Types

type ExtraHeader

type ExtraHeader struct {
	// Name is the wire header name, e.g. "x-portkey-config".
	Name string
}

ExtraHeader names a single optional per-provider routing/config header. Catalog declares N of these per provider type; the operator fills any subset on the provider record (see Provider.ExtraValues). At synth time, only entries with a non-empty operator value are stamped; the proxy's identity-inject middleware applies anti-spoof (Remove + Add) so a client can't supply these headers themselves.

UI copy (label / help text / tooltip) for each known Name lives on the dashboard, not here — the backend's job is just to declare which wire headers are accepted. New provider needs an extra header? Add the Name here AND the matching UI copy on the dashboard.

type HeaderPairInjection

type HeaderPairInjection struct {
	// Customizable, when true, marks the wire header names as
	// operator-overridable: the dashboard surfaces EndUserIDHeader
	// and TagsHeader as editable inputs (defaults shown as
	// placeholders) and the synthesizer pulls the actual values from
	// the provider record's IdentityHeader* fields rather than from
	// these defaults. An empty operator value disables stamping for
	// that dimension. Used today for Bifrost, whose log-metadata /
	// telemetry header prefix (x-bf-lh-* vs x-bf-dim-*) is a
	// per-operator choice; LiteLLM and similar gateways with a fixed
	// wire protocol leave this false so the catalog defaults are
	// authoritative.
	Customizable bool
	// EndUserIDHeader receives the caller's display identity (user
	// email when the peer is attached to a user, else peer.Name),
	// e.g. "x-litellm-end-user-id".
	EndUserIDHeader string
	// TagsHeader receives the caller's NetBird group display names
	// as a CSV, e.g. "x-litellm-tags".
	TagsHeader string
	// TagsInBody, when true, additionally writes the tag list into
	// the request body's metadata.tags array (a JSON path the
	// gateway parses for budget enforcement). LiteLLM only honours
	// metadata.tags for tag-budget gating — its x-litellm-tags
	// header path feeds spend tracking but bypasses
	// _tag_max_budget_check entirely. Body inject is skipped when
	// the request body is empty, truncated, non-JSON, or when an
	// existing metadata field is a non-object value (defensive: we
	// never clobber a client-supplied non-object). The header path
	// remains a robust fallback for spend tracking in those cases.
	TagsInBody bool
	// EndUserIDInBody, when true, additionally writes the display
	// identity into the request body's top-level "user" field (the
	// OpenAI-standard end-user identifier). LiteLLM resolves the end
	// user id from headers first then body, so for LiteLLM this is
	// belt-and-suspenders. It matters when an OpenAI-compatible
	// gateway downstream of LiteLLM (or OpenAI direct, bypassing
	// LiteLLM) only reads the body, and as anti-spoof: client-
	// supplied "user" values are overwritten with our trusted
	// identity. Same skip rules as TagsInBody.
	EndUserIDInBody bool
}

HeaderPairInjection is the LiteLLM-style wire convention.

type IdentityInjection

type IdentityInjection struct {
	// HeaderPair emits separate headers per identity dimension
	// (end-user id, tags as CSV). LiteLLM and OpenAI-compatible
	// self-hosted gateways that read identity from dedicated headers.
	HeaderPair *HeaderPairInjection
	// JSONMetadata emits a single header carrying a JSON object with
	// reserved keys for user / groups / etc. Portkey, Helicone-style
	// metadata headers, anything that wants a structured envelope.
	JSONMetadata *JSONMetadataInjection
}

IdentityInjection describes how the proxy stamps NetBird identity onto upstream gateway requests. Exactly one shape must be set — they're mutually exclusive and dispatched by the inject middleware.

Shape choice tracks the wire convention the upstream gateway uses, not the vendor name. New gateways with a known shape become a catalog entry, not a new code path.

type JSONMetadataInjection

type JSONMetadataInjection struct {
	// Customizable, when true, marks the JSON keys as operator-
	// overridable. The dashboard surfaces UserKey and GroupsKey as
	// editable inputs (the catalog values shown as placeholders) and
	// the synthesizer pulls the actual JSON-key names from the
	// provider record's IdentityHeader* fields. Same field reuse as
	// HeaderPair's customizable path — the dimensions (user identity,
	// groups) are the same, only the wire encoding differs (JSON key
	// vs HTTP header name). An empty operator value disables emission
	// for that dimension. Used today for Cloudflare AI Gateway, whose
	// cf-aig-metadata header accepts arbitrary JSON keys; Portkey
	// leaves this false because its keys are reserved by the Portkey
	// schema.
	Customizable bool
	// Header is the wire header name carrying the JSON payload, e.g.
	// "x-portkey-metadata".
	Header string
	// UserKey is the JSON key for the caller's display identity.
	// Portkey reserves "_user" for this dimension.
	UserKey string
	// GroupsKey is the JSON key for the caller's NetBird groups,
	// emitted as a CSV string value (Portkey requires string values).
	GroupsKey string
	// MaxValueLength caps each emitted JSON value, in bytes. Portkey
	// enforces a 128-char limit per value; oversized values are
	// truncated rather than failing the request. 0 disables the cap.
	MaxValueLength int
}

JSONMetadataInjection is the Portkey-style wire convention: a single header carrying a JSON object. NetBird identity fields land under the configured reserved keys; missing keys (empty string) are skipped at emit time.

type Model

type Model struct {
	ID            string
	Label         string
	InputPer1k    float64
	OutputPer1k   float64
	ContextWindow int
}

Model is the in-memory representation of a catalog model.

type Provider

type Provider struct {
	ID          string
	Name        string
	Description string
	DefaultHost string
	// Kind groups this entry for UI presentation; see ProviderKind.
	Kind ProviderKind
	// AuthHeaderName is the HTTP header the provider's API expects
	// the credential under (e.g. "Authorization" for OpenAI,
	// "x-api-key" for Anthropic). Combined with AuthHeaderTemplate
	// at synthesis time to inject the auth header on every upstream
	// request.
	AuthHeaderName     string
	AuthHeaderTemplate string
	DefaultContentType string
	BrandColor         string
	// ParserID names the proxy LLM parser surface this provider
	// speaks (matches llm.Parser.ProviderName: "openai",
	// "anthropic"). Multiple catalog ids may share a parser surface
	// (e.g. azure_openai_api and mistral_api both speak the OpenAI
	// shape). Empty when no parser is yet implemented for the
	// surface — the proxy middleware then falls back to URL sniffing
	// or skips request-side enrichment.
	ParserID string
	// IdentityInjection, when non-nil, instructs the proxy to stamp
	// the caller's NetBird identity onto upstream requests under the
	// configured header names. Used for gateways like LiteLLM that
	// key budgets and attribution off request headers (the gateway
	// otherwise has no way to learn which user / group made the call).
	// The proxy strips the same header names from the inbound request
	// before stamping ours, so an app can't spoof identity by setting
	// these headers itself.
	IdentityInjection *IdentityInjection
	// ExtraHeaders is a catalog-declared list of additional per-
	// provider routing/config headers the proxy stamps on every
	// upstream request. Distinct from AuthHeaderName/Template (which
	// always carries the API_KEY) and from IdentityInjection (caller
	// identity). Each entry surfaces an optional input on the
	// dashboard's provider modal whose value lives on the provider
	// record's ExtraValues map (keyed by ExtraHeader.Name). Empty
	// list = no extra inputs rendered. Used today by Portkey for
	// "x-portkey-config: pc-..." (a saved-config id that resolves
	// upstream provider + credentials on Portkey's hosted side).
	ExtraHeaders []ExtraHeader
	Models       []Model
}

Provider is the in-memory representation of a catalog provider.

func All

func All() []Provider

All returns a copy of the full catalog.

func Lookup

func Lookup(id string) (Provider, bool)

Lookup returns the catalog entry with the given id, if any.

func (Provider) ToAPIResponse

func (p Provider) ToAPIResponse() api.AgentNetworkCatalogProvider

ToAPIResponse renders a catalog provider as the API representation.

type ProviderKind

type ProviderKind string

ProviderKind groups catalog entries for UI presentation. The split is semantic, not technical:

  • KindProvider: the upstream is a vendor's first-party API (OpenAI, Anthropic, Mistral, Bedrock, etc.) — NetBird talks straight to the model provider.
  • KindGateway: the upstream is itself a routing / aggregation layer in front of multiple providers (LiteLLM, Portkey, Helicone, …). These typically need NetBird identity stamped onto upstream requests so the gateway's analytics and budgets attribute to the real caller; that's what IdentityInjection is for.
  • KindCustom: the catch-all "OpenAI-compatible self-hosted endpoint" entry (vLLM, Ollama, custom inference servers).

Frontend uses Kind to group the provider Select in the modal so an operator can spot at a glance which catalog entries proxy other providers vs. talk straight to one. Backend doesn't dispatch on Kind today; it's purely a presentation hint.

const (
	KindProvider ProviderKind = "provider"
	KindGateway  ProviderKind = "gateway"
	KindCustom   ProviderKind = "custom"
)

Jump to

Keyboard shortcuts

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