universal-tool-calling-protocol/python-utcp

Look into pydantic-ai

Closed this issue · 8 comments

Look into pydantic-ai

Do you need to integrate it with pydantic-ai just like the langchain integration? Can I take this task? @h3xxit

No description provided.

Yeah that would be great thanks!

Yeah that would be great thanks!
Here's the implementation @h3xxit

UTCP ↔ PydanticAI Adapters: tooling discovery, conversion, examples, and tests

This PR implements adapters to use UTCP tools with PydanticAI. It enables discovering tools (from OpenAPI specs or manual definitions), converting them into Pydantic-friendly tools, and invoking them cleanly in async workflows.

Resolves: pydantic-ai #6

Motivation

Provide a PydanticAI integration equivalent to the existing LangChain support in UTCP.
Standardize discovery and invocation across HTTP/SSE/Text using UTCP while exposing ergonomic models for PydanticAI.
Offer clear examples and tests so end-users can adopt UTCP with Pydantic quickly and safely.
Scope of changes

Package: pydantic_utcp_adapters/
pydantic_tools.py: Core adapter to wrap UTCP tools as PydanticAI tools.
Converts UTCP input schemas to Pydantic v2 models.
Async invocation of UTCP tools with validated inputs.
Tool search and bulk-load helpers.
pydantic_bedrock.py: Utilities for Bedrock naming compatibility.
Added missing import for create_model; ready for future Bedrock flows.
init.py: Exports for easy consumption.
Examples: examples/
pydantic_basic_use.py: Basic UTCP client + tool loading.
pydantic_direct_use.py: Inline UTCP configuration; HTTPS and Pydantic v2 updates.
pydantic_openapi.py: OpenAPI discovery to UTCP tools.
pydantic_providers.py: Real providers demo (OpenLibrary + NewsAPI manual).
Robust path resolution for newsapi_manual.json.
Prints input schema safely using dicts (no deprecated schema()).
pydantic_auth.py: Patterns for API Key, Basic, OAuth2 (placeholder creds).
newsapi_manual.json:
Updated to current UTCP text manual schema using tool_call_template/call_template_type.
Added auth.location: "header".
Removed obsolete top-level version.
Tests: tests/
test_pydantic_tools.py, test_pydantic_real_providers.py.
21 tests passing locally.
Project setup:
pyproject.toml (PDM): Proper [project] metadata; dependencies for utcp, utcp-http, utcp-text, pydantic; removed unused mcp.
README.md: Complete setup, testing, and examples with PDM; compatibility matrix; UTCP manual schema note; badges; license.
LICENSE: MIT.
CI: Minimal GitHub Actions workflow for pdm install + pytest.
How to run (PDM)

Install:
bash
pdm install
Run tests:
bash
pdm run pytest
Run examples:
Basic:
bash
pdm run python examples/pydantic_basic_use.py
Direct:
bash
pdm run python examples/pydantic_direct_use.py
OpenAPI:
bash
pdm run python examples/pydantic_openapi.py
Real providers (OpenLibrary + optional NewsAPI manual):
bash
pdm run python examples/pydantic_providers.py
If you want to actually call NewsAPI endpoints, export your key:
bash
export NEWS_API_KEY=your_key
Compatibility

Python 3.11+
Pydantic 2.11.x
UTCP core >= 1.0.4
UTCP HTTP >= 1.0.4
UTCP Text >= 1.0.2
Notes and design decisions

Pydantic v2: All schemas use model_json_schema(); deprecated schema() calls removed from examples.
Security: Examples use HTTPS or localhost to satisfy UTCP constraints.
UTCP manual schema: Uses tool_call_template/call_template_type; documented in README.
Packaging: PDM is the source of truth; setup.py removed to avoid confusion.
Testing performed

Local runs:
pdm install
pdm run pytest → 21 tests passed
pdm run python examples/pydantic_providers.py → loads 13 tools (2 NewsAPI, 11 OpenLibrary) and successfully invokes a sample tool.
Examples that hit network endpoints require internet.
Follow-ups (optional)

Add Python version matrix (3.11, 3.12) to CI.
Add coverage reporting to CI (pytest-cov + Codecov).
Consider a small validator script in CI for UTCP manual JSONs to avoid schema regressions.
Checklist

PDM project installs cleanly.
Tests pass locally.
Examples run from project root.
README documents setup, tests, examples, and manual schema format.
License included (MIT).

Real providers example output confirms tools discovered and a working call; logs available in the PR discussion if useful.
Thanks for reviewing! If there’s a preferred naming or packaging style for the adapters, I’m happy to align.

Very nice, thank you! I'll review it and let you know!

Very nice, thank you! I'll review it and let you know!

Hey @h3xxit, following up on this—happy to make any changes or improvements once you’ve had a look.

Sorry, it took very long for me to get back to this, but its great. Only 2 notices.

  1. Somewhere in the docs you wrote (probably vibe coded) Unified Tool Calling Protocol instead of Universal Tool Calling protocol.
    and
  2. In the pydantic_tools in the
class PydanticAITool:
    """Wrapper for UTCP tools to be used with PydanticAI or generic async usage."""

    def __init__(self, utcp_client: UtcpClient, tool: UTCPTool):
        self.utcp_client = utcp_client
        self.tool = tool
        self.name = tool.name
        self.description = tool.description or f"UTCP tool: {tool.name}"

        # Build input model from UTCP JsonSchema/Pydantic model
        if hasattr(tool.inputs, "model_dump"):
            schema_dict = tool.inputs.model_dump(by_alias=True, exclude_none=True)
        elif hasattr(tool.inputs, "__dict__"):
            schema_dict = tool.inputs.__dict__
        elif isinstance(tool.inputs, dict):
            schema_dict = tool.inputs
        else:
            schema_dict = {"type": "object", "properties": {}}

        self.input_model = _create_pydantic_model_from_schema(
            schema_dict, f"{tool.name.replace('.', '_')}Input"
        )

You should serialize the UTCPTool using the ToolSerializer into a dict and then get the inputs. That way its gonna be in the correct format whatever internal changes happen in UTCP.

That being said, thank you very much for the contribution. I have invited you to the organization. If you can then transfer the repo to the org, I will make you the maintainer of it.

Please feel free to also join the discord where I will also give you the contributor role, I am much more active there, so I wont miss any messages: https://discord.gg/Y6Ycyz8nJR

And finally please let me know your name and any links you want added to the contributors page: https://www.utcp.io/about/about-us

@h3xxit I've fixed the Readme, used ToolSerializer and updated the test cases to work as per ToolSerializer as well in the last commit.

I've joined the organization and transferred the repo to it as well.

For the contributors page - My name is "Raj Panchal"
link - https://www.linkedin.com/in/raj-a-panchal/

-Thank you for this wonderful opportunity!