Skip to content

Conversation

chahn
Copy link
Contributor

@chahn chahn commented Jul 7, 2025

Summary

This PR implements structured output support for the SmolAgentsAdapter as described in issue #62. The adapter now handles MCP tools with outputSchema definitions.

Motivation

The latest MCP specifications (2025-06-18+) include support for outputSchema, which enables tools to return structured data with defined schemas.

It would be great to take advantage of the structured output capabilities that MCP now offers. This enhancement would allow smolagents to use tools that return complex data structures, JSON objects, and other structured formats.
With this feature the agent's LLMs can "see" the structure of the tool output before calling a tool.

Implementation Details

I tried to add following:

  • Output Schema Extraction: Extracts outputSchema from MCP tools and passes it to smolagents for inclusion in system prompts
  • Structured Output Detection: Automatically detects when MCP tools provide outputSchema and sets output_type="object" accordingly
  • Enhanced Content Processing: Prioritizes structuredContent from MCP responses when available
  • JSON Parsing: Attempts to parse JSON from text content when structured output is expected
  • Schema Validation: Validates output against provided schema (with warnings, non-strict mode)
  • Backwards Compatibility: Maintains existing behavior when structured_output=False (default)

I implemented a two-level parameter system:

  • structured_output (adapter-level): User-facing flag to enable/disable structured features
  • use_structured_features (tool-level): Internal flag controlling individual tool behavior

Usage

# Original behavior (backwards compatible)
adapter = SmolAgentsAdapter()

# New structured output features
adapter = SmolAgentsAdapter(structured_output=True)

Testing

I added comprehensive tests in tests/test_smolagents_adapter_structured_output.py covering:

  • ✅ Weather tool with structured JSON output
  • ✅ Schema validation with warnings for invalid outputs
  • ✅ List output handling
  • ✅ Fallback behavior for unparseable JSON
  • ✅ Backwards compatibility verification

All existing tests continue to pass, ensuring no breaking changes.

Demo

I prepared a PR for smolagents that is using the structured output feature of SmolAgentsAdaper.
With our changes, smolagents receives the output schema and includes it in the system prompt, enabling the LLM to understand tool output structure. This results in smolagents needing only one step to respond with an answer:

╭──────────────────────────────────────────────── New run ─────────────────────────────────────────────────╮
│                                                                                                          │
│ What is the temperature in Toronto?                                                                      │
│                                                                                                          │
╰─ LiteLLMModel - openai/gpt-4.1 ──────────────────────────────────────────────────────────────────────────╯
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Step 1 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 ─ Executing parsed code: ─────────────────────────────────────────────────────────────────────────────────
  weather_info = weather_tool(location="Toronto")
  temperature = weather_info["temperature"]
  final_answer(f"The temperature in Toronto is {temperature}°F.")
 ──────────────────────────────────────────────────────────────────────────────────────────────────────────
[07/04/25 11:25:40] INFO     Processing request of type CallToolRequest                        server.py:619
Final answer: The temperature in Toronto is 70°F.
[Step 1: Duration 1.99 seconds| Input tokens: 2,328 | Output tokens: 83]

In this example smolgents is using an extended system prompt showing the LLM the output schema of the tool.

...
Above example were using notional tools that might not exist for you. On top of performing computations in the Python code snippets that you create, you only have access to these tools, behaving like regular python functions:
<code>
def weather_tool(location: string) -> object:
    """Get the weather for a given location
    
    Important:
        If this tool is used in your code, you must use the JSON schema below – describing the output of the tool – to access values of the tool output!

    Args:
        location: The location to get the weather for

    Returns:
        object: The output object is a dictionary conforming to the following JSON schema:
            {
                "properties": {
                    "humidity": {
                        "description": "The humidity in percentage",
                        "title": "Humidity",
                        "type": "integer"
                    },
                    "temperature": {
                        "description": "The temperature in Celsius",
                        "title": "Temperature",
                        "type": "integer"
                    },
                    "weather": {
                        "description": "The weather condition",
                        "title": "Weather",
                        "type": "string"
                    },
                    "wind_speed": {
                        "description": "The wind speed in miles per hour",
                        "title": "Wind Speed",
                        "type": "integer"
                    }
                },
                "required": [
                    "weather",
                    "temperature",
                    "humidity",
                    "wind_speed"
                ],
                "title": "Weather",
                "type": "object"
            }
    """
