Open-source, self-hostable, gateway-agnostic registry & marketplace for agentic artifacts: Skills, Tools, MCP Servers, Prompts, Workflows, Blueprints (plus
Agentfor devai interop).
A registry that is a catalog / control plane — not a proxy and not an auth layer — is a deliberately-vacated gap in the ecosystem:
- Portkey keeps its registry (prompts, model catalog, configs) proprietary and open-sources only the proxy.
- solo.io aregistry couples its registry tightly to
agentgateway. - The official MCP Registry is explicitly not built for self-hosting.
Agentic Registry fills that gap: an open, self-hostable, gateway-neutral control plane. The hard architectural invariant that every decision protects:
The registry stores and serves metadata + bytes and answers discovery queries. It never authenticates traffic, mints tokens, proxies requests, or runs the artifacts it catalogs. Every gateway integration is an adapter that reads from the registry, never a coupling baked into it.
| Area | Decision | Rationale |
|---|---|---|
| Storage | Postgres (envelope as JSONB, GIN-indexed labels) + GCS for bytes, content-addressed by SHA-256 | Artifacts are KB-sized & metadata-heavy; labels/RBAC/visibility/search must live in Postgres anyway. OCI/ORAS deferred to v2. |
| Backend | Go + chi router; OpenAPI doc committed | Registry is infra (metadata CRUD, selector eval, digest math, JWKS) not AI. OCI/cosign/k8s-selector libs are all Go. Single distroless static binary. |
| API group | registry.agentic.dev/v1alpha1 (neutral) |
Normalize registry.solo.io/v1alpha1 & ar.dev/v1alpha1 on ingest so devai's existing seeds publish unchanged. |
| Frontend | React + Vite + Tailwind 4, devai design tokens | Visual sibling of devai Mission Control (Paper·Ink·Slate). |
| Auth | Out of the data path — trusted X-Forwarded-* from a gateway OR JWKS-verified Bearer JWT |
Registry issues no tokens, validates no traffic. |
| Secrets | GCP Secret Manager only — never DB, never code | DB creds via External Secrets; GCS via Workload Identity; provider keys are references, not values. |
Every artifact is a Kubernetes-style envelope:
apiVersion: registry.agentic.dev/v1alpha1
kind: Skill # Skill | Tool | MCPServer | Prompt | Workflow | Blueprint | Agent
metadata:
name: senior-developer
namespace: default # maps to a tenant scope
tag: latest # OCI-style; same-tag apply atomically replaces
labels: { domain: code-review, language: go }
visibility: public # public | internal | private
spec: { ... } # kind-specific
status: { ... } # server-managed- Tag-based versioning (not semver-in-path),
latestdefault,content_hash(SHA-256) idempotent re-apply. MCPServer.specisserver.json(reverse-DNS one-slash name, packages/remotes, transport sub-objects) → native MCP-Registry interop.Project(devai legacy kind) accepted on ingest as a namespace/label collection, not a deployable artifact.
- Scope (ownership):
tenant_id(required) →org_id→team_id. Users join teams; teams live in orgs (Docker Hub model). Reverse-DNS namespaces, ownership-verified. - Visibility:
public | internal | private(internal = whole tenant). Public ⇒ anonymous read. - Labels: freeform user labels + server-managed immutable system labels
(
tenant,org,visibility) publishers cannot spoof.
Access decision (the security boundary):
can_read(id, a) = a.visibility==public
OR (a.visibility==internal AND id.tenant==a.tenant)
OR rbac_grant(read|write|admin, id, a)
Roles are cumulative: read < write < admin.
Discovery uses the Kubernetes LabelSelector verbatim — matchLabels +
matchExpressions, operators In | NotIn | Exists | DoesNotExist only, AND-only.
Both JSON-body and URL string forms (?labelSelector=domain in (code-review),language=go).
Invariant: the visibility/RBAC filter is applied before the label selector. The selector is discovery convenience, never a security boundary.
GET /v0/health
GET /v0/{skills|prompts|servers|mcpservers|agents|tools|workflows|blueprints}[?namespace=&labelSelector=]
GET /v0/{plural}/{name} # latest tag
GET /v0/{plural}/{name}/{tag}
GET /v0/{plural}/{name}/tags
POST /v0/{plural} # publish single resource
POST /v0/apply # multi-doc YAML batch (kubectl-apply-like)
DELETE /v0/apply
servers and mcpservers are aliases for the MCPServer kind. apiVersion group
normalized on ingest.
GET /v0.1/servers?cursor=&limit=&search=&updated_since=&version=&include_deleted=
GET /v0.1/servers/{serverName}/versions
GET /v0.1/servers/{serverName}/versions/{version} # 'latest' allowed
POST /v0.1/publish # Bearer JWT; body = server.json
PATCH /v0.1/servers/{serverName}/versions/{version}/status # active|deprecated|deleted
GET /v0.1/health ; GET /metrics
Cursor pagination via metadata.nextCursor; incremental sync via updated_since.
POST /v0/prompts/{name}/render → { model, messages, params, tools }
Logic-less Mustache templating (no code-exec in tenant templates). Immutable
numbered versions + movable labels (production/staging/@latest).
Exposes list_skills/get_skill, list_servers/get_server, list_agents/get_agent,
search_registry(query) as MCP tools so agentic IDEs discover registry contents
through MCP itself. Catalog, not proxy.
- Auth: accept a pre-validated identity from any OIDC gateway via trusted
X-Forwarded-User/Email/Groups(trusted only over mTLS / known gateway), OR verify a Bearer JWT against a configurable JWKS/issuer. Mapsgroups→ internal roles. Never issues tokens. - Connectors (out-of-tree adapters): translate registry state → a gateway's native
config.
adapters/agentgateway(binds/listeners/routes/MCPBackends),adapters/portkey(config JSON / model-catalog refs). The registry only emits config; the proxy consumes it.
A new registry adapter family in devai/src/devai/adapters/registry/ mirroring
adapters/memory/: factory.py + AdapterRegistry.register(), impls tesserix
(ours), solo_aregistry, portkey, mcp_registry. devai swaps backend by env var;
the registry stays ignorant of devai.
| Secret | Source | Delivery |
|---|---|---|
| Postgres password | GCP Secret Manager prod-agentic-registry-db |
External Secret → K8s Secret → env DATABASE_URL |
| GCS access | Workload Identity (GCP SA app-secrets-agentic-registry-prod@…) |
no key files |
| JWKS / OIDC issuer | non-secret config | env AUTH_JWKS_URL, AUTH_ISSUER |
| Provider API keys (catalog) | GCP Secret Manager | stored as references in registry; values never persisted |
- Distroless Go image (
base-distroless-static),docker-compose.ymlfor local. - Helm chart
tesserix-k8s/charts/apps/agentic-registry, ArgoCD app, new GCP namespaceagentic-registry, in-cluster Postgres (CNPG pattern), External Secrets. - Schema SQL lives only in
tesserix-k8s/charts/apps/db-schema-bootstrap/schemas/agentic-registry/. - Memory-only resources (no CPU limits/requests), KEDA memory-trigger ScaledObject.
- Deploy via the
public → CI → privateflow.
- Repo scaffold + OSS guardrails + this plan ✅
- Backend core: envelope, store (memory+postgres),
/v0/*, label selector, auth - MCP interop
/v0.1/*+server.json+ built-in MCP discovery + prompt render - React marketplace UI (devai tokens)
- CLI
agentic(init/build/push/apply/login) - devai
registryadapter family - Dockerfile + Helm + ArgoCD + GCP deploy + seed devai's registry-seeds
OCI/ORAS pull protocol · cosign admission gating · SBOM/SLSA provenance · vector search · ratings/downloads/trending · in-registry Runtime/Deployment lifecycle · Terraform provider.