Documentation
Adapters
An adapter connects Fendlemark to one system you already run and translates what it finds into facets. Four ship in the binary. All of them are read-only. This page says exactly what each one reads, surfaces, correlates on, and leaves alone.
Common behaviour
- Read-only. No adapter creates, updates, deletes, triggers, retries, or cancels anything upstream. The console deep-links to the tool for those actions.
- Least privilege. Each adapter documents the minimum permission it needs. Grant that and nothing more.
- Graceful degradation. An unreachable upstream marks the adapter
degraded, keeps its last facets forlattice.retain_orphans, and keeps the console up. The other adapters are unaffected. - Health.
fendlemark adapters checkandGET /api/v1/adaptersreport status, latency, and a one-line detail per adapter. - Maturity. Every adapter has a maturity level on the ladder defined in Governance: Provisional, Settled, Established, Canonical. All four built-in adapters are Canonical. No adapter has ever been demoted.
mlflow
Reads from: an MLflow tracking server over its REST API (/api/2.0/mlflow/experiments/search, /runs/search, /metrics/get-history, /artifacts/list, and the registered-models and model-versions endpoints when registry: true). Works with any tracking server backend, since Fendlemark only sees the API. Also understands MLFLOW_TRACKING_USERNAME and MLFLOW_TRACKING_PASSWORD for basic auth, and MLFLOW_TRACKING_TOKEN for bearer auth.
Facets contributed: Experiment, Run (with params, tags, latest metric values, lifecycle stage), Metric series (fetched on demand when the Run view is open), Artifact listing (names and sizes; content is deep-linked, never proxied), Registered Model, Model Version (with stage or alias, source run, and signature summary).
Correlation keys provided: mlflow.run_id (always), mlflow.experiment_id, and whatever it finds in the tags listed in correlation_tags. The default list is:
correlation_tags:
- argo.workflow.name
- fendlemark.argo_workflow
- metaflow.run_id
- metaflow.flow_name
- kfp.run_id
- mlflow.source.git.commit # mapped to git.sha
- mlflow.source.git.repoURL # mapped to git.repoMLflow sets the two mlflow.source.git.* tags automatically when a run is started from a git checkout, so the weak git.sha key usually works without any effort on your part.
Does not: log metrics, create runs, transition model stages, or proxy artifact bytes. Does not read the tracking server's own UI; everything comes from the API.
Minimum permission: read access to the experiments you list (or all, if you list none). On a tracking server with the basic-auth plugin, a user with READ on the relevant experiments and registered models is sufficient.
metaflow
Reads from: the Metaflow metadata service, the same service the Metaflow client and the Metaflow UI backend read. Fendlemark does not read the datastore itself; datastore_root is used only to construct links to artifacts (for example an S3 console URL for a step's artifact prefix).
Facets contributed: Flow, Run (with user, tags, system tags, start and end), Step, Task (with attempt count and status), Artifact listing (names only), and the Metaflow-side view of any @kubernetes or @batch step's compute metadata where the metadata service records it.
Correlation keys provided: metaflow.run_id (in Metaflow's FlowName/RunId form and the bare numeric or Argo-generated form, since both appear in the wild), metaflow.flow_name, argo.workflow.name when the run was launched by a Metaflow-generated Argo Workflow (Metaflow records this in system tags), and git.sha when the @project decorator or a user tag carries it.
Does not: resume, trigger, or tag runs. Does not read artifact contents; Metaflow artifacts can be large and Fendlemark has no business holding them.
Minimum permission: network access to the metadata service. The metadata service itself has no built-in auth; if you front it with a proxy, give Fendlemark a read-only identity there.
argo
Reads from: Argo Server's REST API (/api/v1/workflows/{namespace}, /workflow-templates, /cron-workflows, and /archived-workflows when include_archived: true and the server has an archive configured). With kube_watch: true, it instead watches Workflow resources directly through the Kubernetes API for lower-latency updates, and uses Argo Server only for the archive and templates.
Facets contributed: Workflow (phase, start and finish, labels, annotations, parameters, outputs), Node (each step or DAG task with phase, template name, pod name, and a link to logs), WorkflowTemplate, CronWorkflow (schedule, last scheduled time, active count).
Correlation keys provided: argo.workflow.name (always), argo.workflow.uid, kfp.run_id from the pipeline/runid label that Kubeflow Pipelines sets on Workflows it creates, metaflow.run_id from Metaflow's Argo-generated labels and annotations, and git.sha from the fendlemark.io/git-sha annotation or the common app.kubernetes.io/version label when it looks like a commit.
Does not: submit, resubmit, retry, stop, terminate, suspend, or delete workflows. Does not stream logs through Fendlemark; the Node facet links to Argo's own log viewer.
Minimum permission: an Argo Server token (or kubeconfig context) with get, list, and watch on workflows, workflowtemplates, and cronworkflows in the listed namespaces. Nothing cluster-wide.
kubeflow
Reads from: the Kubeflow Pipelines API (pipelines, pipeline versions, runs, recurring runs, and experiments, scoped by profile when you list them). With katib: true it reads Katib Experiment and Trial resources through the Kubernetes API, and with notebooks: true it reads Notebook resources the same way.
Facets contributed: Pipeline (with versions), Pipeline Run (status, parameters, created and finished), Recurring Run (trigger, enabled, next scheduled), KFP Experiment, Katib Experiment (objective, algorithm, best trial summary), Notebook Server (image, resources, status).
Correlation keys provided: kfp.run_id (always), kfp.pipeline_id, argo.workflow.name because a KFP run's underlying Argo Workflow name is recoverable from the run detail, and metaflow.run_id or mlflow.run_id when they appear as pipeline run parameters named exactly that.
Because Kubeflow Pipelines executes on Argo Workflows by default, enabling both argo and kubeflow for the same cluster produces one entity per pipeline run with both facets attached, which is the single most common reason teams adopt Fendlemark.
Does not: create or terminate runs, enable or disable recurring runs, start or stop notebooks, or read notebook contents.
Minimum permission: a service account with read access to the KFP API for the listed profiles, plus get, list, watch on experiments.kubeflow.org, trials.kubeflow.org, and notebooks.kubeflow.org in those namespaces if Katib and Notebooks are enabled.
Correlation matrix
Which keys connect which adapters, out of the box, with no configuration beyond enabling them:
| mlflow | metaflow | argo | kubeflow | |
|---|---|---|---|---|
| mlflow | — | metaflow.run_id (tag) | argo.workflow.name (tag) | kfp.run_id (tag) |
| metaflow | metaflow.run_id | — | argo.workflow.name (system tag) | metaflow.run_id (parameter) |
| argo | argo.workflow.name | metaflow.run_id (label) | — | kfp.run_id (label, automatic) |
| kubeflow | mlflow.run_id (parameter) | metaflow.run_id (parameter) | argo.workflow.name (automatic) | — |
"Automatic" means the upstream tools already record the key without your pipelines doing anything. Everything else requires that your code set a tag, label, or parameter, which most teams find they were already doing for their own sanity.
A fifth tool?
Write an adapter. The interface has six methods and is documented in Writing an adapter. Proposing it for inclusion in the binary is governed by FCP-1, which the Keepers describe as "thorough".