</code>
...

Backwards Compatibility

This implementation maintains 100% backwards compatibility:

  • Default behavior unchanged (structured_output=False)
  • Existing code continues to work without modification
  • New features are opt-in only

Request for Feedback

This is my first contribution to mcpadapt, so I welcome any suggestions for improvements or alternative approaches!

Fixes #62

chahn added 7 commits July 28, 2025 16:12
Structured output was added in MCP spec 2025-06-18+
- Introduced structured output features, allowing conversion of MCP tools to SmolAgents tools with outputSchema support.
- Added validation for output against schema with warnings for non-strict checks.
- Implemented a two-level parameter system for structured output handling, ensuring backwards compatibility.
- Updated example usage and documentation to reflect new capabilities and usage patterns.
- Introduced a new test file to validate structured output handling in SmolAgentsAdapter.
- Implemented tests for various scenarios including weather synchronization, validation of unparseable JSON, and list outputs.
- Ensured that tools return expected structured outputs and that appropriate warnings are logged for invalid outputs.
- Verified schema structures for tools returning lists and simple text outputs, enhancing overall test coverage for the adapter's capabilities.
- Test same tools with both structured_output=False and True
- Verify legacy mode (raw strings/JSON) vs enhanced mode (wrapped objects)
- Ensure existing code compatibility when upgrading adapter settings
@chahn chahn force-pushed the feature/structured-output branch from 7c42963 to 6fb1d0e Compare July 28, 2025 15:03
@chahn
Copy link
Contributor Author

chahn commented Jul 28, 2025

I have merged the latest updates from main and keep all structured output functionality working.

All tests are passing and backwards compatibility works with structured_output=False as default.

I would be very happy about feedback and thank you very much!

- Updated output type strategy to consistently use "object" for maximum flexibility, allowing runtime type detection for text, image, and audio content.
- Removed validation against schema as it is no longer necessary with the new output type approach.
- Adjusted tests to reflect changes in output type expectations, ensuring compatibility with legacy and enhanced modes.
@chahn chahn requested a review from HSGamer July 29, 2025 12:16
Copy link
Contributor

@HSGamer HSGamer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check my previous message. I think we can just check for structureContent in TextContent based on the backward compatibility note in the specification.

@chahn
Copy link
Contributor Author

chahn commented Jul 29, 2025

Thank you very much @HSGamer for your support! I really appreciate your help as I am new to mcpadapt and smolagents.

I have some concerns about parsing TextContent instead of using structuredContent but I am not 100% sure about it.
Let me explain with examples:

Here are some tool examples from the Python implementation of the Model Context Protocol (MCP):
https://github.com/modelcontextprotocol/python-sdk?tab=readme-ov-file#structured-output

The following tools show how TextContent and structuredContent are handled very differently. The output schema would not match the returned content if we rely on the TextContent.

Note: The RAW Response examples below are actual outputs generated by the official Python MCP SDK reference implementation.

Example 1: List

@mcp.tool()
def list_cities() -> list[str]:
    """Get a list of cities"""
    return ["London", "Paris", "Tokyo"]
    # Returns: {"result": ["London", "Paris", "Tokyo"]}

Output Schema:

{
  "type": "object",
  "properties": {
    "result": {
      "items": {
        "type": "string"
      },
      "title": "Result",
      "type": "array"
    }
  },
  "required": [
    "result"
  ],
  "title": "list_citiesOutput"
}

RAW Response:

