{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://ikanos.io/schemas/v1.0.0-beta2/ikanos.json", "name": "Ikanos Specification", "description": "Ikanos Capability Specification \u2014 describes a capability document (adapter + metadata) or a standalone shared file (consumes / exposes / aggregates / binds). A valid document must declare `ikanos` + exactly one of `capability`, `consumes`, `exposes`, `aggregates`, or `binds`. All adapter logic lives under `capability`; shared section definitions live at root.", "type": "object", "properties": { "ikanos": { "type": "string", "description": "Ikanos specification version. Signals schema compatibility \u2014 always the first key in a capability file.", "const": "1.0.0-beta5" }, "info": { "$ref": "#/$defs/Info", "description": "Human-readable metadata: label, description, tags, dates, stakeholders.\n\n**When to use** \u2014 Required on every capability document. The richer the `description`, the better agents can discover and reason about this capability.\n**Format** \u2014 `created` / `modified` must be `YYYY-MM-DD`. `stakeholders[].role` is free-form (`owner`, `editor`, `reviewer`, etc.)." }, "consumes": { "type": "array", "items": { "oneOf": [ { "$ref": "#/$defs/ConsumesHttp" }, { "$ref": "#/$defs/ImportEntry" } ] }, "minItems": 1, "description": "External HTTP API adapters declared at file scope. Each entry is either an inline `ConsumesHttp` (with `type: http`) or an `ImportEntry` (with a `from` URI). Standalone consumes files use this section at root." }, "exposes": { "type": "array", "items": { "oneOf": [ { "$ref": "#/$defs/ExposesRest" }, { "$ref": "#/$defs/ExposesMcp" }, { "$ref": "#/$defs/ExposesSkill" }, { "$ref": "#/$defs/ExposesControl" }, { "$ref": "#/$defs/ImportEntry" } ] }, "minItems": 1, "description": "Exposed server adapters declared at file scope. Each entry is either an inline adapter (rest/mcp/skill/control) or an `ImportEntry` (with a `from` URI). Standalone exposes files use this section at root." }, "aggregates": { "type": "array", "items": { "oneOf": [ { "$ref": "#/$defs/Aggregate" }, { "$ref": "#/$defs/ImportEntry" } ] }, "minItems": 1, "description": "Domain aggregates declared at file scope. Each entry is either an inline `Aggregate` or an `ImportEntry` (with a `from` URI). Standalone aggregates files use this section at root." }, "binds": { "type": "array", "items": { "oneOf": [ { "$ref": "#/$defs/Binding" }, { "$ref": "#/$defs/ImportEntry" } ] }, "minItems": 1, "description": "External variable bindings available file-wide. Each entry is either an inline `Binding` (with a runtime `location` URI such as `vault://`, `file://`, ...) or an `ImportEntry` (with a parse-time `from` URI to a shared binds file).\n\n**Example**:\n```yaml\nbinds:\n - namespace: secrets\n location: vault://my-vault/secret/data/app\n keys:\n API_KEY: api-key\n DB_PASSWORD: db-password\n```\n**See also** \u2014 `capability.binds` for bindings scoped to a single capability." }, "capability": { "$ref": "#/$defs/Capability", "description": "Technical body of the capability: what it exposes (`exposes`), what it calls (`consumes`), and shared domain logic (`aggregates`). At least one of `exposes`, `consumes`, or `aggregates` is required.\n\n**See also** \u2014 `info` for metadata, `binds` for secrets." } }, "oneOf": [ { "required": [ "ikanos", "capability" ] }, { "required": [ "ikanos", "consumes" ], "not": { "required": [ "capability" ] } }, { "required": [ "ikanos", "exposes" ], "not": { "required": [ "capability" ] } }, { "required": [ "ikanos", "aggregates" ], "not": { "required": [ "capability" ] } }, { "required": [ "ikanos", "binds" ], "not": { "required": [ "capability" ] } } ], "additionalProperties": false, "$defs": { "ImportEntry": { "type": "object", "description": "Unified import directive shared by `consumes`, `exposes`, `aggregates`, and `binds`. Imports a single namespaced entry from another file by its `namespace`, optionally aliasing it locally via `as`. The `from` path is resolved relative to the importing file. Transitive imports are not supported \u2014 each source file must be a self-contained leaf.\n\n**Example**:\n```yaml\nconsumes:\n - from: ./shared/notion-api.yml\n import: notion\n as: notion-shared\n```", "properties": { "from": { "type": "string", "description": "Path or URI to the file that contains the entry to import (e.g. `./shared/notion.yml` or `file:///shared/notion.yml`). Relative paths resolve against the directory of the importing file." }, "import": { "$ref": "#/$defs/IdentifierKebab", "description": "Namespace of the entry to import from the referenced file." }, "as": { "$ref": "#/$defs/IdentifierKebab", "description": "Optional local alias. When set, the imported entry's namespace becomes `as` in the importing document; this enables disambiguation when two sources expose the same name." }, "description": { "type": "string", "description": "Human- and agent-readable description of this import. Helps agents reason about the imported entry." } }, "required": [ "from", "import" ], "additionalProperties": false }, "Binding": { "type": "object", "description": "Declares that the capability binds to an external source of variables. Variables declared via 'keys' are injected using mustache-style expressions.", "properties": { "namespace": { "$ref": "#/$defs/IdentifierKebab", "description": "Unique identifier for this binding. Used as qualifier in expressions for disambiguation." }, "description": { "type": "string", "description": "A meaningful description of the binding's purpose. In a world of agents, context is king." }, "location": { "$ref": "#/$defs/UriLocation", "description": "URI identifying the value provider. The URI scheme expresses the resolution strategy (file://, vault://, github-secrets://, k8s-secret://, etc.). When omitted, values are injected by the runtime environment." }, "keys": { "$ref": "#/$defs/BindingKeys", "description": "Map of variable names to keys in the resolved source. Each key is the variable name used for injection, each value is the corresponding key in the provider." } }, "required": [ "namespace", "keys" ], "additionalProperties": false }, "UriLocation": { "type": "string", "pattern": "^[a-zA-Z][a-zA-Z0-9+.-]*://", "description": "A URI with an explicit scheme identifying the resource provider." }, "BindingVariableName": { "type": "string", "pattern": "^[A-Z][A-Z0-9_]*$", "description": "Variable name for binding injection (SCREAMING_SNAKE_CASE). Enforced for visual distinction from declared parameters in expressions." }, "BindingKeys": { "type": "object", "description": "Map of variable names (SCREAMING_SNAKE_CASE) to source keys in the provider.", "propertyNames": { "$ref": "#/$defs/BindingVariableName" }, "additionalProperties": { "$ref": "#/$defs/IdentifierExtended" } }, "IdentifierKebab": { "type": "string", "description": "Kebab-case identifier (alphanumeric and hyphens).", "pattern": "^[a-zA-Z0-9-]+$" }, "IdentifierExtended": { "type": "string", "description": "Extended identifier (alphanumeric, hyphens, underscores, and wildcard).", "pattern": "^[a-zA-Z0-9-_*]+$" }, "BinarySize": { "type": "string", "description": "A binary size with a mandatory unit (`B`, `KiB`, `MiB`, or `GiB`), e.g. `512KiB`, `5MiB`, `1GiB`. The unit is required to avoid ambiguity (a bare number has no scale).", "pattern": "^\\d+(\\.\\d+)?(B|KiB|MiB|GiB)$" }, "CacheScope": { "type": "string", "description": "Controls whether shared intermediaries may cache the response.", "enum": [ "public", "private" ] }, "ConsumedInputParameter": { "type": "object", "description": "Describes a single function parameter. A unique parameter is defined by a combination of a name and location.", "properties": { "in": { "type": "string", "description": "Location of the parameter", "enum": [ "query", "header", "path", "cookie", "body", "environment" ] }, "value": { "type": "string", "description": "Value of the parameter. Can be a static value or an expression resolved from the execution context (e.g. $this.namespace.param)" } }, "required": [ "in" ], "additionalProperties": false }, "ExposedInputParameter": { "type": "object", "description": "Declares an input parameter for an exposed resource or operation. Type and description are mandatory since the framework cannot infer them.", "properties": { "in": { "type": "string", "description": "Location of the parameter.", "enum": [ "query", "header", "path", "cookie", "body" ] }, "type": { "type": "string", "description": "The expected data type of the parameter.", "enum": [ "string", "number", "integer", "boolean", "array", "object" ] }, "description": { "type": "string", "description": "A meaningful description of the parameter. Used for agent discovery and human documentation." }, "pattern": { "type": "string", "description": "Optional regex pattern for validation. Only applicable when type is 'string'." }, "value": { "type": "string", "description": "Static value or expression resolved from the execution context." } }, "required": [ "in", "type", "description" ], "additionalProperties": false }, "ConsumedOutputParameter": { "type": "object", "description": "Extracts a named value from the raw API response for use in orchestration steps.\n\n**When to use** \u2014 Declare one entry per piece of data you need from the response. The `value` JsonPath expression is evaluated against the parsed response body.\n**Usage** \u2014 Extracted values are referenced by their key in step `with` mappings and `MappedOutputParameter` definitions.\n**Tip** \u2014 For array responses, use JsonPath wildcards (e.g. `$.results[*].id`) to extract a list.", "properties": { "type": { "type": "string", "description": "Expected type of the extracted value. Used for type-checking in step mappings.", "enum": [ "string", "number", "boolean", "object", "array" ] }, "value": { "type": "string", "description": "JsonPath expression evaluated against the parsed response body to extract this parameter. Examples: `$.id`, `$.results[*].name`, `$.meta.total`." } }, "required": [ "type", "value" ], "unevaluatedProperties": false }, "MappedOutputParameterBase": { "type": "object", "description": "Base for an inline-mapped output parameter with recursive typing and JsonPath extraction.", "properties": { "type": { "type": "string", "enum": [ "string", "number", "boolean", "object", "array" ] }, "mapping": { "type": "string", "description": "JsonPath expression to extract the value. E.g. $.properties.Name.title[0].text.content" }, "const": { "description": "Schema-level constant for validation and linting. Not used at runtime for value injection \u2014 use 'value' instead.", "oneOf": [ { "type": "string" }, { "type": "number" }, { "type": "boolean" }, { "type": "array" }, { "type": "object" } ] }, "value": { "type": "string", "description": "Static value injected at runtime. When provided, takes precedence over mapping." } }, "required": [ "type" ] }, "MappedOutputParameterString": { "allOf": [ { "$ref": "#/$defs/MappedOutputParameterBase" }, { "properties": { "type": { "const": "string" }, "mapping": true, "const": true, "value": true }, "oneOf": [ { "required": [ "mapping" ] }, { "required": [ "value" ] } ] } ], "unevaluatedProperties": false }, "MappedOutputParameterNumber": { "allOf": [ { "$ref": "#/$defs/MappedOutputParameterBase" }, { "properties": { "type": { "const": "number" }, "mapping": true, "const": true, "value": true }, "oneOf": [ { "required": [ "mapping" ] }, { "required": [ "value" ] } ] } ], "unevaluatedProperties": false }, "MappedOutputParameterBoolean": { "allOf": [ { "$ref": "#/$defs/MappedOutputParameterBase" }, { "properties": { "type": { "const": "boolean" }, "mapping": true, "const": true, "value": true }, "oneOf": [ { "required": [ "mapping" ] }, { "required": [ "value" ] } ] } ], "unevaluatedProperties": false }, "MappedOutputParameterObject": { "allOf": [ { "$ref": "#/$defs/MappedOutputParameterBase" }, { "properties": { "type": { "const": "object" }, "mapping": true, "const": true, "value": true, "properties": { "type": "object", "description": "A map of named properties. Each key is a property name, each value is a typed output parameter.", "additionalProperties": { "$ref": "#/$defs/MappedOutputParameter" } } }, "required": [ "properties" ] } ], "unevaluatedProperties": false }, "MappedOutputParameterArray": { "allOf": [ { "$ref": "#/$defs/MappedOutputParameterBase" }, { "properties": { "type": { "const": "array" }, "mapping": true, "const": true, "value": true, "items": { "$ref": "#/$defs/MappedOutputParameter" } }, "required": [ "items" ] } ], "unevaluatedProperties": false }, "MappedOutputParameter": { "description": "Inline-mapped output parameter (simple mode). Used when the exposed operation has a single call + with.", "oneOf": [ { "$ref": "#/$defs/MappedOutputParameterString" }, { "$ref": "#/$defs/MappedOutputParameterNumber" }, { "$ref": "#/$defs/MappedOutputParameterBoolean" }, { "$ref": "#/$defs/MappedOutputParameterObject" }, { "$ref": "#/$defs/MappedOutputParameterArray" } ] }, "OrchestratedOutputParameterBase": { "type": "object", "description": "Base for a named output parameter whose value is populated by step mappings during orchestration.", "properties": { "type": { "type": "string", "enum": [ "string", "number", "boolean", "object", "array" ] } }, "required": [ "type" ] }, "OrchestratedOutputParameterScalar": { "allOf": [ { "$ref": "#/$defs/OrchestratedOutputParameterBase" }, { "properties": { "type": { "enum": [ "string", "number", "boolean" ] } } } ], "unevaluatedProperties": false }, "OrchestratedOutputParameterArray": { "allOf": [ { "$ref": "#/$defs/OrchestratedOutputParameterBase" }, { "properties": { "type": { "const": "array" }, "items": { "type": "object", "additionalProperties": { "$ref": "#/$defs/OrchestratedOutputParameter" }, "minProperties": 1 } }, "required": [ "items" ] } ], "unevaluatedProperties": false }, "OrchestratedOutputParameterObject": { "allOf": [ { "$ref": "#/$defs/OrchestratedOutputParameterBase" }, { "properties": { "type": { "const": "object" }, "properties": { "type": "object", "additionalProperties": { "$ref": "#/$defs/OrchestratedOutputParameter" } } }, "required": [ "properties" ] } ], "unevaluatedProperties": false }, "OrchestratedOutputParameter": { "description": "Named output parameter (orchestrated mode). Used when the exposed operation has steps with mappings/lookups.", "oneOf": [ { "$ref": "#/$defs/OrchestratedOutputParameterScalar" }, { "$ref": "#/$defs/OrchestratedOutputParameterArray" }, { "$ref": "#/$defs/OrchestratedOutputParameterObject" } ] }, "MockOutputParameter": { "type": "object", "description": "Named output parameter with a static or template value for mock mode (no call or steps). The value field supports Mustache templates resolved against input parameters at runtime.", "properties": { "type": { "type": "string", "enum": [ "string", "number", "boolean" ] }, "value": { "type": "string", "description": "Static value or Mustache template resolved against input parameters at runtime." } }, "required": [ "type", "value" ], "unevaluatedProperties": false }, "Hostname": { "type": "string", "description": "Valid hostname", "pattern": "^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)(\\.[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$" }, "IPv4": { "type": "string", "description": "Valid IPv4 address", "pattern": "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$" }, "IPv6": { "type": "string", "description": "Valid IPv6 address (simplified)", "pattern": "^([0-9a-fA-F]{0,4}:){2,7}[0-9a-fA-F]{0,4}$" }, "Address": { "description": "hostname or IP for the exposition", "anyOf": [ { "$ref": "#/$defs/Hostname" }, { "$ref": "#/$defs/IPv4" }, { "$ref": "#/$defs/IPv6" } ] }, "Info": { "type": "object", "description": "Information about the capability", "properties": { "display": { "type": "string", "description": "The display name of the capability" }, "description": { "type": "string", "description": "A description of the capability (the more meaningful, the easier for agents discovery)" }, "tags": { "type": "array", "description": "List of tags to help categorize the capability. It can be used for discovery and filtering purposes.", "items": { "type": "string" } }, "created": { "type": "string", "pattern": "^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])$", "description": "The date when the capability was created" }, "modified": { "type": "string", "pattern": "^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])$", "description": "The date when the capability was last modified" }, "version": { "type": "string", "description": "The version of the capability" }, "stakeholders": { "type": "array", "description": "List of stakeholders related to this capability. It can be used for discovery and filtering purposes.", "items": { "$ref": "#/$defs/Person" } } }, "required": [ "display", "description" ], "additionalProperties": false }, "Person": { "type": "object", "description": "A person related to the capability", "properties": { "role": { "type": "string", "description": "The role of the person in relation to the capability. E.g. owner, editor, viewer" }, "fullName": { "type": "string", "description": "The full name of the person" }, "email": { "type": "string", "pattern": "^[a-zA-Z0-9._%+\\-]+@[a-zA-Z0-9.\\-]+\\.[a-zA-Z]{2,}$", "description": "The email address of the person" } }, "required": [ "role", "fullName" ], "additionalProperties": false }, "Capability": { "type": "object", "description": "Capability technical configuration", "properties": { "binds": { "type": "array", "items": { "oneOf": [ { "$ref": "#/$defs/Binding" }, { "$ref": "#/$defs/ImportEntry" } ] }, "minItems": 1, "description": "External sources the capability binds to for variable injection. Inline `Binding` entries or `ImportEntry` references to a shared binds file." }, "exposes": { "type": "array", "description": "List of exposed server adapters. Inline adapters (rest/mcp/skill/control) or `ImportEntry` references to a shared exposes file.", "items": { "oneOf": [ { "$ref": "#/$defs/ExposesRest" }, { "$ref": "#/$defs/ExposesMcp" }, { "$ref": "#/$defs/ExposesSkill" }, { "$ref": "#/$defs/ExposesControl" }, { "$ref": "#/$defs/ImportEntry" } ] }, "minItems": 1 }, "consumes": { "type": "array", "description": "Consumed client adapters. Inline `ConsumesHttp` entries or `ImportEntry` references to a shared consumes file.", "items": { "oneOf": [ { "$ref": "#/$defs/ConsumesHttp" }, { "$ref": "#/$defs/ImportEntry" } ] }, "minItems": 1 }, "aggregates": { "type": "array", "description": "Domain aggregates defining reusable functions that adapters can reference via ref. Inline `Aggregate` entries or `ImportEntry` references to a shared aggregates file.", "items": { "oneOf": [ { "$ref": "#/$defs/Aggregate" }, { "$ref": "#/$defs/ImportEntry" } ] }, "minItems": 1 } }, "anyOf": [ { "required": [ "exposes" ] }, { "required": [ "consumes" ] }, { "required": [ "exposes", "consumes" ] } ], "additionalProperties": false }, "Aggregate": { "type": "object", "description": "A domain aggregate grouping reusable flows. Adapters reference these flows via ref.", "properties": { "display": { "type": "string", "description": "Human-readable name for this aggregate (e.g. 'Forecast')." }, "namespace": { "$ref": "#/$defs/IdentifierKebab", "description": "Machine-readable qualifier for this aggregate. Used as the first segment in ref values. Must match the map key." }, "flows": { "type": "object", "propertyNames": { "$ref": "#/$defs/IdentifierKebab" }, "additionalProperties": { "$ref": "#/$defs/AggregateFlow" }, "description": "Reusable callable flows within this aggregate, keyed by flow name.", "minProperties": 1 } }, "required": [ "display", "flows" ], "additionalProperties": false }, "AggregateFlow": { "type": "object", "description": "A reusable callable flow within an aggregate. Adapter units reference it via ref: aggregate-namespace.flow-name.", "properties": { "description": { "type": "string", "description": "A meaningful description of the flow." }, "tags": { "type": "array", "description": "Arbitrary string tags for filtering and discovery.", "items": { "type": "string" } }, "semantics": { "$ref": "#/$defs/Semantics" }, "outputMediaType": { "type": "string", "description": "Contract-level media type advertised by this flow to downstream `exposes`. Independent of `outputRawFormat`, which is always inherited from the underlying consumed operation (call:) or the terminal step (steps:). Overrides the consumed op's `outputMediaType` for advertisement only; never changes how the entity is parsed." }, "inputParameters": { "type": "object", "propertyNames": { "pattern": "^[a-zA-Z0-9-_*]+$" }, "additionalProperties": { "$ref": "#/$defs/McpToolInputParameter" }, "description": "Function input parameters, keyed by parameter name." }, "call": { "type": "string", "description": "Reference to the consumed operation. Format: {namespace}.{operationId}.", "pattern": "^[a-zA-Z0-9-]+\\.[a-zA-Z0-9-]+$" }, "with": { "$ref": "#/$defs/WithInjector" }, "steps": { "type": "object", "propertyNames": { "$ref": "#/$defs/IdentifierKebab" }, "additionalProperties": { "$ref": "#/$defs/OperationStep" }, "description": "Orchestration steps, keyed by step name.", "minProperties": 1 }, "mappings": { "type": "array", "description": "Maps step outputs to the function's output parameters.", "items": { "$ref": "#/$defs/StepOutputMapping" } }, "outputParameters": true }, "required": [ "description" ], "anyOf": [ { "required": [ "call" ], "type": "object", "properties": { "outputParameters": { "type": "array", "items": { "$ref": "#/$defs/MappedOutputParameter" } } } }, { "required": [ "steps" ], "type": "object", "properties": { "mappings": true, "outputParameters": { "type": "object", "additionalProperties": { "$ref": "#/$defs/OrchestratedOutputParameter" } } } }, { "required": [ "outputParameters" ], "type": "object", "properties": { "outputParameters": { "type": "object", "additionalProperties": { "$ref": "#/$defs/MockOutputParameter" }, "minProperties": 1 } } } ], "additionalProperties": false }, "Semantics": { "type": "object", "description": "Transport-neutral behavioral metadata for an invocable unit. Used for design-time tooling and adapter derivations (e.g. MCP hints).", "properties": { "safe": { "type": "boolean", "description": "If true, the function does not modify state. Default: false." }, "idempotent": { "type": "boolean", "description": "If true, repeating the call has no additional effect. Default: false." }, "cacheable": { "type": "boolean", "description": "If true, the result can be cached. Default: false." } }, "additionalProperties": false }, "ExposesRest": { "type": "object", "description": "REST exposition configuration", "properties": { "type": { "type": "string", "const": "rest" }, "address": { "$ref": "#/$defs/Address" }, "port": { "type": "integer", "minimum": 1, "maximum": 65535 }, "namespace": { "$ref": "#/$defs/IdentifierKebab", "description": "Unique identifier for this exposed API" }, "authentication": { "$ref": "#/$defs/Authentication", "description": "Authentication required on incoming requests to this REST adapter. Protects all resources and operations under this adapter. Supports `basic`, `apikey`, `bearer`, `digest`, and `oauth2` (JWT/introspection)." }, "maxBinarySize": { "$ref": "#/$defs/BinarySize", "description": "Maximum allowed binary response size before buffering. Accepts sizes like '512KiB', '10MiB', '1GiB'. Default: 10MiB. Can be overridden per consumed operation via `maxBinarySize`." }, "resources": { "type": "object", "propertyNames": { "$ref": "#/$defs/IdentifierKebab" }, "additionalProperties": { "$ref": "#/$defs/ExposedResource" }, "description": "Exposed REST resources, keyed by resource name.", "minProperties": 1 } }, "required": [ "type", "port", "namespace" ], "additionalProperties": false }, "ExposesMcp": { "type": "object", "description": "MCP Server exposition configuration. Exposes tools, resources and prompts over MCP transport (Streamable HTTP or stdio).", "properties": { "type": { "type": "string", "const": "mcp" }, "transport": { "type": "string", "enum": [ "http", "stdio" ], "default": "http", "description": "The MCP transport to use. 'http' (default) exposes a Streamable HTTP server; 'stdio' uses stdin/stdout JSON-RPC for local IDE integration." }, "address": { "$ref": "#/$defs/Address" }, "port": { "type": "integer", "minimum": 1, "maximum": 65535 }, "namespace": { "$ref": "#/$defs/IdentifierKebab", "description": "Unique identifier for this exposed MCP server" }, "description": { "type": "string", "description": "A meaningful description of this MCP server's purpose. Used as the server instructions sent during MCP initialization." }, "maxBinarySize": { "$ref": "#/$defs/BinarySize", "description": "Maximum allowed binary response size before base64-encoding. Accepts sizes like '512KiB', '10MiB', '1GiB'. Default: 10MiB. Can be overridden per consumed operation via `maxBinarySize`." }, "ttlMs": { "type": "integer", "description": "A freshness hint (in milliseconds) allowing clients to cache responses and reduce polling. If set to '0', the client will always make a request to the server." }, "cacheScope": { "$ref": "#/$defs/CacheScope", "description": "Controls whether shared intermediaries may cache the response." }, "authentication": { "$ref": "#/$defs/Authentication", "description": "Authentication required on incoming MCP requests. Applied at the transport level; all tools, resources, and prompts under this adapter are protected. Use `oauth2` for standards-compliant MCP authorization servers." }, "tools": { "type": "object", "propertyNames": { "$ref": "#/$defs/IdentifierKebab" }, "additionalProperties": { "$ref": "#/$defs/McpTool" }, "description": "MCP tools exposed by this server, keyed by tool name.", "minProperties": 1 }, "resources": { "type": "object", "propertyNames": { "$ref": "#/$defs/IdentifierKebab" }, "additionalProperties": { "$ref": "#/$defs/McpResource" }, "description": "MCP resources exposed by this server, keyed by resource name.", "minProperties": 1 }, "prompts": { "type": "object", "propertyNames": { "$ref": "#/$defs/IdentifierKebab" }, "additionalProperties": { "$ref": "#/$defs/McpPrompt" }, "description": "MCP prompt templates exposed by this server, keyed by prompt name.", "minProperties": 1 } }, "required": [ "type", "namespace", "tools" ], "oneOf": [ { "properties": { "transport": { "const": "stdio" } }, "required": [ "transport" ], "not": { "required": [ "port" ] } }, { "properties": { "transport": { "const": "http" } }, "required": [ "port" ] } ], "additionalProperties": false }, "McpTool": { "type": "object", "description": "An MCP tool definition. Each tool maps to one or more consumed HTTP operations.", "properties": { "display": { "type": "string", "description": "Human-readable display name of the tool. Mapped to MCP 'title' in tools/list responses." }, "tags": { "type": "array", "description": "Arbitrary string tags for filtering and discovery.", "items": { "type": "string" } }, "description": { "type": "string", "description": "A meaningful description of the tool. Used for agent discovery. Remember, in a world of agents, context is king." }, "inputParameters": { "type": "object", "propertyNames": { "pattern": "^[a-zA-Z0-9-_*]+$" }, "additionalProperties": { "$ref": "#/$defs/McpToolInputParameter" }, "description": "Tool input parameters, keyed by parameter name." }, "ref": { "type": "string", "description": "Reference to an aggregate flow. Format: {aggregate-namespace}.{flow-name}. Inherited fields are merged; explicit fields override.", "pattern": "^[a-zA-Z0-9-]+\\.[a-zA-Z0-9-]+$" }, "call": { "type": "string", "description": "For simple cases, the reference to the consumed operation. Format: {namespace}.{operationId}.", "pattern": "^[a-zA-Z0-9-]+\\.[a-zA-Z0-9-]+$" }, "with": { "$ref": "#/$defs/WithInjector" }, "steps": { "type": "object", "propertyNames": { "$ref": "#/$defs/IdentifierKebab" }, "additionalProperties": { "$ref": "#/$defs/OperationStep" }, "description": "Orchestration steps, keyed by step name.", "minProperties": 1 }, "mappings": { "type": "array", "description": "Maps step outputs to the tool's output parameters.", "items": { "$ref": "#/$defs/StepOutputMapping" } }, "hints": { "$ref": "#/$defs/McpToolHints" }, "outputParameters": true }, "required": [], "anyOf": [ { "required": [ "description", "call" ], "type": "object", "properties": { "outputParameters": { "type": "array", "items": { "$ref": "#/$defs/MappedOutputParameter" } } } }, { "required": [ "description", "steps" ], "type": "object", "properties": { "mappings": true, "outputParameters": { "type": "object", "additionalProperties": { "$ref": "#/$defs/OrchestratedOutputParameter" } } } }, { "required": [ "ref" ] }, { "required": [ "description", "outputParameters" ], "type": "object", "properties": { "outputParameters": { "type": "object", "additionalProperties": { "$ref": "#/$defs/MockOutputParameter" }, "minProperties": 1 } } } ], "additionalProperties": false }, "McpToolHints": { "type": "object", "description": "Optional hints describing tool behavior to MCP clients. All properties are advisory. Mapped to ToolAnnotations in the MCP protocol.", "properties": { "readOnly": { "type": "boolean", "description": "If true, the tool does not modify its environment. Default: false." }, "destructive": { "type": "boolean", "description": "If true, the tool may perform destructive updates. Meaningful only when readOnly is false. Default: true." }, "idempotent": { "type": "boolean", "description": "If true, calling the tool repeatedly with the same arguments has no additional effect. Meaningful only when readOnly is false. Default: false." }, "openWorld": { "type": "boolean", "description": "If true, the tool may interact with external entities. Default: true." } }, "additionalProperties": false }, "McpToolInputParameter": { "type": "object", "description": "Declares an input parameter for an MCP tool. These become properties in the tool's JSON Schema input definition.", "properties": { "type": { "type": "string", "description": "The expected data type of the parameter.", "enum": [ "string", "number", "integer", "boolean", "array", "object" ] }, "description": { "type": "string", "description": "A meaningful description of the parameter. Used for agent discovery and tool documentation." }, "required": { "type": "boolean", "description": "Whether the parameter is required. Defaults to true.", "default": true } }, "required": [ "type", "description" ], "additionalProperties": false }, "McpResource": { "type": "object", "description": "An MCP resource definition. Exposes data that agents can read. Either dynamic (backed by consumed HTTP operations via call/steps) or static (served from local files via location).", "properties": { "display": { "type": "string", "description": "Human-readable display name of the resource. Mapped to MCP 'title' in protocol responses." }, "uri": { "type": "string", "description": "The URI that identifies this resource in MCP. Can use any scheme (e.g. config://, docs://, data://). For resource templates, use {param} placeholders." }, "description": { "type": "string", "description": "A meaningful description of the resource. Used for agent discovery. In a world of agents, context is king." }, "mimeType": { "type": "string", "description": "MIME type of the resource content per RFC 6838 (e.g. application/json, text/markdown, text/plain).", "pattern": "^[a-zA-Z0-9!#$&^_.+-]+\\/[a-zA-Z0-9!#$&^_.+-]+(?:\\s*;\\s*[a-zA-Z0-9!#$&^_.+-]+=(?:[a-zA-Z0-9!#$&^_.+-]+|\"[^\"]*\"))*$" }, "binary": { "type": "boolean", "default": false, "description": "For dynamic resources: when true, the resource read returns `BlobResourceContents` (base64 `blob` + `mimeType`) instead of `TextResourceContents`. The target consumed operation must declare `outputRawFormat: binary`. Defaults to false to preserve the text path." }, "call": { "type": "string", "description": "For dynamic resources: reference to the consumed operation. Format: {namespace}.{operationId}.", "pattern": "^[a-zA-Z0-9-]+\\.[a-zA-Z0-9-]+$" }, "with": { "$ref": "#/$defs/WithInjector" }, "steps": { "type": "object", "propertyNames": { "$ref": "#/$defs/IdentifierKebab" }, "additionalProperties": { "$ref": "#/$defs/OperationStep" }, "description": "Orchestration steps, keyed by step name.", "minProperties": 1 }, "mappings": { "type": "array", "description": "Maps step outputs to the resource content.", "items": { "$ref": "#/$defs/StepOutputMapping" } }, "outputParameters": { "type": [ "array", "object" ] }, "location": { "type": "string", "format": "uri", "pattern": "^file:///", "description": "For static resources: file:/// URI pointing to a directory whose files are served as MCP resources." } }, "required": [ "display", "uri", "description" ], "oneOf": [ { "required": [ "call" ], "type": "object", "properties": { "outputParameters": { "type": "array", "items": { "$ref": "#/$defs/MappedOutputParameter" } } }, "not": { "required": [ "location" ] } }, { "required": [ "steps" ], "type": "object", "properties": { "mappings": true, "outputParameters": { "type": "object", "additionalProperties": { "$ref": "#/$defs/OrchestratedOutputParameter" } } }, "not": { "required": [ "location" ] } }, { "required": [ "location" ], "not": { "anyOf": [ { "required": [ "call" ] }, { "required": [ "steps" ] } ] } } ], "additionalProperties": false }, "McpPrompt": { "type": "object", "description": "An MCP prompt template definition. Prompts are reusable templates with typed arguments that agents can discover and render.", "properties": { "display": { "type": "string", "description": "Human-readable display name of the prompt. Mapped to MCP 'title' in protocol responses." }, "description": { "type": "string", "description": "A meaningful description of the prompt and when to use it. Used for agent discovery." }, "arguments": { "type": "object", "propertyNames": { "pattern": "^[a-zA-Z0-9-_*]+$" }, "additionalProperties": { "$ref": "#/$defs/McpPromptArgument" }, "description": "Prompt arguments, keyed by argument name." }, "template": { "type": "array", "description": "Inline prompt template as an array of messages. Each message has a role and content with {{arg}} placeholders.", "items": { "$ref": "#/$defs/McpPromptMessage" }, "minItems": 1 }, "location": { "type": "string", "format": "uri", "pattern": "^file:///", "description": "File-based prompt: file:/// URI pointing to a file containing the prompt template with {{arg}} placeholders. Content becomes a single 'user' message." } }, "required": [ "display", "description" ], "oneOf": [ { "required": [ "template" ], "not": { "required": [ "location" ] } }, { "required": [ "location" ], "not": { "required": [ "template" ] } } ], "additionalProperties": false }, "McpPromptArgument": { "type": "object", "description": "An argument for an MCP prompt template. Arguments are always strings per MCP spec.", "properties": { "display": { "type": "string", "description": "The display name of the argument. Used for agent discovery." }, "description": { "type": "string", "description": "A meaningful description of the argument. Used for agent discovery." }, "required": { "type": "boolean", "description": "Whether the argument is required. Defaults to true.", "default": true } }, "required": [ "description" ], "additionalProperties": false }, "McpPromptMessage": { "type": "object", "description": "A message in an inline MCP prompt template. Supports {{arg}} placeholders for argument substitution.", "properties": { "role": { "type": "string", "enum": [ "user", "assistant" ], "description": "The role of the message sender." }, "content": { "type": "string", "description": "The message content. Supports {{arg}} placeholders for argument substitution." } }, "required": [ "role", "content" ], "additionalProperties": false }, "ExposedResource": { "type": "object", "description": "An exposed resource", "properties": { "display": { "type": "string", "description": "Display name for the resource. It will likely be used in UIs." }, "tags": { "type": "array", "description": "Arbitrary string tags for filtering and discovery.", "items": { "type": "string" } }, "description": { "type": "string", "description": "Used to provide *meaningful* information about the resource. Remember, in a world of agents, context is king." }, "path": { "type": "string", "description": "Path of the resource (supports {{param}} placeholders)" }, "inputParameters": { "type": "object", "propertyNames": { "pattern": "^[a-zA-Z0-9-_*]+$" }, "additionalProperties": { "$ref": "#/$defs/ExposedInputParameter" }, "description": "Resource-level input parameters (e.g. path params), keyed by parameter name." }, "operations": { "type": "object", "propertyNames": { "$ref": "#/$defs/IdentifierKebab" }, "additionalProperties": { "$ref": "#/$defs/ExposedOperation" }, "description": "Operations on this resource, keyed by operation name.", "minProperties": 1 }, "forward": { "$ref": "#/$defs/ForwardConfig" } }, "required": [ "path" ], "anyOf": [ { "required": [ "operations" ] }, { "required": [ "forward" ] } ], "additionalProperties": false }, "ExposedOperation": { "type": "object", "description": "An operation exposed on a resource.", "properties": { "display": { "type": "string", "description": "Display name for the operation. Used in UIs." }, "tags": { "type": "array", "description": "Arbitrary string tags for filtering and discovery.", "items": { "type": "string" } }, "description": { "type": "string", "description": "Used to provide *meaningful* information about the operation. Remember, in a world of agents, context is king." }, "method": { "type": "string", "enum": [ "GET", "POST", "PUT", "PATCH", "DELETE" ], "default": "GET" }, "inputParameters": { "type": "object", "propertyNames": { "pattern": "^[a-zA-Z0-9-_*]+$" }, "additionalProperties": { "$ref": "#/$defs/ExposedInputParameter" }, "description": "Operation input parameters, keyed by parameter name." }, "ref": { "type": "string", "description": "Reference to an aggregate flow. Format: {aggregate-namespace}.{flow-name}. Inherited fields are merged; explicit fields override.", "pattern": "^[a-zA-Z0-9-]+\\.[a-zA-Z0-9-]+$" }, "call": { "type": "string", "description": "For simple cases, the reference to the consumed operation. Format: {namespace}.{operationId}. E.g.: notion.get-database or github.get-user", "pattern": "^[a-zA-Z0-9-]+\\.[a-zA-Z0-9-]+$" }, "with": { "$ref": "#/$defs/WithInjector" }, "outputParameters": true, "steps": { "type": "object", "propertyNames": { "$ref": "#/$defs/IdentifierKebab" }, "additionalProperties": { "$ref": "#/$defs/OperationStep" }, "description": "Orchestration steps, keyed by step name.", "minProperties": 1 }, "mappings": { "type": "array", "description": "Maps step outputs to the operation's output parameters.", "items": { "$ref": "#/$defs/StepOutputMapping" } }, "responses": { "type": "object", "propertyNames": { "pattern": "^[1-5][0-9X]{2}$" }, "additionalProperties": { "type": "object", "description": "A single HTTP status-code entry in a REST operation's response contract. Mirrors the OpenAPI Response Object subset Ikanos exports.", "properties": { "description": { "type": "string", "description": "Human-readable description of this response. Exported verbatim to the OpenAPI `responses..description`." }, "content": { "type": "object", "propertyNames": { "pattern": "^[a-zA-Z0-9!#$&^_.+-]+\\/[a-zA-Z0-9!#$&^_.+-]+(?:\\s*;\\s*[a-zA-Z0-9!#$&^_.+-]+=(?:[a-zA-Z0-9!#$&^_.+-]+|\"[^\"]*\"))*$" }, "additionalProperties": { "type": "object", "description": "The payload contract for one media type. Either `binary: true` (raw bytes, exported as `type: string, format: binary`) or an inline structured `schema`.", "properties": { "binary": { "type": "boolean", "default": false, "description": "When true, this media type returns raw bytes. Exported to OpenAPI as `schema: { type: string, format: binary }`. Requires the terminal consumed operation to declare `outputRawFormat: binary`." }, "schema": { "type": "object", "description": "Inline JSON Schema for a non-binary structured response. Ignored when `binary` is true.", "additionalProperties": true } }, "additionalProperties": false }, "description": "Response payloads keyed by media type (e.g. `image/jpeg`, `application/json`).", "minProperties": 1 } }, "additionalProperties": false }, "description": "Explicit per-status-code response contract for this REST operation, keyed by HTTP status code (e.g. '200', '404'). Used to declare binary response media types and to drive OpenAPI export. Mutually exclusive with `responseBinary`." }, "responseBinary": { "type": "object", "description": "Shorthand for a single successful binary response. Normalized into the full `responses` structure at spec load. Mutually exclusive with `responses`.", "properties": { "status": { "type": "integer", "minimum": 100, "maximum": 599, "default": 200, "description": "HTTP status code for the binary response. Defaults to 200." }, "mediaType": { "type": "string", "pattern": "^[a-zA-Z0-9!#$&^_.+-]+\\/[a-zA-Z0-9!#$&^_.+-]+(?:\\s*;\\s*[a-zA-Z0-9!#$&^_.+-]+=(?:[a-zA-Z0-9!#$&^_.+-]+|\"[^\"]*\"))*$", "description": "Response media type (e.g. `image/jpeg`, `application/pdf`, `application/octet-stream`)." }, "description": { "type": "string", "description": "Human-readable description exported to OpenAPI `responses..description`." } }, "required": [ "mediaType" ], "additionalProperties": false } }, "required": [ "method" ], "not": { "required": [ "responses", "responseBinary" ] }, "anyOf": [ { "properties": { "outputParameters": { "items": { "$ref": "#/$defs/MappedOutputParameter" } } } }, { "required": [ "steps" ], "properties": { "mappings": true, "outputParameters": { "type": "object", "additionalProperties": { "$ref": "#/$defs/OrchestratedOutputParameter" } } } }, { "required": [ "ref" ] } ], "additionalProperties": false }, "WithInjector": { "type": "object", "description": "A map of key-value pairs that binds input parameters of the called operation to values or expressions resolved from the execution context.", "additionalProperties": { "oneOf": [ { "type": "string" }, { "type": "number" } ] } }, "ConsumesHttp": { "type": "object", "description": "Inline HTTP API adapter. Declares the base URI, shared input parameters, authentication, and resources for an upstream HTTP service.\n\n**When to use** \u2014 Define one `ConsumesHttp` per upstream API (e.g. one for Notion, one for GitHub). Declare it at root-level `consumes[]` to share across capabilities, or under `capability.consumes[]` to scope it locally.\n**Execution model** \u2014 The framework uses `namespace` as the call target. Operations are resolved by matching `ConsumedHttpResource.name` + `ConsumedHttpOperation.name`.\n**See also** \u2014 `ImportedConsumesHttp` (cross-file reuse), `ForwardConfig` (header forwarding), `Authentication` (security).", "properties": { "namespace": { "$ref": "#/$defs/IdentifierKebab", "description": "Unique adapter identifier (kebab-case). Used as the call target: `call: namespace.resource.operation`. Must be unique within the file." }, "type": { "type": "string", "const": "http" }, "description": { "type": "string", "description": "Human- and agent-readable description of this upstream API. Explain what the API does, its domain (e.g. project management, code hosting), and any important constraints. Agents use this to decide which adapter to call." }, "baseUri": { "type": "string", "description": "Root URL of the upstream API (scheme + host + optional base path). No path parameters allowed here \u2014 use `ConsumedHttpResource.path` for per-resource segments. Example: `https://api.notion.com/v1`.", "pattern": "^https?://[^/]+(/[^{]*)?$" }, "inputParameters": { "type": "object", "propertyNames": { "pattern": "^[a-zA-Z0-9-_*]+$" }, "additionalProperties": { "$ref": "#/$defs/ConsumedInputParameter" }, "description": "Adapter-level parameters injected into every request, keyed by parameter name." }, "authentication": { "$ref": "#/$defs/Authentication", "description": "Authentication applied to every request of this adapter. Can be overridden at operation level. Supports `basic`, `apikey`, `bearer`, `digest`, and `oauth2`." }, "tunnel": { "$ref": "#/$defs/TunnelConfig", "description": "Optional reverse-tunnel transport for reaching APIs behind a firewall. When set, the engine dials the consumed API through the configured overlay instead of the public internet. The TLS / authentication layer declared via `authentication` runs unchanged on top of the tunnel.\n\n**Engine support** \u2014 declarative only in this schema version; runtime engine wiring lands in a later release. Capabilities that declare `tunnel:` parse and validate today, but the engine still dials the public `baseUri` directly until the embedded tunnel feature is enabled. See the Reverse Tunnel guide for the sidecar pattern that works today." }, "resources": { "type": "object", "propertyNames": { "$ref": "#/$defs/IdentifierKebab" }, "additionalProperties": { "$ref": "#/$defs/ConsumedHttpResource" }, "description": "HTTP resources of the upstream API, keyed by resource name.", "minProperties": 1 } }, "required": [ "namespace", "type", "baseUri" ], "additionalProperties": false }, "TunnelConfig": { "description": "Tunnel transport configuration for a `ConsumesHttp`. Use `type: ziti` to dial through an OpenZiti overlay. Additional types (e.g. `frp`, `cloudflared`) may be added in future versions; the `type` discriminator keeps existing capabilities forward-compatible.\n\n**See also** \u2014 `TunnelZiti` for the OpenZiti shape. The capability `binds` block is the recommended source for tunnel identities \u2014 never inline the identity JSON directly.", "oneOf": [ { "$ref": "#/$defs/TunnelZiti" } ] }, "TunnelZiti": { "type": "object", "description": "OpenZiti zero-trust overlay transport. The Ikanos engine dials the configured Ziti service for every request to the parent `ConsumesHttp.baseUri`, using the supplied identity. End-to-end mTLS runs through the overlay; application-layer TLS (declared via `authentication`) runs on top.", "properties": { "type": { "type": "string", "const": "ziti", "description": "Discriminator for the tunnel transport. Always `ziti` for this shape." }, "service": { "type": "string", "description": "Ziti service name to dial (e.g. `crm-api`). Defined in the Ziti controller and authorized for this capability's identity. Routing happens by service name \u2014 not by IP or DNS." }, "identity": { "type": "string", "description": "Ziti identity used to authenticate to the controller. Recommended form: a Mustache expression resolved from `binds` (e.g. `{{secrets.ZITI_IDENTITY}}`). A bare filesystem path is allowed for local development but discouraged in production. The Polychro rule `ikanos-tunnel-identity-must-bind` requires Mustache references to resolve to an existing binding." }, "fallback": { "type": "string", "enum": [ "fail", "direct" ], "default": "fail", "description": "Behavior when the tunnel cannot be established. `fail` (default) \u2014 operations return a 503-equivalent. `direct` \u2014 engine attempts a direct HTTP call to `baseUri`; NOT recommended for production, intended for local development against a stubbed upstream. The Polychro rule `ikanos-tunnel-fallback-direct-warns` warns when `direct` is used against a non-loopback baseUri." } }, "required": [ "type", "service", "identity" ], "additionalProperties": false }, "ConsumedHttpResource": { "type": "object", "description": "A logical resource group on the upstream API. Combines a path segment with a set of HTTP operations and optional shared parameters.\n\n**When to use** \u2014 Each distinct REST resource (e.g. `/databases`, `/pages/{id}`) maps to one `ConsumedHttpResource`. Group operations that share the same base path and lifecycle.\n**Naming** \u2014 `name` is used as part of the call reference: `call: namespace.resource-name.operation-name`.\n**See also** \u2014 `ConsumedHttpOperation` (individual method + body), `ConsumedInputParameter` (path/query/header params).", "properties": { "display": { "type": "string", "description": "Human-readable label for editors and documentation. Does not affect runtime behavior." }, "tags": { "type": "array", "description": "Arbitrary string tags for filtering and discovery.", "items": { "type": "string" } }, "description": { "type": "string", "description": "Description of what this resource represents in the upstream API (e.g. 'A Notion database object \u2014 a structured collection of pages'). Used for agent discovery." }, "path": { "type": "string", "description": "Path segment appended to `ConsumesHttp.baseUri`. May include path parameters in curly-brace notation (e.g. `/databases/{databaseId}`). Path parameters must be declared in `inputParameters` with `in: path`." }, "inputParameters": { "type": "object", "propertyNames": { "pattern": "^[a-zA-Z0-9-_*]+$" }, "additionalProperties": { "$ref": "#/$defs/ConsumedInputParameter" }, "description": "Resource-level parameters shared by all operations, keyed by parameter name." }, "operations": { "type": "object", "propertyNames": { "$ref": "#/$defs/IdentifierKebab" }, "additionalProperties": { "$ref": "#/$defs/ConsumedHttpOperation" }, "description": "HTTP operations on this resource, keyed by operation name.", "minProperties": 1 } }, "required": [ "path", "operations" ], "additionalProperties": false }, "ConsumedHttpOperation": { "type": "object", "description": "An operation on a consumed HTTP resource", "properties": { "display": { "type": "string" }, "tags": { "type": "array", "description": "Arbitrary string tags for filtering and discovery.", "items": { "type": "string" } }, "description": { "type": "string", "description": "Used to provide *meaningful* information about the operation. Remember, in a world of agents, context is king." }, "method": { "type": "string", "enum": [ "GET", "POST", "PUT", "PATCH", "DELETE" ], "default": "GET", "description": "HTTP method for this operation. Defaults to `GET`." }, "inputParameters": { "type": "object", "propertyNames": { "pattern": "^[a-zA-Z0-9-_*]+$" }, "additionalProperties": { "$ref": "#/$defs/ConsumedInputParameter" }, "description": "Operation input parameters, keyed by parameter name." }, "outputRawFormat": { "type": "string", "enum": [ "json", "xml", "avro", "protobuf", "csv", "tsv", "psv", "yaml", "html", "markdown", "binary" ], "default": "json", "description": "The raw format of the response from the consumed API. It is used to determine how to parse the response and extract the output parameters. Delimited formats: csv (comma), tsv (tab), psv (pipe). Use `binary` to buffer the raw bytes without UTF-8 decoding (images, audio, PDFs, archives) and propagate the upstream Content-Type. Default value is json." }, "outputMediaType": { "type": "string", "description": "Contract-level response media type. Independent of `outputRawFormat`: applies equally to parsed responses (JSON, XML, YAML) and to binary responses. Overrides the upstream Content-Type for advertised media types (REST headers, OAS `responses.content.` keys, MCP `TextResourceContents.mimeType` / `BlobResourceContents.mimeType`) but does not change how the entity is parsed." }, "maxBinarySize": { "$ref": "#/$defs/BinarySize", "description": "Per-operation override of the adapter-level maxBinarySize. Accepts sizes like '512KiB', '5MiB', '1GiB'. Only meaningful when `outputRawFormat` is `binary`." }, "outputSchema": { "type": "string", "description": "Format-specific schema or selector:\n- **avro / protobuf** \u2014 path to the schema file (required for these formats).\n- **html** \u2014 CSS selector to scope table extraction (e.g. `table.results`).\n- **markdown** \u2014 Heading prefix to filter sections (e.g. `## Results`).\n- Other formats \u2014 unused." }, "outputParameters": { "type": "object", "additionalProperties": { "$ref": "#/$defs/ConsumedOutputParameter" } }, "body": { "$ref": "#/$defs/RequestBody", "description": "Optional request body (POST/PUT/PATCH). Choose the variant matching the upstream API content-type: `json`, `text`/`xml`/`sparql`, `formUrlEncoded`, `multipartForm`, or a raw string." } }, "required": [ "method" ], "not": { "required": [ "responses", "responseBinary" ] }, "anyOf": [ { "properties": { "outputParameters": { "items": { "$ref": "#/$defs/MappedOutputParameter" } } } }, { "required": [ "steps" ], "properties": { "mappings": true, "outputParameters": { "type": "object", "additionalProperties": { "$ref": "#/$defs/OrchestratedOutputParameter" } } } }, { "required": [ "ref" ] } ], "additionalProperties": false }, "OperationStepBase": { "type": "object", "properties": { "type": { "type": "string", "enum": [ "call", "lookup", "script" ] } }, "required": [ "type" ] }, "OperationStepCall": { "allOf": [ { "$ref": "#/$defs/OperationStepBase" }, { "properties": { "type": { "const": "call" }, "call": { "type": "string", "description": "Reference to the consumed operation. Format: {namespace}.{operationId}.", "pattern": "^[a-zA-Z0-9-]+\\.[a-zA-Z0-9-]+$" }, "with": { "$ref": "#/$defs/WithInjector" } }, "required": [ "call" ] } ], "unevaluatedProperties": false }, "OperationStepLookup": { "allOf": [ { "$ref": "#/$defs/OperationStepBase" }, { "properties": { "type": { "const": "lookup" }, "index": { "$ref": "#/$defs/IdentifierKebab", "description": "Name of a previous call step whose output serves as the lookup table." }, "match": { "$ref": "#/$defs/IdentifierKebab", "description": "Name of the key field in the index to match against." }, "lookupValue": { "type": "string", "description": "JsonPath expression resolving to the value(s) to look up." }, "outputParameters": { "type": "array", "description": "List of field names to extract from the matched index entries.", "items": { "type": "string" }, "minItems": 1 } }, "required": [ "index", "match", "lookupValue", "outputParameters" ] } ], "unevaluatedProperties": false }, "OperationStepScript": { "allOf": [ { "$ref": "#/$defs/OperationStepBase" }, { "properties": { "type": { "const": "script" }, "language": { "type": "string", "enum": [ "javascript", "python", "groovy" ], "description": "GraalVM language identifier for the script engine. Optional when 'management.scripting.defaultLanguage' is set in the Control Port \u2014 the engine falls back to the default." }, "location": { "type": "string", "format": "uri", "pattern": "^file:///", "description": "file:/// URI pointing to the scripts directory. Follows the same convention as ExposedSkill.location \u2014 a directory root from which 'file' and 'dependencies' are resolved as relative paths. Optional when 'management.scripting.defaultLocation' is set in the Control Port \u2014 the engine falls back to the default." }, "file": { "type": "string", "description": "Relative path to the main script file within the 'location' directory. The script must assign to the 'result' variable to produce output. Path segments must match [a-zA-Z0-9._-]+ (same validation as Skill instruction paths).", "minLength": 1 }, "dependencies": { "type": "array", "description": "Relative paths to dependent script files within the 'location' directory, pre-evaluated in order before the main script. Each dependent script can define helper functions, constants, or shared logic.", "items": { "type": "string", "minLength": 1 }, "minItems": 1 }, "with": { "$ref": "#/$defs/WithInjector" } }, "required": [ "file" ] } ], "unevaluatedProperties": false }, "OperationStep": { "oneOf": [ { "$ref": "#/$defs/OperationStepCall" }, { "$ref": "#/$defs/OperationStepLookup" }, { "$ref": "#/$defs/OperationStepScript" } ] }, "StepOutputMapping": { "type": "object", "description": "Describes how to map the output of an operation step to the input of another step or to the output of the exposed operation", "properties": { "target": { "type": "string", "pattern": "^[a-zA-Z0-9-_.]+$", "description": "The name of the parameter to map to. Supports dot-notation for nested objects (e.g. route.from). It can be an input parameter of a next step or an output parameter of the exposed operation" }, "value": { "type": "string", "description": "A JsonPath reference to the value to map from. E.g. $.get-database.database_id" } }, "required": [ "target", "value" ], "additionalProperties": false }, "RequestBodyJson": { "type": "object", "description": "JSON request body. Sends `data` serialized as `application/json`. `data` can be a static string, object, or array \u2014 or a Mustache template string resolved from the execution context.", "properties": { "type": { "type": "string", "const": "json" }, "data": { "description": "Payload serialized as JSON. Accepts a static string (Mustache-interpolated at runtime), an inline object, or an inline array.", "oneOf": [ { "type": "string" }, { "type": "object" }, { "type": "array" } ] } }, "required": [ "type", "data" ], "additionalProperties": false }, "RequestBodyText": { "type": "object", "description": "Plain-text, XML, or SPARQL request body. Sends `data` as a string with the matching content-type (`text/plain`, `application/xml`, or `application/sparql-query`).", "properties": { "type": { "type": "string", "description": "Content-type variant: `text` \u2192 `text/plain`, `xml` \u2192 `application/xml`, `sparql` \u2192 `application/sparql-query`.", "enum": [ "text", "xml", "sparql" ] }, "data": { "type": "string", "description": "Body string. Supports Mustache interpolation for runtime value injection." } }, "required": [ "type", "data" ], "additionalProperties": false }, "RequestBodyFormUrlEncoded": { "type": "object", "description": "URL-encoded form request body (`application/x-www-form-urlencoded`). Suitable for OAuth token endpoints and legacy form APIs.", "properties": { "type": { "type": "string", "const": "formUrlEncoded" }, "data": { "description": "Form fields. Provide either a pre-encoded string or a key\u2192value object whose values are URL-encoded by the framework.", "oneOf": [ { "type": "string", "description": "Pre-encoded form string (e.g. `grant_type=client_credentials&scope=read`)." }, { "type": "object", "description": "Key\u2013value map of form fields. Values must be strings; the framework handles encoding.", "additionalProperties": { "type": "string" } } ] } }, "required": [ "type", "data" ], "additionalProperties": false }, "RequestBodyMultipartFormPart": { "type": "object", "description": "A single part in a `multipart/form-data` request. Use `filename` + `contentType` to attach files; omit them for plain form fields.", "properties": { "name": { "type": "string", "description": "Form field name for this part." }, "value": { "type": "string", "description": "Content of this part. For file parts, this is the base64-encoded or raw file content." }, "filename": { "type": "string", "description": "Optional file name hint sent in `Content-Disposition`. Presence signals to the server that this part is a file upload." }, "contentType": { "type": "string", "description": "MIME type for this part (e.g. `image/png`, `application/pdf`). Required when uploading a file." } }, "required": [ "name", "value" ], "additionalProperties": false }, "RequestBodyMultipartForm": { "type": "object", "description": "Multipart form request body (`multipart/form-data`). Use for file uploads or mixed text+file payloads. Each part is a `RequestBodyMultipartFormPart`.", "properties": { "type": { "type": "string", "const": "multipartForm" }, "data": { "type": "array", "description": "Ordered list of form parts. Mix plain fields (no `filename`) and file parts (`filename` + `contentType`) as needed.", "items": { "$ref": "#/$defs/RequestBodyMultipartFormPart" } } }, "required": [ "type", "data" ], "additionalProperties": false }, "RequestBodyRaw": { "type": "string", "description": "Raw body string sent as-is. Use a YAML block scalar (`|`) for multi-line payloads. The framework treats the string as JSON by default; pair with a `Content-Type` input parameter to override." }, "RequestBody": { "description": "Request body attached to a `ConsumedHttpOperation`. Choose the variant that matches the upstream API's expected content-type:\n- `json` \u2192 `application/json` (object, array, or template string)\n- `text` / `xml` / `sparql` \u2192 plain text / XML / SPARQL query\n- `formUrlEncoded` \u2192 `application/x-www-form-urlencoded`\n- `multipartForm` \u2192 `multipart/form-data` (file uploads)\n- raw string \u2192 sent as-is (override content-type via an `inputParameter` with `in: header`)", "oneOf": [ { "$ref": "#/$defs/RequestBodyJson" }, { "$ref": "#/$defs/RequestBodyText" }, { "$ref": "#/$defs/RequestBodyFormUrlEncoded" }, { "$ref": "#/$defs/RequestBodyMultipartForm" }, { "$ref": "#/$defs/RequestBodyRaw" } ] }, "ForwardConfig": { "type": "object", "description": "Configuration for transparently forwarding incoming requests to a `ConsumesHttp` adapter.\n\n**When to use** \u2014 Attach to an `ExposesRest` or `ExposesMcp` adapter when you want to proxy or relay requests to an upstream API without writing explicit operation logic.\n**Security** \u2014 Only headers listed in `trustedHeaders` are forwarded; all others are stripped to avoid leaking internal headers.\n**See also** \u2014 `ConsumesHttp.namespace` as the forward target, `Authentication` on the target adapter for upstream credentials.", "properties": { "targetNamespace": { "$ref": "#/$defs/IdentifierKebab", "description": "Namespace of the `ConsumesHttp` adapter to forward requests to. Must match a `namespace` declared in `consumes[]`." }, "trustedHeaders": { "type": "array", "items": { "type": "string" }, "description": "Allowlist of incoming HTTP header names that may be forwarded to the upstream adapter. Headers not in this list are stripped before forwarding. Example: `[\"Authorization\", \"X-Correlation-Id\"]`.", "minItems": 1 } }, "required": [ "targetNamespace" ], "additionalProperties": false }, "Authentication": { "description": "Authentication strategy applied to outgoing requests (on `ConsumesHttp`) or to incoming request validation (on `Exposes*`). Choose the variant matching the upstream or downstream security model:\n- `basic` \u2014 HTTP Basic (username + password)\n- `apikey` \u2014 API key in header or query string\n- `bearer` \u2014 Static Bearer token\n- `digest` \u2014 HTTP Digest (username + password)\n- `oauth2` \u2014 OAuth 2.1 resource server (JWT validation or token introspection)", "oneOf": [ { "$ref": "#/$defs/AuthBasic" }, { "$ref": "#/$defs/AuthApiKey" }, { "$ref": "#/$defs/AuthBearer" }, { "$ref": "#/$defs/AuthDigest" }, { "$ref": "#/$defs/AuthOAuth2" } ] }, "AuthBasic": { "type": "object", "description": "HTTP Basic authentication (`Authorization: Basic `). Credentials are base64-encoded by the framework at runtime \u2014 do not pre-encode them here. Use environment variable expressions (e.g. `$env.MY_PASSWORD`) to avoid hardcoding secrets.", "properties": { "type": { "type": "string", "const": "basic" }, "username": { "type": "string", "description": "Username. Supports environment variable expressions (e.g. `$env.API_USER`)." }, "password": { "type": "string", "description": "Password. Supports environment variable expressions (e.g. `$env.API_PASSWORD`). Never hardcode secrets in YAML." } }, "required": [ "type" ], "additionalProperties": false }, "AuthApiKey": { "type": "object", "description": "API Key authentication. Injects a named key\u2013value pair into every request, either as a request header or a query parameter. Common for services like Notion (`Authorization: Bearer`), OpenWeather (`appid=...`), etc.", "properties": { "type": { "type": "string", "const": "apikey" }, "key": { "type": "string", "description": "Name of the header or query parameter (e.g. `X-Api-Key`, `api_key`, `Authorization`)." }, "value": { "type": "string", "description": "API key value. Supports environment variable expressions (e.g. `$env.NOTION_TOKEN`). Never hardcode secrets." }, "placement": { "type": "string", "enum": [ "header", "query" ], "description": "Where to place the key: `header` (as an HTTP request header) or `query` (as a URL query parameter). Defaults to `header` when omitted." } }, "required": [ "type" ], "additionalProperties": false }, "AuthBearer": { "type": "object", "description": "Static Bearer token authentication (`Authorization: Bearer `). Use for APIs that issue long-lived tokens (service accounts, PATs). For dynamic token refresh, use `oauth2` instead.", "properties": { "type": { "type": "string", "const": "bearer" }, "token": { "type": "string", "description": "Bearer token value. Supports environment variable expressions (e.g. `$env.GITHUB_TOKEN`). Never hardcode secrets." } }, "required": [ "type" ], "additionalProperties": false }, "AuthDigest": { "type": "object", "description": "HTTP Digest authentication (RFC 7616). The framework performs the full challenge\u2013response handshake automatically. Used by older APIs that require digest over basic.", "properties": { "type": { "type": "string", "const": "digest" }, "username": { "type": "string", "description": "Username for digest auth. Supports environment variable expressions (e.g. `$env.API_USER`)." }, "password": { "type": "string", "description": "Password for digest auth. Supports environment variable expressions (e.g. `$env.API_PASSWORD`). Never hardcode secrets." } }, "required": [ "type" ], "additionalProperties": false }, "AuthOAuth2": { "type": "object", "description": "OAuth 2.1 resource server authentication. The server validates bearer tokens issued by an external authorization server.", "properties": { "type": { "type": "string", "const": "oauth2" }, "authorizationServerUri": { "type": "string", "format": "uri", "description": "Issuer URI of the OAuth 2.1 authorization server. The engine derives metadata endpoints (.well-known/oauth-authorization-server) from this URI." }, "resource": { "type": "string", "format": "uri", "description": "Canonical URI of this server (RFC 8707). Used for audience validation and Protected Resource Metadata." }, "scopes": { "type": "array", "items": { "type": "string" }, "description": "Scopes this resource server recognizes." }, "audience": { "type": "string", "description": "Expected 'aud' claim in the JWT. Defaults to the 'resource' URI if not set." }, "tokenEndpoint": { "type": "string", "format": "uri", "description": "Token endpoint URI of the authorization server. Used by the OpenAPI exporter as the clientCredentials tokenUrl. When omitted, the exporter falls back to authorizationServerUri (with a warning)." }, "tokenValidation": { "type": "string", "enum": [ "jwks", "introspection" ], "default": "jwks", "description": "How to validate incoming access tokens. 'jwks' (default): fetch the AS public keys and validate JWT signatures locally. 'introspection': call the AS token introspection endpoint (RFC 7662) for each request." } }, "required": [ "type", "authorizationServerUri", "resource" ], "additionalProperties": false }, "ExposesSkill": { "type": "object", "description": "Skill server adapter \u2014 metadata and catalog layer. Skills declare tools derived from sibling api or mcp adapters or defined as local file instructions. Does not execute tools.", "properties": { "type": { "type": "string", "const": "skill" }, "address": { "$ref": "#/$defs/Address" }, "port": { "type": "integer", "minimum": 1, "maximum": 65535 }, "namespace": { "$ref": "#/$defs/IdentifierKebab", "description": "Unique identifier for this skill server" }, "description": { "type": "string", "description": "Description of this skill server's purpose" }, "authentication": { "$ref": "#/$defs/Authentication", "description": "Authentication required on incoming requests to this skill server. Protects the skills catalog and tool invocation endpoints." }, "skills": { "type": "object", "propertyNames": { "$ref": "#/$defs/IdentifierKebab" }, "additionalProperties": { "$ref": "#/$defs/ExposedSkill" }, "description": "Skill definitions, keyed by skill name.", "minProperties": 1 } }, "required": [ "type", "port", "namespace", "skills" ], "additionalProperties": false }, "ExposedSkill": { "type": "object", "description": "A skill definition with full Agent Skills Spec frontmatter. Declares tools derived from sibling api or mcp adapters or defined as local file instructions, or stands alone as purely descriptive (no tools).", "properties": { "description": { "type": "string", "maxLength": 1024, "description": "What the skill does and when to use it. Used for agent discovery." }, "license": { "type": "string", "description": "License identifier (e.g., MIT, Apache-2.0)" }, "compatibility": { "type": "string", "maxLength": 500, "description": "Compatibility notes and requirements" }, "metadata": { "type": "object", "additionalProperties": { "type": "string" }, "description": "Arbitrary key-value metadata (author, category, tags, ecosystem, etc.)" }, "allowed-tools": { "type": "string", "maxLength": 1024, "description": "Space-delimited list of pre-approved tool names (Agent Skills Spec)" }, "argument-hint": { "type": "string", "description": "Hint text shown when agents invoke this skill via slash command (Agent Skills Spec)" }, "user-invocable": { "type": "boolean", "default": true, "description": "Whether agents can invoke this skill as a slash command (Agent Skills Spec)" }, "disable-model-invocation": { "type": "boolean", "default": false, "description": "Whether to prevent auto-loading this skill based on context (Agent Skills Spec)" }, "location": { "type": "string", "format": "uri", "pattern": "^file:///", "description": "file:/// URI to a directory containing SKILL.md and supporting files. Required when any tool uses 'instruction'." }, "tools": { "type": "object", "propertyNames": { "$ref": "#/$defs/IdentifierKebab" }, "additionalProperties": { "$ref": "#/$defs/SkillTool" }, "description": "Tools declared by this skill, keyed by tool name.", "minProperties": 1 } }, "required": [ "description" ], "additionalProperties": false }, "SkillTool": { "type": "object", "description": "A tool declared within a skill. Exactly one of 'from' (derived from a sibling api or mcp adapter) or 'instruction' (local file path relative to the skill's location) must be specified.", "properties": { "description": { "type": "string", "description": "What the tool does. Used for agent discovery." }, "from": { "type": "object", "description": "Derive this tool from a sibling api or mcp adapter.", "properties": { "sourceNamespace": { "type": "string", "description": "Namespace of a sibling exposes[] entry of type api or mcp" }, "action": { "type": "string", "description": "Operation name (api) or tool name (mcp) in the source adapter" } }, "required": [ "sourceNamespace", "action" ], "additionalProperties": false }, "instruction": { "type": "string", "description": "File path relative to the skill's location directory containing the tool instruction content" } }, "required": [ "description" ], "oneOf": [ { "required": [ "from" ] }, { "required": [ "instruction" ] } ], "additionalProperties": false }, "ExposesControl": { "type": "object", "description": "Control adapter \u2014 management plane for health, metrics, traces, and runtime diagnostics. Endpoints are engine-provided, not user-defined.", "properties": { "type": { "type": "string", "const": "control" }, "address": { "$ref": "#/$defs/Address", "default": "localhost", "description": "Bind address for the control port. Defaults to localhost for security." }, "port": { "type": "integer", "minimum": 1, "maximum": 65535, "description": "TCP port for the control adapter." }, "authentication": { "$ref": "#/$defs/Authentication", "description": "Optional authentication for the control port. Reuses the same Authentication model as business adapters." }, "management": { "$ref": "#/$defs/ControlManagementSpec" }, "observability": { "$ref": "#/$defs/ObservabilitySpec" } }, "required": [ "type", "port" ], "additionalProperties": false }, "ControlManagementSpec": { "type": "object", "description": "Toggle individual control port management endpoint groups. Does not include OTel-dependent endpoints (metrics, traces) \u2014 those are configured under observability.", "properties": { "health": { "type": "boolean", "default": true, "description": "Enable /health/live and /health/ready endpoints." }, "info": { "type": "boolean", "default": false, "description": "Enable /status and /config endpoints. Disabled by default." }, "reload": { "type": "boolean", "default": false, "description": "Enable POST /config/reload. Disabled by default." }, "validate": { "type": "boolean", "default": false, "description": "Enable POST /config/validate (dry-run validation). Disabled by default." }, "logs": { "oneOf": [ { "type": "boolean", "description": "Simple mode: true enables all /logs endpoints (level control + streaming with default max-subscribers). false disables all." }, { "$ref": "#/$defs/ControlLogsEndpointSpec" } ], "default": false, "description": "Configure /logs endpoints for log level control and SSE streaming. Accepts a boolean (simple) or an object (advanced)." }, "scripting": { "$ref": "#/$defs/ScriptingManagementSpec" } }, "additionalProperties": false }, "ControlLogsEndpointSpec": { "type": "object", "description": "Advanced configuration for /logs endpoints (log level control and SSE streaming).", "properties": { "level-control": { "type": "boolean", "default": true, "description": "Enable /logs and /logs/{logger} endpoints for live log level control. Default: true (enabled when logs object is present)." }, "stream": { "type": "boolean", "default": false, "description": "Enable /logs/stream SSE endpoint. Disabled by default." }, "max-subscribers": { "type": "integer", "minimum": 1, "maximum": 20, "default": 5, "description": "Maximum concurrent SSE subscribers for log streaming." } }, "additionalProperties": false }, "ScriptingManagementSpec": { "type": "object", "description": "Scripting governance controls exposed via the Control Port. Configures defaults, limits, and runtime toggles for script steps.", "properties": { "enabled": { "type": "boolean", "default": true, "description": "Runtime toggle to enable or disable script step execution. When false, all script steps fail fast with a descriptive error. Overrides the IKANOS_SCRIPTING env var when set." }, "defaultLocation": { "type": "string", "format": "uri", "pattern": "^file:///", "description": "Default scripts directory for all script steps. When set, individual steps can omit 'location' and the engine resolves 'file' and 'dependencies' from this directory. Steps with an explicit 'location' override this default." }, "defaultLanguage": { "type": "string", "enum": [ "javascript", "python", "groovy" ], "description": "Default language for all script steps. When set, individual steps can omit 'language' and the engine uses this default. Steps with an explicit 'language' override this default." }, "timeout": { "type": "integer", "minimum": 1, "default": 60000, "description": "Execution timeout in milliseconds for each script step. Overrides the engine default (60000 ms)." }, "statementLimit": { "type": "integer", "minimum": 1, "default": 100000, "description": "Maximum number of statements a script can execute. Applies to JavaScript and Python only. Groovy scripts are not subject to this limit. Overrides the engine default (100,000)." }, "allowedLanguages": { "type": "array", "items": { "type": "string", "enum": [ "javascript", "python", "groovy" ] }, "description": "Restrict which script languages are permitted. If omitted, all languages supported by the build are allowed." } }, "additionalProperties": false }, "ObservabilitySpec": { "type": "object", "description": "Spec-driven observability configuration. Controls distributed tracing, metrics collection, and their local exposure on the control port. All fields are optional \u2014 defaults to OTel env vars when not specified.", "properties": { "enabled": { "type": "boolean", "default": true, "description": "Enable or disable observability. Defaults to true." }, "metrics": { "$ref": "#/$defs/ObservabilityMetricsSpec" }, "traces": { "$ref": "#/$defs/ObservabilityTracesSpec" }, "exporters": { "$ref": "#/$defs/ObservabilityExportersSpec" } }, "unevaluatedProperties": false }, "ObservabilityMetricsSpec": { "type": "object", "description": "Metrics collection and local exposure configuration.", "properties": { "local": { "$ref": "#/$defs/ObservabilityLocalEndpointSpec", "description": "Controls the /metrics Prometheus scrape endpoint on the control port." } }, "unevaluatedProperties": false }, "ObservabilityTracesSpec": { "type": "object", "description": "Trace sampling, propagation, and local exposure configuration.", "properties": { "sampling": { "type": "number", "minimum": 0, "maximum": 1, "default": 1.0, "description": "Trace sampling rate. 1.0 = sample all, 0.1 = sample 10%." }, "propagation": { "type": "string", "enum": [ "w3c", "b3" ], "default": "w3c", "description": "Context propagation format for outgoing HTTP calls." }, "local": { "$ref": "#/$defs/ObservabilityTracesLocalSpec", "description": "Controls the /traces endpoint on the control port." } }, "unevaluatedProperties": false }, "ObservabilityLocalEndpointSpec": { "type": "object", "description": "Toggle for a local observability endpoint on the control port.", "properties": { "enabled": { "type": "boolean", "default": true, "description": "Enable or disable the local endpoint. Defaults to true." } }, "unevaluatedProperties": false }, "ObservabilityTracesLocalSpec": { "type": "object", "description": "Configuration for the /traces endpoint on the control port.", "properties": { "enabled": { "type": "boolean", "default": true, "description": "Enable the /traces endpoint. Defaults to true." }, "buffer-size": { "type": "integer", "minimum": 10, "maximum": 10000, "default": 100, "description": "Maximum number of completed trace summaries to retain in the ring buffer." } }, "unevaluatedProperties": false }, "ObservabilityExportersSpec": { "type": "object", "description": "Exporter configuration container.", "properties": { "otlp": { "$ref": "#/$defs/ObservabilityOtlpExporterSpec" } }, "unevaluatedProperties": false }, "ObservabilityOtlpExporterSpec": { "type": "object", "description": "OTLP exporter endpoint configuration.", "properties": { "endpoint": { "type": "string", "description": "OTLP exporter endpoint. Supports Mustache expressions for binds." } }, "required": [ "endpoint" ], "unevaluatedProperties": false } } }