Skip to content

feat: add Pydantic AI integration#76

Open
lfnovo wants to merge 4 commits intomainfrom
pydantic-ai-integration
Open

feat: add Pydantic AI integration#76
lfnovo wants to merge 4 commits intomainfrom
pydantic-ai-integration

Conversation

@lfnovo
Copy link
Owner

@lfnovo lfnovo commented Jan 30, 2026

Summary

  • Add .to_pydantic_ai() method to all language models for seamless Pydantic AI agent integration
  • Implement EsperantoPydanticModel adapter supporting tool calling, streaming, and structured output
  • Enable provider switching (15+ providers) without changing agent code

Changes

New Files

  • src/esperanto/integrations/pydantic_ai.py - Core adapter implementation
  • src/esperanto/integrations/__init__.py - Module exports
  • docs/advanced/pydantic-ai-integration.md - Full usage documentation
  • examples/pydantic_ai_example.py - 6 example use cases
  • tests/unit/test_pydantic_ai_adapter.py - 32 unit tests
  • tests/integration/test_pydantic_ai_integration.py - 11 integration tests

Modified Files

  • src/esperanto/providers/llm/base.py - Added to_pydantic_ai() method
  • src/esperanto/providers/llm/google.py - Schema cleaning and tool response fixes
  • pyproject.toml - Added pydantic-ai optional dependency
  • README.md - Added feature mention and usage example
  • CHANGELOG.md - Added release notes

Provider-Specific Fixes

  • Google: Remove additionalProperties from JSON schemas (not supported)
  • Google: Ensure tool responses are always dict/Struct (not primitives)
  • Ollama: Return Tool objects instead of dicts for tool conversion

Testing

  • 43 tests total (32 unit + 11 integration)
  • Manually tested providers: OpenAI, Anthropic, Google, Groq, Mistral, Azure, xAI, Ollama, DeepSeek

Usage

from esperanto import AIFactory
from pydantic_ai import Agent

# Create model and convert to Pydantic AI
model = AIFactory.create_language("openai", "gpt-4o").to_pydantic_ai()

# Use with Pydantic AI Agent
agent = Agent(model)
result = await agent.run("What is the capital of France?")

Test plan

  • Unit tests pass (uv run pytest tests/unit/test_pydantic_ai_adapter.py -v)
  • Integration tests pass (uv run pytest tests/integration/test_pydantic_ai_integration.py -v)
  • Manual testing with real APIs (OpenAI, Anthropic, Google, etc.)

Add `.to_pydantic_ai()` method to all language models, enabling
seamless integration with Pydantic AI agents.

Features:
- New EsperantoPydanticModel adapter implementing Pydantic AI's Model interface
- Full support for tool calling, streaming, and structured output
- Provider flexibility: switch between 15+ providers without code changes
- EsperantoStreamedResponse for streaming support

Provider-specific fixes:
- Google: Clean JSON schemas (remove unsupported additionalProperties)
- Google: Ensure tool responses are always dict/Struct
- Ollama: Return Tool objects instead of dicts for tool conversion

Testing:
- 32 unit tests for adapter functionality
- 11 integration tests with mocked responses
- Manual testing: OpenAI, Anthropic, Google, Groq, Mistral, Azure, xAI, Ollama, DeepSeek

Documentation:
- Full usage guide at docs/advanced/pydantic-ai-integration.md
- Example with 6 use cases at examples/pydantic_ai_example.py
- Updated README with installation and usage
- Updated CHANGELOG
Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

No issues found across 15 files

1. Add run_context parameter to request_stream() to match new
   pydantic-ai API signature (fixes streaming across all providers)

2. Add _dereference_schema() helper to inline $defs/$ref values
   for Google provider which doesn't support JSON schema references
   (fixes structured output with nested Pydantic models)
Release includes:
- Pydantic AI integration with full streaming, tool calling, and structured output support
- Fix for streaming (new run_context parameter)
- Fix for Google structured output (JSON schema dereferencing)
@claude
Copy link

claude bot commented Jan 30, 2026

Code Review

Found 2 CLAUDE.md compliance issues that need to be addressed:

Issue 1: Missing integrations/ in Project Structure

File: CLAUDE.md (lines 13-30)

The Project Structure section doesn't include the new integrations/ directory added in this PR.

According to CLAUDE.md line 230-231:

AI docs: Keep CLAUDE.md files updated for AI context (this file structure)
Consistency: Documentation should reflect actual implementation

The structure should include:

├── src/esperanto/
│   ├── __init__.py                 # Public API exports
│   ├── factory.py                  # AIFactory for creating provider instances
│   ├── model_discovery.py          # Static model discovery system
│   ├── providers/                  # Provider implementations
│   ├── integrations/               # Third-party framework integrations
│   ├── common_types/               # Shared type definitions
│   └── utils/                      # Cross-cutting utilities

Issue 2: Missing integrations/ in Module Documentation

File: CLAUDE.md (lines 32-41)

The Module Documentation section doesn't reference the new src/esperanto/integrations/CLAUDE.md file.

According to CLAUDE.md line 29:

See detailed documentation in subdirectory CLAUDE.md files.

The Module Documentation section should include:

- **[src/esperanto/integrations/](src/esperanto/integrations/CLAUDE.md)**: Third-party framework integrations

This should be added alongside the existing entries for providers/, common_types/, and utils/.


Summary: The implementation itself is solid with no bugs found. These are documentation consistency issues that ensure the root CLAUDE.md accurately reflects the new project structure.

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.

1 participant