{
  "content": [
    {
      "type": "text",
      "text": "London"
    },
    {
      "type": "text",
      "text": "Paris"
    },
    {
      "type": "text",
      "text": "Tokyo"
    }
  ],
  "structuredContent": {
    "result": [
      "London",
      "Paris",
      "Tokyo"
    ]
  },
  "isError": false
}

Example 2: Number

@mcp.tool()
def get_temperature(city: str) -> float:
    """Get temperature as a simple float"""
    return 22.5
    # Returns: {"result": 22.5}

Output Schema:

{
  "type": "object",
  "properties": {
    "result": {
      "title": "Result",
      "type": "number"
    }
  },
  "required": [
    "result"
  ],
  "title": "get_temperatureOutput"
}

RAW Response:

{
  "content": [
    {
      "type": "text",
      "text": "22.5"
    }
  ],
  "structuredContent": {
    "result": 22.5
  },
  "isError": false
}

Why This Matters

Problem 1: Lists break apart

  • TextContent splits arrays/lists into separate text blocks
  • How would we know that "London", "Paris", "Tokyo" belong together as one array?
  • The output schema expects {"result": ["London", "Paris", "Tokyo"]} but TextContent gives us three separate strings

Problem 2: Data types are lost

  • Numbers become strings (22.5"22.5")
  • The output schema expects {"result": 22.5} (number) but TextContent gives us "22.5" (string)

Problem 3: Schema mismatch

  • The output schema describes the structure of structuredContent
  • If we parse TextContent, the data won't match the schema that smolagents receives

My Question

Since the MCP spec says tools SHOULD provide both formats for backwards compatibility, shouldn't we:

  1. Use structuredContent when available (matches the output schema perfectly)
  2. Fall back to TextContent when structuredContent is missing (for backwards compatibility)

This approach would...

  • Keep the data structure that matches the output schema
  • Preserve data types (numbers, arrays, objects)
  • Still work with older tools that don't have structured output

With this strategy, would we still need something like structured_output=True/False to control the behavior? Or could we always prefer structuredContent when it exists?

What do you think?

Thank you again for your help!

@HSGamer
Copy link
Contributor

HSGamer commented Jul 29, 2025

Thank you very much @HSGamer for your support! I really appreciate your help as I am new to mcpadapt and smolagents.

I have some concerns about parsing TextContent instead of using structuredContent but I am not 100% sure about it. Let me explain with examples:

Here are some tool examples from the Python implementation of the Model Context Protocol (MCP): modelcontextprotocol/python-sdk#structured-output

The following tools show how TextContent and structuredContent are handled very differently. The output schema would not match the returned content if we rely on the TextContent.

Note: The RAW Response examples below are actual outputs generated by the official Python MCP SDK reference implementation.

Example 1: List

@mcp.tool()
def list_cities() -> list[str]:
    """Get a list of cities"""
    return ["London", "Paris", "Tokyo"]
    # Returns: {"result": ["London", "Paris", "Tokyo"]}

Output Schema:

{
  "type": "object",
  "properties": {
    "result": {
      "items": {
        "type": "string"
      },
      "title": "Result",
      "type": "array"
    }
  },
  "required": [
    "result"
  ],
  "title": "list_citiesOutput"
}

RAW Response:

{
  "content": [
    {
      "type": "text",
      "text": "London"
    },
    {
      "type": "text",
      "text": "Paris"
    },
    {
      "type": "text",
      "text": "Tokyo"
    }
  ],
  "structuredContent": {
    "result": [
      "London",
      "Paris",
      "Tokyo"
    ]
  },
  "isError": false
}

Example 2: Number

@mcp.tool()
def get_temperature(city: str) -> float:
    """Get temperature as a simple float"""
    return 22.5
    # Returns: {"result": 22.5}

Output Schema:

{
  "type": "object",
  "properties": {
    "result": {
      "title": "Result",
      "type": "number"
    }
  },
  "required": [
    "result"
  ],
  "title": "get_temperatureOutput"
}

RAW Response:

