Back to Langflow

Manifest reference

docs/docs/Lfx/extensions-manifest.mdx

1.12.0.dev1410.6 KB
Original Source

This page is the reference for the extension.json manifest used by manifest-shipping extensions, including curated packages and graduated standalone packages.

The lfx-bundles metapackage uses manifest-less discovery through the lfx.bundles group and does not use extension.json.

The canonical JSON Schema lives at https://schemas.langflow.org/extension/v1.json and is generated from the Pydantic model at lfx.extension.manifest.ExtensionManifest.

To export the live schema, run:

bash
lfx extension schema --output extension.schema.json

Use the $schema reference in your manifest so editors can autocomplete and validate inline:

json
{
  "$schema": "https://schemas.langflow.org/extension/v1.json",
  "id": "lfx-my-extension",
  "version": "0.1.0",
  "name": "My extension",
  "lfx": { "compat": ["1"] },
  "bundles": [{ "name": "my_bundle", "path": "components/my_bundle" }]
}

Top-level fields

FieldTypeRequiredDescription
idstringyesGlobally-unique extension ID. Lowercase, hyphenated, starts with a letter, 2-64 chars. Convention: lfx-<name>.
versionstringyesSemVer 2.0.0 version string for this extension release.
namestringyesHuman-readable display name shown in the Langflow palette. 1-200 chars.
descriptionstring | nullnoOptional one-paragraph summary, max 2000 chars.
lfxobjectyesCompatibility declaration against the BUNDLE_API contract.
bundlesarraynoBundle list. v0 accepts at most one bundle; omit it for a provider-only extension.
providersarraynoModel providers contributed to the unified model-provider registry.
capabilitiesobjectnoOptional capability flags. Defaults to all-false.
$schemastringnoOptional pointer to this JSON Schema; editors use it for autocomplete.

additionalProperties: false — any field not listed here is rejected with a typed error. Reserved names (services, routes, hooks, starterProjects, userConfig) are documented under Deferred fields and surface a more specific error code.

An extension must declare at least one entry in either bundles or providers. It can declare both when one package contributes components and model providers.

lfx: compatibility declaration

json
"lfx": { "compat": ["1"] }
FieldTypeDescription
compatarray of stringsNon-empty list of BUNDLE_API.md contract versions this extension supports. Each entry is a positive-integer string.

The runtime compares str(BUNDLE_API_VERSION) against this list. A mismatch fails install with version-constraint-unsatisfied. v0 accepts only "1"; lists like ["1", "2"] become meaningful when a future BUNDLE_API revision ships.

bundles

json
"bundles": [
  { "name": "my_bundle", "path": "components/my_bundle" }
]
FieldTypeDescription
namestringBundle name; addressable as ext:<bundle>:<Class>@<slot>. Lowercase snake_case, starts with a letter, 2-64 chars.
pathstringPath to the bundle directory, relative to the manifest. Must not start with / or contain ...

v0 enforces maxItems: 1; multi-bundle extensions are rejected with multi-bundle-unsupported and ship in a later epic. The list can be empty when the extension declares at least one model provider.

providers

A provider-only extension can add a provider without adding a component bundle:

json
{
  "$schema": "https://schemas.langflow.org/extension/v1.json",
  "id": "lfx-acme-models",
  "version": "0.1.0",
  "name": "Acme Models",
  "lfx": { "compat": ["1"] },
  "providers": [
    {
      "name": "Acme",
      "provider_id": "acme.models",
      "display_name": "Acme Models",
      "aliases": ["Acme Legacy"],
      "metadata": {
        "icon": "Bot",
        "variables": [],
        "mapping": {
          "model_class": "ChatAcme",
          "model_param": "model"
        }
      },
      "api_key_required": false,
      "model_class": {
        "module": "langchain_acme",
        "attr": "ChatAcme",
        "install_hint": "langchain-acme"
      },
      "catalog_loader": "lfx_acme.catalog:load_models"
    }
  ]
}
FieldTypeRequiredDescription
namestringyesCanonical provider name used by existing saved flows and provider selectors.
provider_idstringnoStable lowercase machine identity used by policy and extension compatibility. Must match ^[a-z0-9][a-z0-9._-]*$. Legacy manifests can omit it and receive a deterministic ID derived from name.
display_namestringnoUser-facing label. It can change without changing provider_id or saved-flow identity.
aliasesarray of stringsnoUnique legacy names accepted when resolving the provider's stable identity.
metadataobjectyesProvider icon, variables, API documentation URL, and mapping. mapping.model_class must be non-empty.
model_classobjectnoLazy LLM class import with module, attr, and optional install_hint. Omit it when reusing an already-registered class.
embeddingobjectnoOptional embedding class import and parameter mapping. Includes class_name, module, attr, param_mapping_key, param_mapping, and optional install_hint.
api_key_requiredboolnoWhether unified runtime helpers reject missing API-key credentials. Defaults to true.
liveboolnoEnables always-on live model discovery. Mutually exclusive with conditional_live.
conditional_liveboolnoEnables live discovery only when the provider has a custom endpoint configured. Mutually exclusive with live.
live_discoverystringnoLazy module:callable that receives (user_id, model_type) and returns live model rows.
validatorstringnoLazy module:callable that validates (provider, variables, model) and raises on invalid credentials.
catalog_loaderstringnoLazy module:callable returning the provider's static model metadata rows.

