Files
agents/sdk/python/tests/test_skill_pydantic_models.py
zeekayandGitHub 5b5cf9e9db feat: merge AgentField control plane + SDKs as Hanzo Agents (#1)
Transforms hanzoai/agents from a marketplace config repo into a full
agent orchestration platform by merging the AgentField infrastructure:

- Go control plane (K8s-like agent orchestration, service mesh, DAG workflows)
- Python SDK (FastAPI-based agent framework, LiteLLM, memory, DID/VC)
- TypeScript SDK (@hanzo/agents - Vercel AI SDK, MCP, workflows)
- Go SDK (idiomatic agent builder + client)
- React 19 embedded dashboard (XyFlow DAGs, Recharts, Radix UI)
- Docker/K8s/Helm deployment configs
- Examples: hello world, deep research, RAG, simulation, benchmarks
- Functional test suite across Python/Go/TypeScript

All references rebranded: AgentField → Hanzo Agents
- Module: github.com/hanzoai/agents/control-plane
- Python: hanzo_agents
- TypeScript: @hanzo/agents
- Go: github.com/hanzoai/agents/sdk/go
- Env vars: HANZO_AGENTS_*
- Config: hanzo-agents.yaml

Previous marketplace configs moved to config/ directory.
2026-02-09 18:53:09 -08:00

146 lines
4.9 KiB
Python

"""
Unit tests for Pydantic model support in skills.
Tests that skills can now accept Pydantic models as parameters,
providing the same developer experience as reasoners.
"""
import pytest
from typing import Optional
from pydantic import BaseModel
from hanzo_agents import Agent
from hanzo_agents.pydantic_utils import should_convert_args, convert_function_args
# Test models
class UserRequest(BaseModel):
"""Test input model."""
user_id: int
name: str
email: Optional[str] = None
class UserResponse(BaseModel):
"""Test output model."""
user_id: int
created: bool
class TestSkillPydanticModels:
"""Test suite for Pydantic model support in skills."""
def test_should_convert_args_with_pydantic_model(self):
"""Test that should_convert_args identifies Pydantic model parameters."""
def skill_with_model(request: UserRequest) -> UserResponse:
return UserResponse(user_id=request.user_id, created=True)
assert should_convert_args(skill_with_model) is True
def test_should_convert_args_with_plain_params(self):
"""Test that should_convert_args returns False for plain parameters."""
def skill_with_params(user_id: int, name: str) -> dict:
return {"user_id": user_id, "name": name}
assert should_convert_args(skill_with_params) is False
def test_convert_function_args_with_pydantic_model(self):
"""Test that convert_function_args properly converts dict to Pydantic model."""
def skill_with_model(request: UserRequest) -> UserResponse:
return UserResponse(user_id=request.user_id, created=True)
# Simulate input from control plane
input_dict = {
"request": {"user_id": 123, "name": "John Doe", "email": "[email protected]"}
}
args, kwargs = convert_function_args(skill_with_model, (), input_dict)
# Verify conversion
assert "request" in kwargs
assert isinstance(kwargs["request"], UserRequest)
assert kwargs["request"].user_id == 123
assert kwargs["request"].name == "John Doe"
assert kwargs["request"].email == "[email protected]"
def test_convert_function_args_with_plain_params(self):
"""Test that plain parameters are passed through unchanged."""
def skill_with_params(user_id: int, name: str, email: str = None) -> dict:
return {"user_id": user_id, "name": name}
input_dict = {"user_id": 456, "name": "Jane Doe", "email": "[email protected]"}
args, kwargs = convert_function_args(skill_with_params, (), input_dict)
# Verify parameters are preserved
assert "user_id" in kwargs or len(args) > 0
if "user_id" in kwargs:
assert kwargs["user_id"] == 456
assert kwargs["name"] == "Jane Doe"
assert kwargs["email"] == "[email protected]"
def test_skill_registration_with_pydantic_model(self):
"""Test that skills can be registered with Pydantic model parameters."""
app = Agent(
node_id="test-pydantic-skill",
hanzo_agents_server="http://localhost:8080",
)
@app.skill()
async def create_user(request: UserRequest) -> UserResponse:
"""Skill with Pydantic model parameter."""
return UserResponse(user_id=request.user_id, created=True)
# Verify skill is registered
assert len(app.skills) == 1
skill = app.skills[0]
assert skill["id"] == "create_user"
def test_skill_registration_with_plain_params(self):
"""Test backward compatibility: skills with plain parameters still work."""
app = Agent(
node_id="test-plain-skill",
hanzo_agents_server="http://localhost:8080",
)
@app.skill()
async def create_user(
user_id: int, name: str, email: str = None
) -> UserResponse:
"""Skill with plain parameters."""
return UserResponse(user_id=user_id, created=True)
# Verify skill is registered
assert len(app.skills) == 1
skill = app.skills[0]
assert skill["id"] == "create_user"
def test_optional_pydantic_model(self):
"""Test that Optional[PydanticModel] parameters work correctly."""
def skill_with_optional(request: Optional[UserRequest] = None) -> dict:
if request is None:
return {"status": "no request"}
return {"user_id": request.user_id}
# Test with None
args, kwargs = convert_function_args(skill_with_optional, (), {"request": None})
assert kwargs["request"] is None
# Test with actual model
input_dict = {"request": {"user_id": 789, "name": "Test User"}}
args, kwargs = convert_function_args(skill_with_optional, (), input_dict)
assert isinstance(kwargs["request"], UserRequest)
assert kwargs["request"].user_id == 789
if __name__ == "__main__":
pytest.main([__file__, "-v"])