{
  "content": [
    {
      "type": "text",
      "text": "22.5"
    }
  ],
  "structuredContent": {
    "result": 22.5
  },
  "isError": false
}

Why This Matters

Problem 1: Lists break apart

  • TextContent splits arrays/lists into separate text blocks
  • How would we know that "London", "Paris", "Tokyo" belong together as one array?
  • The output schema expects {"result": ["London", "Paris", "Tokyo"]} but TextContent gives us three separate strings

Problem 2: Data types are lost

  • Numbers become strings (22.5"22.5")
  • The output schema expects {"result": 22.5} (number) but TextContent gives us "22.5" (string)

Problem 3: Schema mismatch

  • The output schema describes the structure of structuredContent
  • If we parse TextContent, the data won't match the schema that smolagents receives

My Question

Since the MCP spec says tools SHOULD provide both formats for backwards compatibility, shouldn't we:

  1. Use structuredContent when available (matches the output schema perfectly)
  2. Fall back to TextContent when structuredContent is missing (for backwards compatibility)

This approach would...

  • Keep the data structure that matches the output schema
  • Preserve data types (numbers, arrays, objects)
  • Still work with older tools that don't have structured output

With this strategy, would we still need something like structured_output=True/False to control the behavior? Or could we always prefer structuredContent when it exists?

What do you think?

Thank you again for your help!

You can always prefer structuredContent if it's available, since it would always be a TextContent for backward compatibility. So we can either return structuredContent if it exists or add a check for structuredContent in the TextContent. Either ways, we don't need structured_output=True/False at all.

@chahn
Copy link
Contributor Author

chahn commented Jul 30, 2025

Thank you @HSGamer! I'm happy that this make sense to you.
You are right, we can always use structuredContent when it exists.

But I worry about backward compatibility without a solution like structured_output=True/False.

If we always use structuredContent, we will change how the adapter currently works. This could break existing code.

Here's what happens:

The latest releases of MCP Python SDK wrap return values in a {"result": value} object when tools have type hints. This includes primitive types (str, int, float, bool, bytes, None) and generic types (list, tuple, Union, Optional, etc.).
See the documentation: https://github.com/modelcontextprotocol/python-sdk?tab=readme-ov-file#structured-output

What This Means for Users

Smolagents and our tests in tests/test_smolagents_adapter.py would get different results than without the structured output feature. This could break existing code and the tests.

Example: tool in tests/test_smolagents_adapter.py

@mcp.tool()
def echo_tool(text: str) -> str:
    """Echo the input text"""
    return f"Echo: {text}"
  • How it works today: Returns "Echo: hello"
  • With structured output: Returns {"result": "Echo: hello"}

Existing code, and our test expects the simple string "Echo: hello".
If we return {"result": "Echo: hello"}, the code might break and we must modify our tests.

Possible solution:

What if we use structured_output=True/False and make it optional and default to False?

This gives us:

  1. No breaking changes, old code keeps working
  2. New features available, users can turn on structured output when they want it
  3. Safe upgrade path, we can change the default later

Usage in smolagents:

with MCPClient(server_parameters, structured_output=True) as tools:
    # True is passed into MCPAdapt(server_parameters, SmolAgentsAdapter(structured_output=structured_output))
    # smolagents gets structured output + output schema
    # and can render the schema in the CodeAgent system prompt

Advantages:

  • Old code keeps working
  • New structured output features are available when needed
  • Users can upgrade safely
  • Smolagents can use output schemas when enabled

What do you think? Is it worth adding a flag to avoid breaking existing code?

Thank you for helping with these design decisions!

@HSGamer
Copy link
Contributor

HSGamer commented Jul 30, 2025

Thank you @HSGamer! I'm happy that this make sense to you.
You are right, we can always use structuredContent when it exists.

But I worry about backward compatibility without a solution like structured_output=True/False.

If we always use structuredContent, we will change how the adapter currently works. This could break existing code.

Here's what happens:

