{"id":"fa28d66c-4e02-4670-b17d-3af066d81749","shortId":"BMq8Wm","kind":"skill","title":"pydantic","tagline":"Auto-activate for pydantic imports, BaseModel, BaseSettings, pydantic_settings. Pydantic v2 data validation and settings management: field validators, model validators, serialization, TypeAdapter, BaseSettings env config. Produces validated Pydantic models, settings classes, cust","description":"# Pydantic Skill\n\nPydantic v2 is a high-performance Python data validation library with first-class support for type hints, environment configuration via `BaseSettings`, and a complete rewrite from v1 with significant API changes.\n\n## Code Style Rules\n\n- Use PEP 604 for unions: `T | None` (not `Optional[T]`)\n- Use `model_config = ConfigDict(...)` not inner `class Config`\n- Use `model_validate()` for untrusted external input (not `__init__`)\n- Use `Annotated[T, Field(...)]` over `Field(...)` as a default value\n\n## Quick Reference\n\n### ConfigDict\n\n```python\nfrom pydantic import BaseModel, ConfigDict\n\nclass MyModel(BaseModel):\n    model_config = ConfigDict(\n        from_attributes=True,       # replaces orm_mode=True (v1)\n        extra=\"forbid\",             # \"allow\", \"ignore\", or \"forbid\"\n        validate_assignment=True,   # re-validate on attribute set\n        arbitrary_types_allowed=True,\n        populate_by_name=True,      # allow field name or alias\n        str_strip_whitespace=True,\n        frozen=True,                # make model immutable\n    )\n```\n\n### Validators\n\n```python\nfrom pydantic import BaseModel, field_validator, model_validator, computed_field\n\nclass Order(BaseModel):\n    quantity: int\n    unit_price: float\n    discount: float = 0.0\n\n    @field_validator(\"quantity\")\n    @classmethod\n    def quantity_must_be_positive(cls, v: int) -> int:\n        if v <= 0:\n            raise ValueError(\"quantity must be > 0\")\n        return v\n\n    @field_validator(\"discount\")\n    @classmethod\n    def discount_in_range(cls, v: float) -> float:\n        if not (0.0 <= v <= 1.0):\n            raise ValueError(\"discount must be between 0 and 1\")\n        return v\n\n    @model_validator(mode=\"before\")\n    @classmethod\n    def check_raw_data(cls, data: dict) -> dict:\n        # runs before individual field validation\n        if \"unit_price\" in data and data[\"unit_price\"] < 0:\n            raise ValueError(\"unit_price cannot be negative\")\n        return data\n\n    @model_validator(mode=\"after\")\n    def check_total(self) -> \"Order\":\n        # runs after all fields are validated; self is fully populated\n        if self.quantity * self.unit_price > 1_000_000:\n            raise ValueError(\"order total exceeds limit\")\n        return self\n\n    @computed_field\n    @property\n    def total(self) -> float:\n        return self.quantity * self.unit_price * (1 - self.discount)\n```\n\n### Serialization\n\n```python\nmodel = Order(quantity=2, unit_price=9.99)\n\n# model_dump options\nmodel.model_dump()\nmodel.model_dump(by_alias=True)          # use field aliases in output\nmodel.model_dump(exclude_unset=True)     # omit fields not explicitly set\nmodel.model_dump(exclude_none=True)      # omit None-valued fields\nmodel.model_dump(include={\"quantity\"})   # only these fields\nmodel.model_dump(exclude={\"discount\"})   # all except these fields\nmodel.model_dump(mode=\"json\")            # JSON-serializable types\n\n# JSON string\nmodel.model_dump_json()\nmodel.model_dump_json(by_alias=True, exclude_none=True)\n\n# Custom field serializer\nfrom pydantic import field_serializer\n\nclass Item(BaseModel):\n    price: float\n\n    @field_serializer(\"price\")\n    def serialize_price(self, v: float) -> str:\n        return f\"${v:.2f}\"\n\n# Custom model serializer\nfrom pydantic import model_serializer\n\nclass Item(BaseModel):\n    name: str\n    price: float\n\n    @model_serializer\n    def custom_serialize(self) -> dict:\n        return {\"label\": self.name, \"cost\": self.price}\n```\n\n### TypeAdapter — Bulk Validation\n\n```python\nfrom pydantic import TypeAdapter\n\n# Significantly faster than calling MyModel(...) in a loop\nadapter = TypeAdapter(list[MyModel])\nitems = adapter.validate_python(raw_list)          # from Python objects\nitems = adapter.validate_json(json_string)         # from JSON bytes/str\n\n# Also works for non-model types\nint_adapter = TypeAdapter(int)\nint_adapter.validate_python(\"42\")  # returns 42\n```\n\n### Custom Types — Annotated Pattern\n\n```python\nfrom typing import Annotated\nfrom pydantic import BeforeValidator, PlainSerializer, WithJsonSchema\nfrom pydantic.functional_validators import AfterValidator\n\ndef parse_comma_list(v: str | list) -> list[str]:\n    if isinstance(v, str):\n        return [item.strip() for item in v.split(\",\")]\n    return v\n\ndef validate_positive(v: int) -> int:\n    assert v > 0, \"must be positive\"\n    return v\n\nCommaList = Annotated[\n    list[str],\n    BeforeValidator(parse_comma_list),\n    WithJsonSchema({\"type\": \"string\", \"description\": \"Comma-separated values\"}),\n]\n\nPositiveInt = Annotated[int, AfterValidator(validate_positive)]\n\nTagList = Annotated[\n    list[str],\n    BeforeValidator(parse_comma_list),\n    PlainSerializer(lambda v: \",\".join(v), return_type=str),\n]\n```\n\n### BaseSettings — Environment Configuration\n\n```python\nfrom pydantic_settings import BaseSettings, SettingsConfigDict\n\nclass AppSettings(BaseSettings):\n    model_config = SettingsConfigDict(\n        env_file=\".env\",\n        env_file_encoding=\"utf-8\",\n        env_nested_delimiter=\"__\",   # DATABASE__HOST → database.host\n        case_sensitive=False,\n        extra=\"ignore\",\n    )\n\n    debug: bool = False\n    secret_key: str\n    allowed_hosts: list[str] = [\"localhost\"]\n\nsettings = AppSettings()   # reads from env + .env file\n```\n\nPriority chain: **explicit args > env vars > .env file > defaults**\n\nSee [BaseSettings Deep Reference](references/basesettings.md) for nested models, secrets directory, multiple env files, and custom sources.\n\n### PrivateAttr — Non-Validated Internal State\n\n```python\nfrom pydantic import BaseModel, PrivateAttr\n\nclass Connection(BaseModel):\n    host: str\n    port: int = 5432\n    _client: object = PrivateAttr(default=None)\n\n    def connect(self) -> None:\n        self._client = create_client(self.host, self.port)\n```\n\n### Constrained Types via Field\n\n```python\nfrom pydantic import BaseModel, Field\n\nclass Product(BaseModel):\n    name: str = Field(min_length=1, max_length=100)\n    price: float = Field(gt=0, le=999_999.99)\n    stock: int = Field(ge=0)\n    sku: str = Field(pattern=r\"^[A-Z]{3}-\\d{4}$\")\n    tags: list[str] = Field(min_length=0, max_length=10)\n```\n\n### Special Types\n\n```python\nfrom pydantic import EmailStr, SecretStr, AnyUrl, AnyHttpUrl\nfrom pydantic import PastDate, FutureDate, AwareDatetime, ByteSize\n\nclass UserProfile(BaseModel):\n    email: EmailStr              # validates email format\n    password: SecretStr          # hidden in repr/serialization\n    website: AnyHttpUrl | None = None\n    birth_date: PastDate | None = None\n    appointment: AwareDatetime | None = None  # timezone-aware datetime\n    avatar_size: ByteSize = \"5MB\"             # \"5MB\", \"1GiB\", etc.\n```\n\n### V1 → V2 Migration Quick Reference\n\n| V1 | V2 |\n|----|-----|\n| `class Config: orm_mode = True` | `model_config = ConfigDict(from_attributes=True)` |\n| `@root_validator` | `@model_validator(mode='before'/'after')` |\n| `@validator` | `@field_validator` |\n| `.dict()` | `.model_dump()` |\n| `.json()` | `.model_dump_json()` |\n| `.parse_obj(data)` | `.model_validate(data)` |\n| `.parse_raw(json_str)` | `.model_validate_json(json_str)` |\n| `__fields__` | `model_fields` |\n| `Field(alias=..., allow_population_by_field_name=True)` | `Field(alias=...) + ConfigDict(populate_by_name=True)` |\n\nSee [V1→V2 Migration Guide](references/migration-v1-v2.md) for full mapping, breaking changes, and coexistence patterns.\n\n### Performance\n\n```python\n# Prefer model_validate() for untrusted/external data — skips Python __init__ overhead\nobj = MyModel.model_validate(raw_dict)\n\n# TypeAdapter for batch operations — do NOT use list comprehension with __init__\nadapter = TypeAdapter(list[MyModel])\nitems = adapter.validate_python(raw_list)   # single validation pass\n\n# Selective model_dump — avoid serializing the whole model if you only need a few fields\nsubset = obj.model_dump(include={\"id\", \"name\"})\n```\n\n<workflow>\n\n## Workflow\n\n### Step 1: Define Models\n\nCreate `BaseModel` subclasses with type-annotated fields. Use `ConfigDict` at the top of each model to set behavior. Prefer `Annotated[T, Field(...)]` over `Field(...)` as default values for reusability.\n\n### Step 2: Add Validators\n\nAdd `@field_validator` for single-field rules. Use `@model_validator(mode='before')` to preprocess raw input dicts and `@model_validator(mode='after')` for cross-field invariants on the fully constructed model. Add `@computed_field` for derived read-only properties.\n\n### Step 3: Handle Serialization\n\nUse `model_dump(exclude_unset=True)` when patching. Use `by_alias=True` when the API consumer expects camelCase or snake_case aliases. Use `@field_serializer` or `@model_serializer` for custom output formats.\n\n### Step 4: Configure Settings\n\nCreate a `BaseSettings` subclass in `pydantic_settings` for environment-driven config. Set `env_nested_delimiter=\"__\"` to support nested models from flat env vars. Load once at startup and inject as a dependency.\n\n### Step 5: Validate\n\nRun `mypy` or `pyright` with the pydantic plugin. Use `TypeAdapter` when validating collections for performance. Run tests to confirm validator error messages are user-friendly.\n\n</workflow>\n\n<guardrails>\n\n## Guardrails\n\n- **Use `ConfigDict` not inner `class Config`** -- `class Config` is the V1 pattern and silently ignored in some V2 contexts.\n- **Use `model_validate()` for untrusted input** -- it is faster and safer than calling `__init__` directly; triggers full validation pipeline.\n- **Use `BaseSettings` for environment configuration** -- never read `os.environ` manually in application code; BaseSettings handles type coercion, defaults, and `.env` loading.\n- **Use `TypeAdapter` for bulk operations** -- never use a list comprehension calling `MyModel(...)` or `MyModel.model_validate(...)` in a loop; a single `TypeAdapter(list[MyModel]).validate_python(data)` is significantly faster.\n- **Never mix V1 and V2 patterns in the same model** -- mixing `@validator` (V1) with `@field_validator` (V2) in the same class causes silent misbehavior or errors.\n- **Use `Annotated[T, Field(...)]` over `Field(...)` as a default value** -- the `Annotated` pattern allows reuse as a type alias and avoids mutable default pitfalls.\n- **Use `SecretStr` for passwords and tokens** -- prevents accidental leakage in logs, repr, and serialization.\n- **Avoid `model_dump(mode='json')` in hot paths** -- use `model_dump_json()` directly when you need a JSON string; it skips the intermediate dict.\n\n</guardrails>\n\n<validation>\n\n### Validation Checkpoint\n\nBefore delivering Pydantic code, verify:\n\n- [ ] `model_config = ConfigDict(...)` used (not inner `class Config`)\n- [ ] `model_validate()` used for external/untrusted data (not bare `__init__`)\n- [ ] `TypeAdapter` used for bulk list/collection validation\n- [ ] No V1 patterns (`@validator`, `@root_validator`, `.dict()`, `.json()`) in new code\n- [ ] `BaseSettings` used for environment configuration, not `os.environ`\n- [ ] Passwords/tokens use `SecretStr`\n- [ ] `Annotated[T, Field(...)]` pattern used for constrained fields\n- [ ] `@computed_field` used for derived properties (not plain `@property`)\n\n</validation>\n\n<example>\n\n## Example\n\n**Task:** User registration model with validation + app settings loaded from environment.\n\n```python\nfrom __future__ import annotations  # NOT used — pydantic needs runtime type eval\n\nfrom typing import Annotated\nfrom pydantic import (\n    BaseModel,\n    ConfigDict,\n    EmailStr,\n    Field,\n    SecretStr,\n    computed_field,\n    field_validator,\n    model_validator,\n)\nfrom pydantic_settings import BaseSettings, SettingsConfigDict\n\n\n# --- Reusable constrained type aliases ---\nUsername = Annotated[str, Field(min_length=3, max_length=32, pattern=r\"^\\w+$\")]\nPassword = Annotated[SecretStr, Field(min_length=8)]\n\n\n# --- Domain model ---\nclass UserRegistration(BaseModel):\n    model_config = ConfigDict(str_strip_whitespace=True)\n\n    username: Username\n    email: EmailStr\n    password: Password\n    confirm_password: Password\n\n    @field_validator(\"username\")\n    @classmethod\n    def username_not_reserved(cls, v: str) -> str:\n        reserved = {\"admin\", \"root\", \"system\"}\n        if v.lower() in reserved:\n            raise ValueError(f\"'{v}' is a reserved username\")\n        return v\n\n    @model_validator(mode=\"after\")\n    def passwords_match(self) -> \"UserRegistration\":\n        if self.password != self.confirm_password:\n            raise ValueError(\"passwords do not match\")\n        return self\n\n    @computed_field\n    @property\n    def display_name(self) -> str:\n        return self.username.capitalize()\n\n\n# --- Settings from environment ---\nclass DatabaseSettings(BaseModel):\n    host: str = \"localhost\"\n    port: int = 5432\n    name: str = \"app\"\n    user: str = \"postgres\"\n    password: SecretStr = SecretStr(\"postgres\")\n\n    @computed_field\n    @property\n    def url(self) -> str:\n        pwd = self.password.get_secret_value()\n        return f\"postgresql+asyncpg://{self.user}:{pwd}@{self.host}:{self.port}/{self.name}\"\n\n\nclass AppSettings(BaseSettings):\n    model_config = SettingsConfigDict(\n        env_file=\".env\",\n        env_nested_delimiter=\"__\",\n        extra=\"ignore\",\n    )\n\n    debug: bool = False\n    secret_key: SecretStr\n    database: DatabaseSettings = DatabaseSettings()\n    allowed_hosts: list[str] = [\"localhost\"]\n\n\n# --- Usage ---\n# Validate untrusted input\nregistration = UserRegistration.model_validate({\n    \"username\": \"alice\",\n    \"email\": \"alice@example.com\",\n    \"password\": \"s3cure!pw\",\n    \"confirm_password\": \"s3cure!pw\",\n})\n\n# Load settings once at startup\n# DATABASE__HOST=db.prod DATABASE__PORT=5433 SECRET_KEY=xyz python app.py\nsettings = AppSettings()\ndb_url = settings.database.url\n```\n\n</example>\n\n---\n\n## References Index\n\nFor detailed guides and configuration examples, refer to the following documents in `references/`:\n\n- **[BaseSettings Deep Reference](references/basesettings.md)** -- SettingsConfigDict options, nested models, secrets directory, multiple env files, custom sources, and full working example.\n- **[V1→V2 Migration Guide](references/migration-v1-v2.md)** -- Full API mapping table, breaking changes, gotchas, and coexistence patterns during incremental migration.\n\n---\n\n## Official References\n\n- <https://docs.pydantic.dev/latest/>\n- <https://docs.pydantic.dev/latest/concepts/models/>\n- <https://docs.pydantic.dev/latest/concepts/validators/>\n- <https://docs.pydantic.dev/latest/concepts/serialization/>\n- <https://docs.pydantic.dev/latest/concepts/pydantic_settings/>\n- <https://docs.pydantic.dev/latest/migration/>\n- <https://github.com/pydantic/pydantic>\n- <https://github.com/pydantic/pydantic-settings>\n\n## Shared Styleguide Baseline\n\n- Use shared styleguides for generic language/framework rules to reduce duplication in this skill.\n- [General Principles](https://github.com/cofin/flow/blob/main/templates/styleguides/general.md)\n- [Python](https://github.com/cofin/flow/blob/main/templates/styleguides/languages/python.md)\n- Keep this skill focused on tool-specific workflows, edge cases, and integration details.","tags":["pydantic","flow","cofin","agent-skills","ai-agents","beads","claude-code","codex","cursor","developer-tools","gemini-cli","opencode"],"capabilities":["skill","source-cofin","skill-pydantic","topic-agent-skills","topic-ai-agents","topic-beads","topic-claude-code","topic-codex","topic-cursor","topic-developer-tools","topic-gemini-cli","topic-opencode","topic-plugin","topic-slash-commands","topic-spec-driven-development"],"categories":["flow"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/cofin/flow/pydantic","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add cofin/flow","source_repo":"https://github.com/cofin/flow","install_from":"skills.sh"}},"qualityScore":"0.455","qualityRationale":"deterministic score 0.46 from registry signals: · indexed on github topic:agent-skills · 11 github stars · SKILL.md body (14,993 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-04-24T07:03:19.315Z","embedding":null,"createdAt":"2026-04-23T13:04:00.907Z","updatedAt":"2026-04-24T07:03:19.315Z","lastSeenAt":"2026-04-24T07:03:19.315Z","tsv":"'-8':632 '/cofin/flow/blob/main/templates/styleguides/general.md)':1761 '/cofin/flow/blob/main/templates/styleguides/languages/python.md)':1765 '/latest/':1719 '/latest/concepts/models/':1722 '/latest/concepts/pydantic_settings/':1731 '/latest/concepts/serialization/':1728 '/latest/concepts/validators/':1725 '/latest/migration/':1734 '/pydantic/pydantic':1737 '/pydantic/pydantic-settings':1740 '0':208,214,240,272,565,747,755,773 '0.0':192,231 '000':306,307 '1':242,305,327,739,976 '1.0':233 '10':776 '100':742 '1gib':829 '2':334,1010 '2f':436 '3':764,1056,1459 '32':1462 '4':766,1092 '42':513,515 '5':1129 '5432':706,1566 '5433':1652 '5mb':827,828 '604':75 '8':1472 '9.99':337 '999':749 '999.99':750 'a-z':761 'accident':1302 'activ':4 'adapt':480,508,941 'adapter.validate':485,493,946 'add':1011,1013,1046 'admin':1507 'aftervalid':535,590 'alia':160,346,405,885,893,1069,1289 'alias':350,1080,1452 'alic':1632 'alice@example.com':1634 'allow':135,150,156,650,886,1284,1619 'also':500 'annot':101,518,524,572,588,594,985,999,1272,1282,1384,1417,1428,1454,1467 'anyhttpurl':786,808 'anyurl':785 'api':68,1073,1703 'app':1408,1569 'app.py':1657 'applic':1206 'appoint':816 'appset':620,656,1597,1659 'arbitrari':148 'arg':665 'assert':563 'assign':140 'attribut':126,146,847 'auto':3 'auto-activ':2 'avatar':824 'avoid':956,1291,1309 'awar':822 'awaredatetim':792,817 'bare':1355 'baselin':1743 'basemodel':8,117,121,175,184,420,447,697,701,729,733,796,980,1432,1477,1560 'baseset':9,25,59,609,617,621,672,1097,1197,1208,1374,1447,1598,1678 'batch':932 'beforevalid':528,575,597 'behavior':997 'birth':811 'bool':645,1611 'break':908,1706 'bulk':465,1219,1360 'bytes':793,826 'bytes/str':499 'call':475,1189,1226 'camelcas':1076 'cannot':277 'case':639,1079,1776 'caus':1266 'chain':663 'chang':69,909,1707 'check':251,287 'checkpoint':1334 'class':33,51,89,119,182,418,445,619,699,731,794,838,1162,1164,1265,1346,1475,1558,1596 'classmethod':196,220,249,1497 'client':707,718 'cls':202,225,254,1502 'code':70,1207,1338,1373 'coercion':1211 'coexist':911,1710 'collect':1143 'comma':538,577,584,599 'comma-separ':583 'commalist':571 'complet':62 'comprehens':938,1225 'comput':180,316,1047,1392,1437,1545,1577 'config':27,85,90,123,623,839,844,1106,1163,1165,1341,1347,1479,1600 'configdict':86,112,118,124,845,894,988,1159,1342,1433,1480 'configur':57,611,1093,1200,1378,1669 'confirm':1149,1491,1638 'connect':700,713 'constrain':721,1390,1450 'construct':1044 'consum':1074 'context':1176 'cost':462 'creat':717,979,1095 'cross':1038 'cross-field':1037 'cust':34 'custom':410,437,455,516,685,1088,1691 'd':765 'data':14,45,253,255,267,269,281,868,871,920,1241,1353 'databas':636,1616,1647,1650 'database.host':638 'databaseset':1559,1617,1618 'date':812 'datetim':823 'db':1660 'db.prod':1649 'debug':644,1610 'deep':673,1679 'def':197,221,250,286,319,426,454,536,557,712,1498,1528,1548,1580 'default':108,670,710,1005,1212,1279,1293 'defin':977 'delimit':635,1110,1607 'deliv':1336 'depend':1127 'deriv':1050,1396 'descript':582 'detail':1666,1779 'dict':256,257,458,859,929,1030,1332,1369 'direct':1191,1321 'directori':680,1687 'discount':190,219,222,236,383 'display':1549 'docs.pydantic.dev':1718,1721,1724,1727,1730,1733 'docs.pydantic.dev/latest/':1717 'docs.pydantic.dev/latest/concepts/models/':1720 'docs.pydantic.dev/latest/concepts/pydantic_settings/':1729 'docs.pydantic.dev/latest/concepts/serialization/':1726 'docs.pydantic.dev/latest/concepts/validators/':1723 'docs.pydantic.dev/latest/migration/':1732 'document':1675 'domain':1473 'driven':1105 'dump':339,342,344,354,364,374,381,389,399,402,861,864,955,970,1061,1311,1319 'duplic':1753 'edg':1775 'email':797,800,1487,1633 'emailstr':783,798,1434,1488 'encod':630 'env':26,625,627,628,633,659,660,666,668,682,1108,1117,1214,1602,1604,1605,1689 'environ':56,610,1104,1199,1377,1412,1557 'environment-driven':1103 'error':1151,1270 'etc':830 'eval':1424 'exampl':1401,1670,1696 'exceed':312 'except':385 'exclud':355,365,382,407,1062 'expect':1075 'explicit':361,664 'extern':96 'external/untrusted':1352 'extra':133,642,1608 'f':434,1516,1589 'fals':641,646,1612 'faster':473,1185,1244 'field':19,103,105,157,176,181,193,217,261,294,317,349,359,372,379,387,411,416,423,724,730,736,745,753,758,770,857,881,883,884,889,892,967,986,1001,1003,1014,1019,1039,1048,1082,1259,1274,1276,1386,1391,1393,1435,1438,1439,1456,1469,1494,1546,1578 'file':626,629,661,669,683,1603,1690 'first':50 'first-class':49 'flat':1116 'float':189,191,227,228,322,422,431,451,744 'focus':1769 'follow':1674 'forbid':134,138 'format':801,1090 'friend':1156 'frozen':165 'full':906,1193,1694,1702 'fulli':299,1043 'futur':1415 'futured':791 'ge':754 'general':1757 'generic':1748 'github.com':1736,1739,1760,1764 'github.com/cofin/flow/blob/main/templates/styleguides/general.md)':1759 'github.com/cofin/flow/blob/main/templates/styleguides/languages/python.md)':1763 'github.com/pydantic/pydantic':1735 'github.com/pydantic/pydantic-settings':1738 'gotcha':1708 'gt':746 'guardrail':1157 'guid':903,1667,1700 'handl':1057,1209 'hidden':804 'high':42 'high-perform':41 'hint':55 'host':637,651,702,1561,1620,1648 'hot':1315 'id':972 'ignor':136,643,1172,1609 'immut':169 'import':7,116,174,415,442,470,523,527,534,616,696,728,782,789,1416,1427,1431,1446 'includ':375,971 'increment':1713 'index':1664 'individu':260 'init':99,923,940,1190,1356 'inject':1124 'inner':88,1161,1345 'input':97,1029,1182,1627 'int':186,204,205,507,510,561,562,589,705,752,1565 'int_adapter.validate':511 'integr':1778 'intermedi':1331 'intern':691 'invari':1040 'isinst':546 'item':419,446,484,492,552,945 'item.strip':550 'join':604 'json':391,393,396,400,403,494,495,498,862,865,874,878,879,1313,1320,1326,1370 'json-serializ':392 'keep':1766 'key':648,1614,1654 'label':460 'lambda':602 'language/framework':1749 'le':748 'leakag':1303 'length':738,741,772,775,1458,1461,1471 'librari':47 'limit':313 'list':482,488,539,542,543,573,578,595,600,652,768,937,943,949,1224,1237,1621 'list/collection':1361 'load':1119,1215,1410,1642 'localhost':654,1563,1623 'log':1305 'loop':479,1233 'make':167 'manag':18 'manual':1204 'map':907,1704 'match':1530,1542 'max':740,774,1460 'messag':1152 'migrat':833,902,1699,1714 'min':737,771,1457,1470 'misbehavior':1268 'mix':1246,1255 'mode':130,247,284,390,841,853,1024,1034,1312,1526 'model':21,31,84,92,122,168,178,245,282,331,338,438,443,452,505,622,678,843,851,860,863,869,876,882,916,954,960,978,994,1022,1032,1045,1060,1085,1114,1178,1254,1310,1318,1340,1348,1405,1441,1474,1478,1524,1599,1685 'model.model':341,343,353,363,373,380,388,398,401 'multipl':681,1688 'must':199,212,237,566 'mutabl':1292 'mymodel':120,476,483,944,1227,1238 'mymodel.model':926,1229 'mypi':1132 'name':154,158,448,734,890,897,973,1550,1567 'need':964,1324,1421 'negat':279 'nest':634,677,1109,1113,1606,1684 'never':1201,1221,1245 'new':1372 'non':504,689 'non-model':503 'non-valid':688 'none':79,366,370,408,711,715,809,810,814,815,818,819 'none-valu':369 'obj':867,925 'obj.model':969 'object':491,708 'offici':1715 'omit':358,368 'oper':933,1220 'option':81,340,1683 'order':183,290,310,332 'orm':129,840 'os.environ':1203,1380 'output':352,1089 'overhead':924 'pars':537,576,598,866,872 'pass':952 'password':802,1298,1466,1489,1490,1492,1493,1529,1536,1539,1573,1635,1639 'passwords/tokens':1381 'pastdat':790,813 'patch':1066 'path':1316 'pattern':519,759,912,1169,1250,1283,1365,1387,1463,1711 'pep':74 'perform':43,913,1145 'pipelin':1195 'pitfal':1294 'plain':1399 'plainseri':529,601 'plugin':1138 'popul':152,300,887,895 'port':704,1564,1651 'posit':201,559,568,592 'positiveint':587 'postgr':1572,1576 'postgresql':1590 'prefer':915,998 'preprocess':1027 'prevent':1301 'price':188,265,271,276,304,326,336,421,425,428,450,743 'principl':1758 'prioriti':662 'privateattr':687,698,709 'produc':28 'product':732 'properti':318,1054,1397,1400,1547,1579 'pw':1637,1641 'pwd':1584,1592 'pydant':1,6,10,12,30,35,37,115,173,414,441,469,526,614,695,727,781,788,1100,1137,1337,1420,1430,1444 'pydantic.functional':532 'pyright':1134 'python':44,113,171,330,467,486,490,512,520,612,693,725,779,914,922,947,1240,1413,1656,1762 'quantiti':185,195,198,211,333,376 'quick':110,834 'r':760,1464 'rais':209,234,273,308,1514,1537 'rang':224 'raw':252,487,873,928,948,1028 're':143 're-valid':142 'read':657,1052,1202 'read-on':1051 'reduc':1752 'refer':111,674,835,1663,1671,1677,1680,1716 'references/basesettings.md':675,1681 'references/migration-v1-v2.md':904,1701 'registr':1404,1628 'replac':128 'repr':1306 'repr/serialization':806 'reserv':1501,1506,1513,1520 'return':215,243,280,314,323,433,459,514,549,555,569,606,1522,1543,1553,1588 'reus':1285 'reusabl':1008,1449 'rewrit':63 'root':849,1367,1508 'rule':72,1020,1750 'run':258,291,1131,1146 'runtim':1422 's3cure':1636,1640 'safer':1187 'secret':647,679,1586,1613,1653,1686 'secretstr':784,803,1296,1383,1436,1468,1574,1575,1615 'see':671,899 'select':953 'self':289,297,315,321,429,457,714,1531,1544,1551,1582 'self._client':716 'self.confirm':1535 'self.discount':328 'self.host':719,1593 'self.name':461,1595 'self.password':1534 'self.password.get':1585 'self.port':720,1594 'self.price':463 'self.quantity':302,324 'self.unit':303,325 'self.user':1591 'self.username.capitalize':1554 'sensit':640 'separ':585 'serial':23,329,412,417,424,427,439,444,453,456,957,1058,1083,1086,1308 'serializ':394 'set':11,17,32,147,362,615,655,996,1094,1101,1107,1409,1445,1555,1643,1658 'settings.database.url':1662 'settingsconfigdict':618,624,1448,1601,1682 'share':1741,1745 'signific':67,472,1243 'silent':1171,1267 'singl':950,1018,1235 'single-field':1017 'size':825 'skill':36,1756,1768 'skill-pydantic' 'skip':921,1329 'sku':756 'snake':1078 'sourc':686,1692 'source-cofin' 'special':777 'specif':1773 'startup':1122,1646 'state':692 'step':975,1009,1055,1091,1128 'stock':751 'str':161,432,449,541,544,548,574,596,608,649,653,703,735,757,769,875,880,1455,1481,1504,1505,1552,1562,1568,1571,1583,1622 'string':397,496,581,1327 'strip':162,1482 'style':71 'styleguid':1742,1746 'subclass':981,1098 'subset':968 'support':52,1112 'system':1509 'tabl':1705 'tag':767 'taglist':593 'task':1402 'test':1147 'timezon':821 'timezone-awar':820 'token':1300 'tool':1772 'tool-specif':1771 'top':991 'topic-agent-skills' 'topic-ai-agents' 'topic-beads' 'topic-claude-code' 'topic-codex' 'topic-cursor' 'topic-developer-tools' 'topic-gemini-cli' 'topic-opencode' 'topic-plugin' 'topic-slash-commands' 'topic-spec-driven-development' 'total':288,311,320 'trigger':1192 'true':127,131,141,151,155,164,166,347,357,367,406,409,842,848,891,898,1064,1070,1484 'type':54,149,395,506,517,522,580,607,722,778,984,1210,1288,1423,1426,1451 'type-annot':983 'typeadapt':24,464,471,481,509,930,942,1140,1217,1236,1357 'union':77 'unit':187,264,270,275,335 'unset':356,1063 'untrust':95,1181,1626 'untrusted/external':919 'url':1581,1661 'usag':1624 'use':73,83,91,100,348,936,987,1021,1059,1067,1081,1139,1158,1177,1196,1216,1222,1271,1295,1317,1343,1350,1358,1375,1382,1388,1394,1419,1744 'user':1155,1403,1570 'user-friend':1154 'usernam':1453,1485,1486,1496,1499,1521,1631 'userprofil':795 'userregistr':1476,1532 'userregistration.model':1629 'utf':631 'v':203,207,216,226,232,244,430,435,540,547,556,560,564,570,603,605,1503,1517,1523 'v.lower':1511 'v.split':554 'v1':65,132,831,836,900,1168,1247,1257,1364,1697 'v2':13,38,832,837,901,1175,1249,1261,1698 'valid':15,20,22,29,46,93,139,144,170,177,179,194,218,246,262,283,296,466,533,558,591,690,799,850,852,856,858,870,877,917,927,951,1012,1015,1023,1033,1130,1142,1150,1179,1194,1230,1239,1256,1260,1333,1349,1362,1366,1368,1407,1440,1442,1495,1525,1625,1630 'valu':109,371,586,1006,1280,1587 'valueerror':210,235,274,309,1515,1538 'var':667,1118 'verifi':1339 'via':58,723 'w':1465 'websit':807 'whitespac':163,1483 'whole':959 'withjsonschema':530,579 'work':501,1695 'workflow':974,1774 'xyz':1655 'z':763","prices":[{"id":"93714398-ca1e-4dd7-9a70-54a14c8f63e7","listingId":"fa28d66c-4e02-4670-b17d-3af066d81749","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"cofin","category":"flow","install_from":"skills.sh"},"createdAt":"2026-04-23T13:04:00.907Z"}],"sources":[{"listingId":"fa28d66c-4e02-4670-b17d-3af066d81749","source":"github","sourceId":"cofin/flow/pydantic","sourceUrl":"https://github.com/cofin/flow/tree/main/skills/pydantic","isPrimary":false,"firstSeenAt":"2026-04-23T13:04:00.907Z","lastSeenAt":"2026-04-24T07:03:19.315Z"}],"details":{"listingId":"fa28d66c-4e02-4670-b17d-3af066d81749","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"cofin","slug":"pydantic","github":{"repo":"cofin/flow","stars":11,"topics":["agent-skills","ai-agents","beads","claude-code","codex","context-driven-development","cursor","developer-tools","gemini-cli","opencode","plugin","slash-commands","spec-driven-development","subagents","tdd","workflow"],"license":"apache-2.0","html_url":"https://github.com/cofin/flow","pushed_at":"2026-04-19T23:22:27Z","description":"Context-Driven Development toolkit for AI agents — spec-first planning, TDD workflow, and Beads integration.","skill_md_sha":"26a9784d483f02e386b1397a010520fbd113f567","skill_md_path":"skills/pydantic/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/cofin/flow/tree/main/skills/pydantic"},"layout":"multi","source":"github","category":"flow","frontmatter":{"name":"pydantic","description":"Auto-activate for pydantic imports, BaseModel, BaseSettings, pydantic_settings. Pydantic v2 data validation and settings management: field validators, model validators, serialization, TypeAdapter, BaseSettings env config. Produces validated Pydantic models, settings classes, custom types, and migration-safe patterns. Use when: defining data models with validation, managing environment configuration, validating external data, or migrating from Pydantic v1 to v2. Not for msgspec Structs or dataclasses -- Pydantic has its own patterns."},"skills_sh_url":"https://skills.sh/cofin/flow/pydantic"},"updatedAt":"2026-04-24T07:03:19.315Z"}}