Capability Provider Contract (Canonical)¶
This document is the canonical contract for services that register capabilities in MeshFlows.
Use this spec when implementing or reviewing any provider that publishes trigger or workflow_step capabilities.
Scope¶
This contract defines:
- service registration payload shape
- capability metadata conventions
- dashboard designer metadata (
metadata.designer) - icon and description ownership (provider-owned)
Out of scope:
- transport/runtime details of each capability implementation
- orchestration semantics for built-in step types
Service Registration Contract¶
Providers register through the capability registry endpoint:
POST /v1/registry/services/register
Minimum service-level fields:
| Field | Required | Type | Notes |
|---|---|---|---|
service_name |
yes | string | Stable service identifier |
service_type |
yes | string | Usually provider |
service_url |
yes | string | Base URL reachable by internal consumers |
capabilities |
yes | array | At least one capability |
Recommended service-level optional fields:
| Field | Required | Type | Notes |
|---|---|---|---|
description |
no | string | Short service description for UI and catalog |
icon |
no | string | Provider-owned icon (URL, emoji, or agreed token) |
icon_emoji |
no | string | Optional explicit emoji icon |
metadata.description |
no | string | Fallback description |
metadata.icon |
no | string | Fallback icon |
metadata.icon_emoji |
no | string | Fallback icon emoji |
Capability Contract¶
Each capability in capabilities[]:
| Field | Required | Type | Notes |
|---|---|---|---|
name |
yes | string | Unique capability name, e.g. gateway.http_trigger |
version |
yes | string | Semver |
kind |
yes | string | trigger, workflow_step, workflow_connection (embedded workflow connection templates), or other kinds outside designer |
description |
yes | string | Human-readable short description |
metadata |
no | object | Extension bucket for schemas, routes, designer metadata |
Recommended capability optional fields:
| Field | Required | Type | Notes |
|---|---|---|---|
summary |
no | string | Additional short text used by UI fallback |
icon |
no | string | Capability-specific icon |
icon_emoji |
no | string | Capability-specific icon emoji |
metadata.icon |
no | string | Fallback icon |
metadata.icon_emoji |
no | string | Fallback icon emoji |
metadata.description |
no | string | Fallback description |
Designer Metadata Contract (metadata.designer)¶
For capabilities shown in dashboard wizard/pickers, provide metadata.designer.
Common fields:
| Field | Required | Type | Notes |
|---|---|---|---|
display_name |
yes | string | Label shown in picker cards |
category |
no | string | Grouping label in picker |
description |
recommended | string | Short description shown in picker cards |
icon |
recommended | string | Designer-specific icon override |
icon_emoji |
recommended | string | Designer-specific icon emoji override |
form_fields |
conditional | array | Dynamic fields for trigger/step configuration |
Trigger-only fields:
| Field | Required | Type | Notes |
|---|---|---|---|
invocation_type |
yes | string | Value for workflow invocation.type |
Workflow-step-only fields:
| Field | Required | Type | Notes |
|---|---|---|---|
step_type |
yes* | string | Value for YAML step.type |
variants |
optional | array | Alternative to single step_type; each variant defines step_type, display_name, and optionally description, icon, icon_emoji, form_fields |
*Required when variants is not used.
Workflow scoped declarations (metadata.designer.scoped_declarations)¶
For providers that materialize workflow-level variable slots (scoped_context.variables in workflow YAML), the service may publish a machine-readable declaration schema so the dashboard designer can render tables or forms without hard-coding field lists (ADR 0001).
| Field | Required | Type | Notes |
|---|---|---|---|
schema_version |
recommended | integer | Increment when the shape of variable_row or provider_block changes |
description |
no | string | Human-readable purpose |
aligns_with |
no | string | Free-text pointer (e.g. Pydantic model name or doc anchor) |
variable_row |
yes | object | JSON-Schema-shaped description of one scoped_context.variables[] element (name, type, optional init) |
provider_block |
no | object | JSON-Schema-shaped description of scoped_context.provider |
Consumers (dashboard) should treat unknown keys as forward-compatible. Version negotiation is schema_version plus provider semver on the registering service.
Example (conceptual):
{
"metadata": {
"designer": {
"scoped_declarations": {
"schema_version": 1,
"description": "Variable rows for workflow scoped_context when backed by variables.service",
"variable_row": {
"type": "object",
"required": ["name", "type"],
"properties": {
"name": { "type": "string" },
"type": { "type": "string" },
"init": {
"type": "object",
"properties": { "value": {} }
}
}
},
"provider_block": {
"type": "object",
"required": ["service_name"],
"properties": {
"service_name": { "type": "string" },
"capability_hint": { "type": "string" },
"version": { "type": "string" }
}
}
}
}
}
}
Publish scoped_declarations on the service registration payload (metadata.designer) unless your product convention attaches it to a specific capability (both are acceptable if documented).
form_fields Contract¶
Each form field object:
| Key | Required | Type | Notes |
|---|---|---|---|
name |
yes | string | Unique key in form |
label |
yes | string | Visible label |
type |
yes | string | text, textarea, number, boolean, select, code, keyvalue, connection |
required |
no | boolean | Required flag |
default |
no | any | Default value |
options |
select only | array[string] | Allowed options |
placeholder |
no | string | Input hint |
yaml_path |
recommended | string | Dot path on invocation/step object |
Runtime trigger documents (orchestrator)¶
This is not the same object as a capability registry entry: it is the runtime start contract that points at a workflow.
- Triggers are stored as separate YAML/JSON files in a
triggers/directory next toworkflows/, or via the storage serviceGET/PUT /internal/triggerswhen the orchestrator usesORCH_RUNTIME_STORE=http. - Each trigger document has at least:
name,target_workflow(workflow name), andinvocation(same structure as the workflow’sinvocationblock). - Many triggers may share the same
target_workflow(e.g. one HTTP entry and one schedule entry for the same flow). The orchestrator merges theirinvocationvalues at load (union of types and HTTP methods, first-wins for other fields). - The matching workflow file should omit top-level
invocationwhen all start behaviour is defined in trigger documents (otherwise inlineinvocationis overridden with a warning).
UI Ownership Rules (Important)¶
To keep responsibilities separated:
- Icons must be owned by service/capability metadata.
- Descriptions must be owned by service/capability metadata.
- Dashboard should only render metadata and apply neutral fallback values.
- Dashboard must not infer product-specific icon choices from capability names.
Recommended UI fallback order for icon:
metadata.designer.icon/metadata.designer.icon_emoji- capability
icon/icon_emoji - capability
metadata.icon/metadata.icon_emoji - service
icon/icon_emoji - service
metadata.icon/metadata.icon_emoji - neutral fallback (for example
⚡)
Recommended UI fallback order for description:
metadata.designer.description- capability
description - capability
summary - capability
metadata.description - service
description - service
summary - service
metadata.description - neutral fallback (
No description available.)
Example: Trigger Capability¶
{
"service_name": "gateway",
"service_type": "provider",
"service_url": "http://gateway:8080",
"description": "Gateway entrypoint capabilities.",
"icon_emoji": "🌐",
"capabilities": [
{
"name": "gateway.http_trigger",
"version": "1.0.0",
"kind": "trigger",
"description": "HTTP trigger template for workflow entrypoints via gateway.",
"metadata": {
"designer": {
"display_name": "Gateway HTTP Trigger",
"category": "gateway",
"invocation_type": "http",
"description": "Receive HTTP requests and start the workflow.",
"icon_emoji": "🌐",
"form_fields": [
{ "name": "http_method", "label": "HTTP Method", "type": "select", "options": ["GET", "POST"], "default": "POST", "yaml_path": "http_method" }
]
}
}
}
]
}
Example: Workflow Step Capability with Variants¶
{
"name": "script.execute",
"version": "1.2.0",
"kind": "workflow_step",
"description": "Execute scripts in supported runtimes.",
"metadata": {
"designer": {
"category": "compute",
"variants": [
{
"step_type": "script_js",
"display_name": "Execute JavaScript",
"description": "Run a JavaScript snippet in the JS runtime.",
"icon_emoji": "🧩",
"form_fields": [
{ "name": "script", "label": "Script", "type": "code", "required": true, "yaml_path": "script" }
]
},
{
"step_type": "script_py",
"display_name": "Execute Python",
"description": "Run Python code in an isolated runtime.",
"icon_emoji": "🐍",
"form_fields": [
{ "name": "script", "label": "Script", "type": "code", "required": true, "yaml_path": "script" }
]
}
]
}
}
}
Provider Implementation Checklist¶
- Provide
descriptionfor service and each capability. - Provide icon metadata (
iconoricon_emoji) at least at one stable level (designer/capability/service). - For designer-exposed capabilities, provide
metadata.designer.display_name. - For triggers, provide
metadata.designer.invocation_type. - For workflow steps, provide
metadata.designer.step_typeorvariants[]. - Provide
form_fieldsandyaml_pathfor all non-trivial inputs. - Keep semver in
version. - Keep heartbeat and re-registration behavior compliant with registry expectations.
Egress deploy integration (registry-driven providers)¶
For standalone egress microservices discovered via service_call (no orchestrator EGRESS_*_URL env), follow Capability provider deploy integration.
Related Documents¶
wiki/docs/engine/reference/15-capability-registry-and-extensibility-v0.1x.mdwiki/docs/engine/reference/16-capability-registry-implementation-plan-and-feasibility.mdwiki/docs/flows/reference/01-workflow-yaml.mdinternal/capability-provider-template.md