The latest releases of MCP Python SDK wrap return values in a {"result": value} object when tools have type hints. This includes primitive types (str, int, float, bool, bytes, None) and generic types (list, tuple, Union, Optional, etc.).
See the documentation: https://github.com/modelcontextprotocol/python-sdk?tab=readme-ov-file#structured-output

What This Means for Users

Smolagents and our tests in tests/test_smolagents_adapter.py would get different results than without the structured output feature. This could break existing code and the tests.

Example: tool in tests/test_smolagents_adapter.py

@mcp.tool()
def echo_tool(text: str) -> str:
    """Echo the input text"""
    return f"Echo: {text}"
  • How it works today: Returns "Echo: hello"
  • With structured output: Returns {"result": "Echo: hello"}

Existing code, and our test expects the simple string "Echo: hello".
If we return {"result": "Echo: hello"}, the code might break and we must modify our tests.

Possible solution:

What if we use structured_output=True/False and make it optional and default to False?

This gives us:

  1. No breaking changes, old code keeps working
  2. New features available, users can turn on structured output when they want it
  3. Safe upgrade path, we can change the default later

Usage in smolagents:

with MCPClient(server_parameters, structured_output=True) as tools:
    # True is passed into MCPAdapt(server_parameters, SmolAgentsAdapter(structured_output=structured_output))
    # smolagents gets structured output + output schema
    # and can render the schema in the CodeAgent system prompt

Advantages:

  • Old code keeps working
  • New structured output features are available when needed
  • Users can upgrade safely
  • Smolagents can use output schemas when enabled

What do you think? Is it worth adding a flag to avoid breaking existing code?

Thank you for helping with these design decisions!

Now you mention it, it seems like the structured_content behavior of FastMCP is confusing (or dumb). While the specification requires the JSON output to be serializable as a TextContent and the JSON output is determined by whether the structured_content key exists or not, FastMCP always returns structured_content for any types including str (WTF MCP?).
Well, I guess adding the flag is needed to avoid those "hilarious" implementations.

@grll
Copy link
Owner

grll commented Jul 31, 2025

Thank you @HSGamer! I'm happy that this make sense to you.
You are right, we can always use structuredContent when it exists.
But I worry about backward compatibility without a solution like structured_output=True/False.
If we always use structuredContent, we will change how the adapter currently works. This could break existing code.

Here's what happens:

The latest releases of MCP Python SDK wrap return values in a {"result": value} object when tools have type hints. This includes primitive types (str, int, float, bool, bytes, None) and generic types (list, tuple, Union, Optional, etc.).
See the documentation: https://github.com/modelcontextprotocol/python-sdk?tab=readme-ov-file#structured-output

What This Means for Users

Smolagents and our tests in tests/test_smolagents_adapter.py would get different results than without the structured output feature. This could break existing code and the tests.
Example: tool in tests/test_smolagents_adapter.py

@mcp.tool()
def echo_tool(text: str) -> str:
    """Echo the input text"""
    return f"Echo: {text}"
  • How it works today: Returns "Echo: hello"
  • With structured output: Returns {"result": "Echo: hello"}

Existing code, and our test expects the simple string "Echo: hello".
If we return {"result": "Echo: hello"}, the code might break and we must modify our tests.

Possible solution:

What if we use structured_output=True/False and make it optional and default to False?
This gives us:

  1. No breaking changes, old code keeps working
  2. New features available, users can turn on structured output when they want it
  3. Safe upgrade path, we can change the default later

Usage in smolagents:

with MCPClient(server_parameters, structured_output=True) as tools:
    # True is passed into MCPAdapt(server_parameters, SmolAgentsAdapter(structured_output=structured_output))
    # smolagents gets structured output + output schema
    # and can render the schema in the CodeAgent system prompt

Advantages:

  • Old code keeps working
  • New structured output features are available when needed
  • Users can upgrade safely
  • Smolagents can use output schemas when enabled

