Stage 1: Describe the Adapter

View as Markdown

An Adapter Descriptor tells NVIDIA NeMo Fabric how to locate an adapter and which contract surface it implements. NeMo Fabric reads and validates this record during planning without importing or starting the adapter.

Adapter Descriptor filenames end in .fabric-adapter.json.

Create a Minimum Descriptor

The following descriptor is enough to declare an in-process Python adapter that accepts an empty AgentConfig and implements only the required lifecycle:

1{
2 "contract_version": "fabric.adapter/v1alpha2",
3 "adapter_id": "com.acme.fabric.example",
4 "adapter_kind": "python",
5 "runner": {
6 "module": "acme_fabric_adapter.runtime"
7 }
8}

Use a globally stable adapter_id. Treat it as a machine identifier, not a display name. Adapters receive AgentConfig; FabricConfig never crosses the southbound boundary.

The primary descriptor fields are:

FieldPurpose
contract_versionSelects the complete negotiated adapter contract. Use fabric.adapter/v1alpha2.
adapter_idIdentifies the adapter implementation during selection and planning.
adapter_kindSelects the runtime binding: python, process, http, or native_plugin.
runnerSupplies binding-specific startup metadata, such as a Python module.
requirementsDescribes binaries, environment-variable names, files, services, or plugin hooks for diagnostics.
configDeclares the normalized fields the adapter applies and target-native files it generates.
capabilitiesDeclares optional runtime operations implemented through the adapter binding.
telemetryDeclares telemetry outputs and integration modes the adapter produces or forwards.
target_typesDeclares registered target types a shared adapter can load. Omit it for a direct harness or dedicated-agent adapter.

Use the canonical adapter-descriptor.schema.json for exact fields, defaults, and constraints.

Declare Accepted Configuration

Add a config.accepts value only after the implementation applies that field. For example, the following adapter accepts named models, model endpoints, system instructions, and a target-applied turn limit:

1"config": {
2 "accepts": [
3 "models",
4 "models.base_url",
5 "instructions.system",
6 "runtime.max_turns"
7 ]
8}

Accepting a parent does not automatically accept every optional child. For example, models accepts the base model block, while models.temperature and models.base_url are separate declarations. Use the schema enum for the exact accepted values.

Planning rejects configured normalized behavior outside the declared surface. NeMo Fabric does not silently remove unsupported fields.

Add Adapter-Owned Schemas

Use an Adapter Descriptor schema for target-specific data that cannot be validated by the normalized contract alone:

Descriptor FieldValidates
settings_schemaFabricConfig.harness.settings for this adapter.
model_schemaEvery configured model role, including provider compatibility and closed model settings.
tool_definition_schemaEvery normalized named tool or tool-group definition.
extension_schemasAdapter-owned data at named southbound extension points.

The following closed settings schema permits one optional command timeout:

1"settings_schema": {
2 "type": "object",
3 "properties": {
4 "command_timeout": {
5 "type": "integer",
6 "minimum": 1
7 }
8 },
9 "additionalProperties": false
10}

Use a closed object with no properties when the adapter accepts harness.settings but has no settings. Omit the schema when the adapter does not support that configuration surface.

Schemas must be valid, self-contained JSON Schema objects. NeMo Fabric does not load arbitrary HTTP or file references during planning. Use additionalProperties: false unless an intentionally open compatibility surface is part of the adapter contract.

Register Targets for a Shared Adapter

A shared framework adapter separates its static implementation descriptor from the custom agents it can load. The Adapter Descriptor declares the supported target type:

1{
2 "contract_version": "fabric.adapter/v1alpha2",
3 "adapter_id": "com.acme.fabric.framework",
4 "adapter_kind": "python",
5 "target_types": ["workflow"],
6 "runner": {
7 "module": "acme_framework_adapter.runtime"
8 },
9 "config": {
10 "accepts": ["models", "tools.definitions"]
11 }
12}

Each separately installed workflow publishes one *.fabric-target.json Adapter Target Descriptor. The target record selects its adapter, fixes the adapter-scoped entry point, and validates that target’s workflow settings:

1{
2 "contract_version": "fabric.adapter/v1alpha2",
3 "type": "workflow",
4 "id": "com.acme.email-phishing",
5 "adapter_id": "com.acme.fabric.framework",
6 "spec": {
7 "entrypoint": {
8 "kind": "factory",
9 "ref": "acme.agent.react"
10 },
11 "settings_schema": {
12 "type": "object",
13 "properties": {
14 "llm_name": {
15 "type": "string",
16 "minLength": 1
17 }
18 },
19 "required": ["llm_name"],
20 "additionalProperties": false
21 }
22 }
23}

The Adapter Target Descriptor uses the same contract_version as the Adapter Descriptor. It does not introduce another contract or schema version. workflow.target_id selects the target by id; consumer configuration does not repeat its adapter-specific entry point.

Use the canonical adapter-target-descriptor.schema.json for the complete target record.

Keep Claims Exact

Declare only behavior implemented through the adapter boundary. A target’s native cancellation or streaming feature does not become a NeMo Fabric capability until the adapter binding implements the corresponding contract. Relay-backed ATOF streaming does not require capabilities.streaming; that flag is reserved for the optional native OpenAI streaming operation.

Next, map normalized configuration and implement only the fields listed in config.accepts.