catalog_loader must return a flat list[dict]. Every row requires a non-empty name; model_type can be llm or embeddings and defaults to llm. Langflow overwrites any supplied provider value with the descriptor's canonical name, supplies the provider icon when omitted, and rejects duplicate (model_type, name) identities. Deployments that require an extension catalog can call validate_registered_provider_catalogs() or get_registry_snapshot(validate_catalogs=True) during readiness.

Providers that use ambient authentication or need no credentials should set api_key_required to false. They remain eligible for unified model options when metadata.variables is empty or contains only optional configuration fields.

Built-in providers take precedence over extension declarations. A provider-name collision is skipped without preventing other providers or components from loading. Stable-ID or alias collisions are reported as provider-invalid.

capabilities

Optional. Defaults to { "requiresCredentials": false }.

FieldTypeDescription
requiresCredentialsboolIf true, the loader records that components in this bundle expect credential variables to be configured before use.

Additional capability keys are rejected with extra="forbid" so a misspelled key surfaces immediately rather than silently turning a feature off.

Deferred fields

The schema strips these names from the published properties map but reserves them via x-deferred-fields, so a manifest that sets one gets a specific error code instead of the generic "additional property" message.

Reserved keyReplacement error codeFuture epic
servicesfield-deferred-in-this-milestoneB2 — non-component primitives
routesfield-deferred-in-this-milestoneB2 — non-component primitives
hooksfield-deferred-in-this-milestoneB2 — non-component primitives
starterProjectsfield-deferred-in-this-milestonelater milestone
userConfigfield-deferred-in-this-milestonelater milestone

A manifest that sets any of these to a non-null value is rejected at validate / load time. Setting them to null is allowed (the loader treats null and absent identically).

Pyproject alternative

If you'd rather not ship a separate extension.json next to pyproject.toml, declare the same fields under [tool.langflow.extension]:

toml
[tool.langflow.extension]
id = "lfx-my-extension"
version = "0.1.0"
name = "My extension"

[tool.langflow.extension.lfx]
compat = ["1"]

[[tool.langflow.extension.bundles]]
name = "my_bundle"
path = "components/my_bundle"

The loader prefers an extension.json when both exist. The Pydantic validator is the same so error codes and field semantics are identical.

Error codes raised against this manifest

The loader and validator both emit typed errors keyed by the manifest field that triggered them. The full reference is on the Extension error codes page; the codes most relevant when authoring a manifest are:

CodeCause
manifest-invalidSchema validation failed; the message names the field.
manifest-not-foundNo extension.json and no [tool.langflow.extension] section at the extension root.
version-constraint-unsatisfiedlfx.compat does not include this Langflow's BUNDLE_API_VERSION.
field-deferred-in-this-milestoneA reserved field was set to a non-null value.
multi-bundle-deferred-in-this-milestonebundles has more than one entry.
path-escapeA bundles[].path resolves outside the manifest root (typically a symlink).
bundle-path-not-foundbundles[].path does not exist or is not a directory.
provider-invalidA provider descriptor or one of its lazy import paths is malformed. The invalid provider is skipped.
provider-skippedA provider name collides with a built-in or previously loaded provider. The existing provider wins.

Run lfx extension validate <path> to see every error as a structured object with code, message, location, hint, and ref_url.

See also