What do you think? Is it worth adding a flag to avoid breaking existing code?
Thank you for helping with these design decisions!

Now you mention it, it seems like the structured_content behavior of FastMCP is confusing (or dumb). While the specification requires the JSON output to be serializable as a TextContent and the JSON output is determined by whether the structured_content key exists or not, FastMCP always returns structured_content for any types including str (WTF MCP?). Well, I guess adding the flag is needed to avoid those "hilarious" implementations.

If that's the case we can always patch the fastMCP implementation :)

@HSGamer
Copy link
Contributor

HSGamer commented Jul 31, 2025

If that's the case we can always patch the fastMCP implementation :)

Either ways, I think keeping the flag is fine for now. We can remove it later when we figure out a way to patch FastMCP that makes sense.

@chahn
Copy link
Contributor Author

chahn commented Jul 31, 2025

If that's the case we can always patch the fastMCP implementation :)

Either ways, I think keeping the flag is fine for now. We can remove it later when we figure out a way to patch FastMCP that makes sense.

I totally agree with you @grll and @HSGamer! The MCP specification is not clearly describing all relevant cases. The specification may be intentionally leaving room for interpretation?

I do understand the reasoning behind FastMCP wrapping everything in {"result": ...} for structured output if there is a type annotation at the moment:

When primitive and generic types are wrapped inside the {"result": ...} JSON, an output schema with types can be provided. This way the agent LLM can always see what types to expect from each tool, not only from tools with more complex structured output.

I think they are aware of the compatibility issues as they provide a related flag to ours:

There are two notes in the FastAPI / Python SDK documentation:

Note: For backward compatibility, unstructured results are also returned. Unstructured results are provided for backward compatibility with previous versions of the MCP specification, and are quirks-compatible with previous versions of FastMCP in the current version of the SDK.

Note: In cases where a tool function's return type annotation causes the tool to be classified as structured and this is undesirable, the classification can be suppressed by passing structured_output=False to the @tool decorator.

I think it makes sense to keep the flag in MCPAdapt to be independent of the tool and to be able to decide what we get on the agent side.


@grll I fixed the linter issue with the last commit. Sorry for missing that!

Thanks a lot!

- Update docstring to indicate JSON parsing happens when structured_output=True,
  not just when outputSchema exists
- Clarify that JSON parsing always attempts when structuredContent is absent
- No functional changes, documentation only
@chahn chahn force-pushed the feature/structured-output branch from 83dff8b to 74d45be Compare August 2, 2025 12:10
Copy link
Owner

@grll grll left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank a lot for bringing this feature into mcpadapt! and sorry for the delay in reviewing the work. I have added a few points here and there.

…put coverage

- Add comprehensive tests for structured output type handling
- Add test for warning if tool returns unparseable JSON
@chahn chahn requested a review from grll August 4, 2025 07:32
@chahn
Copy link
Contributor Author

chahn commented Aug 6, 2025

I added the ruff format recommendations in my last commit (612ea05).

Copy link
Contributor Author

@chahn chahn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot @grll for your support and feedback on this PR!

Based on your suggestions I've made the following updates with my latest commits:

  • Kept docstring minimal and informative
  • Used structured_output parameter consistently
  • Refactored tests to focus on types and warnings, tests now validate:
    • Different return types (dict, list, string) are handled with proper schemas
    • Warning messages are properly logged when tools return unparseable JSON
  • Consolidated structured output tests, moved all structured output-related tests to tests/test_smolagents_adapter.py

@grll
Copy link
Owner

grll commented Aug 8, 2025

Thanks a lot @grll for your support and feedback on this PR!

Based on your suggestions I've made the following updates with my latest commits:

  • Kept docstring minimal and informative

  • Used structured_output parameter consistently

  • Refactored tests to focus on types and warnings, tests now validate:

    • Different return types (dict, list, string) are handled with proper schemas
    • Warning messages are properly logged when tools return unparseable JSON
  • Consolidated structured output tests, moved all structured output-related tests to tests/test_smolagents_adapter.py

