fernandofuc/nextjs-c-s

agent-builder-pydantic-ai

Build conversational AI agents using Pydantic AI + OpenRouter. Use when creating type-safe Python agents with tool calling, validation, and streaming.

First seen Jan 24, 2026

Installation

$ npx skills add fernandofuc/nextjs-c-s --skill agent-builder-pydantic-ai

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from fernandofuc/nextjs-c-s.

npx skills add fernandofuc/nextjs-c-s

Browse all from fernandofuc/nextjs-c-s

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

License MIT
Default branch main
Open issues 0
Status Active

Skill metadata

Parsed from SKILL.md frontmatter.

LicenseMIT

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 5,740 B
  • docs SUMMARY.md 183 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 12 installs

SKILL.md

Pydantic AI Agent Builder

Purpose

Create production-ready AI agents with type safety, automatic validation, and minimal boilerplate using Pydantic AI framework.

When to Use

  • Building FastAPI backend with AI capabilities
  • Need strict type checking and validation
  • Want auto-retry on malformed LLM responses
  • Creating agents with custom tools

Architecture Pattern

Project Structure

backend/
├── agents/
│   ├── __init__.py
│   ├── base_agent.py          # Base agent class
│   └── [feature]_agent.py     # Feature-specific agents
├── tools/
│   ├── __init__.py
│   └── [tool_name].py         # Tool definitions
└── config/
    └── agent_config.py        # Agent configurations

Installation

pip install pydantic-ai httpx pydantic python-dotenv

Base Agent Pattern

from pydantic_ai import Agent
from pydantic import BaseModel
import os

class AgentResponse(BaseModel):
    result: str
    confidence: float

agent = Agent(
    model='openrouter:openai/gpt-4o',
    output_type=AgentResponse,
    tools=[tool1, tool2],
    system_prompt="You are a helpful AI assistant."
)

# Usage
result = await agent.run("user message")

Integration with OpenRouter

Setup

import os
from pydantic_ai.models import OpenRouterModel

model = OpenRouterModel(
    name='openai/gpt-4o',
    api_key=os.getenv('OPENROUTER_API_KEY'),
    http_referer=os.getenv('FRONTEND_URL')
)

Environment Variables

OPENROUTER_API_KEY=sk-or-v1-...
FRONTEND_URL=http://localhost:3000

Tool Definition Pattern

from pydantic import BaseModel, Field
from pydantic_ai import Agent, Tool

class GenerateImageArgs(BaseModel):
    prompt: str = Field(description="Image description")
    num_images: int = Field(ge=1, le=10, default=1)

async def generate_image_tool(args: GenerateImageArgs) -> dict:
    # Your implementation
    return {"images": [...]}

# Register tool
agent.add_tool(
    Tool(
        name="generate_image",
        description="Generate images using AI",
        parameters=GenerateImageArgs,
        execute=generate_image_tool
    )
)

Streaming Pattern

async def stream_response(agent, message):
    async for chunk in agent.stream(message):
        yield {
            "type": "text" if isinstance(chunk, str) else "tool_call",
            "content": chunk
        }

Error Handling & Retry

from pydantic_ai import Agent, RetryConfig

agent = Agent(
    model='openrouter:openai/gpt-4o',
    retry_config=RetryConfig(
        max_retries=3,
        retry_on=[ValidationError, TimeoutError]
    )
)

# Auto-retry on validation errors
try:
    result = await agent.run("user message")
except ValidationError as e:
    # Will retry automatically
    logger.error(f"Validation failed after retries: {e}")

FastAPI Integration

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel

app = FastAPI()

class ChatRequest(BaseModel):
    message: str
    history: list = []

@app.post("/chat")
async def chat_endpoint(request: ChatRequest):
    try:
        result = await agent.run(
            request.message,
            context={"history": request.history}
        )
        return {"response": result.result}
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

Testing Pattern

import pytest
from pydantic_ai import Agent

@pytest.mark.asyncio
async def test_agent_response():
    agent = Agent(
        model='openrouter:openai/gpt-4o',
        system_prompt="You are a test assistant"
    )

    result = await agent.run("Say hello")
    assert "hello" in result.lower()

Best Practices

  1. Type Safety: Always define Pydantic models for inputs/outputs
  2. Dependency Injection: Use FastAPI-style DI for tools
  3. Auto-Retry: Configure retry logic for robustness
  4. Logging: Add structured logging for debugging
  5. Testing: Write pytest tests for agent behaviors
  6. Validation: Let Pydantic handle validation automatically
  7. Context: Pass context dict for stateful conversations

Example: Complete Agent

from pydantic_ai import Agent, Tool
from pydantic import BaseModel, Field
import os

# Output type
class ChatResponse(BaseModel):
    message: str
    tool_used: str | None = None
    confidence: float = Field(ge=0, le=1)

# Tool definition
class WeatherArgs(BaseModel):
    city: str

async def get_weather(args: WeatherArgs) -> dict:
    # Your API call here
    return {"temp": 72, "condition": "sunny"}

# Create agent
agent = Agent(
    model='openrouter:openai/gpt-4o',
    output_type=ChatResponse,
    system_prompt="You are a helpful weather assistant."
)

# Register tool
agent.add_tool(
    Tool(
        name="get_weather",
        description="Get current weather for a city",
        parameters=WeatherArgs,
        execute=get_weather
    )
)

# Usage
if __name__ == "__main__":
    result = await agent.run("What's the weather in SF?")
    print(result.message)

Common Pitfalls

Don't: Use any type ✅ Do: Define strict Pydantic models

Don't: Handle retries manually ✅ Do: Configure RetryConfig

Don't: Parse LLM output manually ✅ Do: Let Pydantic AI handle it

Resources