microsoft/semantic-kernel · error · AgentInitializationException

Invalid JSON in OpenAPI 'specification' field: {e}

Error message

Invalid JSON in OpenAPI 'specification' field: {e}

What it means

Raised when the OpenAPI tool's 'specification' option is a string but json.loads fails to parse it. The builder first tries to parse strings as JSON (passing objects through unchanged), so this only fires for malformed JSON text. The original JSONDecodeError is chained as the cause for debugging.

Source

Thrown at python/semantic_kernel/agents/azure_ai/azure_ai_agent.py:213


@_register_tool("openapi")
def _openapi(spec: ToolSpec) -> OpenApiTool:
    opts = spec.options or {}

    if not spec.id:
        raise AgentInitializationException("OpenAPI tool requires a non-empty 'id' (used as name).")
    if not spec.description:
        raise AgentInitializationException(f"OpenAPI tool '{spec.id}' requires a 'description'.")

    raw_spec = opts.get("specification")
    if not raw_spec:
        raise AgentInitializationException(f"OpenAPI tool '{spec.id}' is missing required 'specification' field.")

    try:
        parsed_spec = json.loads(raw_spec) if isinstance(raw_spec, str) else raw_spec
    except json.JSONDecodeError as e:
        raise AgentInitializationException(f"Invalid JSON in OpenAPI 'specification' field: {e}") from e

    auth = opts.get("auth", OpenApiAnonymousAuthDetails())

    return OpenApiTool(
        name=spec.id,
        description=spec.description,
        spec=parsed_spec,
        auth=auth,
        default_parameters=opts.get("default_parameters"),
    )


def _build_tool(spec: ToolSpec, kernel: "Kernel") -> ToolDefinition:
    if not spec.type:
        raise AgentInitializationException("Tool spec must include a 'type' field.")

    try:
        builder = _TOOL_BUILDERS[spec.type.lower()]

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Validate the specification string with a JSON linter (e.g. python -m json.tool) before passing it.
  2. If your source is YAML, parse it first (yaml.safe_load) and pass the resulting dict, not the raw YAML text.
  3. Pass the specification as a pre-parsed dict/object to bypass string parsing entirely.
  4. Inspect the chained exception 'e' (position/column) to locate the syntax error.

Example fix

// before
options:
  specification: "openapi: 3.0.0\npaths: /weather"  # YAML, not JSON
// after
import yaml, json
spec = yaml.safe_load(open('openapi.yaml'))
options = {"specification": json.dumps(spec)}  # or pass spec dict directly
Defensive patterns

Strategy: validation

Validate before calling

import json
def ensure_valid_json_specification(opts):
    spec = opts.get('specification')
    if isinstance(spec, str):
        json.loads(spec)  # raises early with a clear error
    return spec
# call on each openapi tool's options before agent creation

Type guard

def is_json_or_object(v) -> bool:
    if not isinstance(v, str):
        return isinstance(v, (dict, list))
    try:
        json.loads(v); return True
    except json.JSONDecodeError:
        return False

Try / catch

try:
    agent = await AzureAIAgent._from_dict(data, kernel=kernel, client=client)
except AgentInitializationException as e:
    cause = e.__cause__
    if isinstance(cause, json.JSONDecodeError):
        log.error('Malformed JSON specification at line %s col %s', cause.lineno, cause.colno)
    raise

Prevention

When it happens

Trigger: Passing options.specification as a string that contains YAML instead of JSON; a string with trailing commas, single quotes, or comments; a truncated/copy-pasted spec string; a file read that included a BOM or surrounding whitespace/newlines that break strict JSON.

Common situations: Authoring the OpenAPI doc by hand as a string literal and using YAML/JS-style syntax; loading a .yaml OpenAPI file into the string field instead of converting it to JSON; embedding a JSON string with f-string interpolation that introduced stray characters.

Understand the failure class

Related errors


AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13). Data as JSON: /api/errors/01235b8e33bb47de. Report an issue: GitHub.