Hey hey thanks for your patience and sorry again for the time it took to review. I have just added a demo script that showcases the benefits of using structured output it's crazy how much it improves!

@grll
Copy link
Owner

grll commented Aug 8, 2025

@chahn let me know what you think, we should be good to merge

@chahn
Copy link
Contributor Author

chahn commented Aug 8, 2025

@grll Great example, thank you for adding! If everything looks good on your side, feel free to merge.

I’ve already prepared a PR for smolagents to use this new feature. Once this is merged, I’ll open it there and would love your feedback.

Thanks a lot for your support!

@grll grll merged commit e8ac1f7 into grll:main Aug 8, 2025
@grll
Copy link
Owner

grll commented Aug 8, 2025

Thanks again @chahn really impactful change for CodeAgents!

@HSGamer
Copy link
Contributor

HSGamer commented Aug 8, 2025

Good work

@chahn
Copy link
Contributor Author

chahn commented Aug 8, 2025

Thanks again for all your help, @grll and @HSGamer.
I’ve opened a draft PR over there: huggingface/smolagents#1663

I’d really appreciate your feedback when you have a moment.

amithkk pushed a commit to amithkk/mcpadapt that referenced this pull request Sep 6, 2025
…rll#63)

* Update mcp dependency version to 1.10.1 in pyproject.toml

Structured output was added in MCP spec 2025-06-18+

* Enhance SmolAgentsAdapter with structured output support

- Introduced structured output features, allowing conversion of MCP tools to SmolAgents tools with outputSchema support.
- Added validation for output against schema with warnings for non-strict checks.
- Implemented a two-level parameter system for structured output handling, ensuring backwards compatibility.
- Updated example usage and documentation to reflect new capabilities and usage patterns.

* Add tests for SmolAgentsAdapter structured output functionality

- Introduced a new test file to validate structured output handling in SmolAgentsAdapter.
- Implemented tests for various scenarios including weather synchronization, validation of unparseable JSON, and list outputs.
- Ensured that tools return expected structured outputs and that appropriate warnings are logged for invalid outputs.
- Verified schema structures for tools returning lists and simple text outputs, enhancing overall test coverage for the adapter's capabilities.

* Add docstring to test_weather_sync for clarity

* Fix: Merge image/audio support with structured output features

* Update uv.lock for MCP dependency version 1.10.1

* Add backwards compatibility test for structured output

- Test same tools with both structured_output=False and True
- Verify legacy mode (raw strings/JSON) vs enhanced mode (wrapped objects)
- Ensure existing code compatibility when upgrading adapter settings

* Refactor SmolAgentsAdapter to always use "object" output type

- Updated output type strategy to consistently use "object" for maximum flexibility, allowing runtime type detection for text, image, and audio content.
- Removed validation against schema as it is no longer necessary with the new output type approach.
- Adjusted tests to reflect changes in output type expectations, ensuring compatibility with legacy and enhanced modes.

* Remove unused pytest import from structured output test file

* docs: Clarify JSON parsing behavior in structured output mode

- Update docstring to indicate JSON parsing happens when structured_output=True,
  not just when outputSchema exists
- Clarify that JSON parsing always attempts when structuredContent is absent
- No functional changes, documentation only

* refactor: Rename use_structured_features to structured_output in SmolAgentsAdapter

* docs: Update docstring in SmolAgentsAdapter to clarify structured output usage

* refactor: streamline structured output tests for key behaviors

Focus on type correctness, warning cases, and backwards compatibility.

* refactor(tests): enhance smolagents adapter tests with structured output coverage

- Add comprehensive tests for structured output type handling
- Add test for warning if tool returns unparseable JSON

* refactor: improve readability and structure in SmolAgentsAdapter (ruff format recommendation)

* example structured vs not structured output

---------

Co-authored-by: Guillaume Raille <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Feature Request: Parse output schema in smolagents adapter
3 participants