[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6ENYC534TV49VT224Q1VR56":3,"skill-same:01M6ENYC534TV49VT224Q1VR56":65},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":31,"linkOnly":32,"markdownContent":33,"markdownBody":34,"frontMatter":35,"refName":36,"commitSha":37,"skillDirectory":38,"forksCount":39,"repositoryHtmlUrl":40,"repositoryHomepageUrl":41,"ownerHtmlUrl":42,"ownerBlogUrl":6,"ownerDescription":43,"updatedAt":44,"install":45,"resources":58},"01M6ENYC534TV49VT224Q1VR56","py-sqlmodel-patterns",null,"SQLModel and async SQLAlchemy patterns. Use when working with database models, queries, relationships, or debugging ORM issues.","ComeOnOliver\u002Fskillshub","ComeOnOliver","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F43215937?v=4","01M6E5JNFECJAAVFE0W7SMWWD2","Haoran Shu","01M6E5JNNDQS7AJZDYFQ8TPZCK",67,"MIT","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Faiskillstore\u002Fmarketplace\u002Fcjharmath\u002Fpy-sqlmodel-patterns\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30],"patterns","py sqlmodel patterns","debugging","issues","database","orm","use","async","models","queries","relationships","sqlalchemy","2026-11-10 10:12:30",false,"---\nname: py-sqlmodel-patterns\ndescription: SQLModel and async SQLAlchemy patterns. Use when working with database models, queries, relationships, or debugging ORM issues.\n---\n\n# SQLModel Patterns\n\n## Problem Statement\n\nSQLModel combines Pydantic and SQLAlchemy, blurring the line between models and schemas. Async SQLAlchemy has different rules than sync. Mistakes here cause data corruption, N+1 queries, and hard-to-debug errors.\n\n---\n\n## Pattern: Eager Loading for Async\n\n**Problem:** Lazy loading doesn't work with async SQLAlchemy. Accessing relationships without eager loading raises errors.\n\n```python\n# ❌ WRONG: Lazy loading fails in async\nresult = await session.execute(select(User).where(User.id == user_id))\nuser = result.scalar_one()\nassessments = user.assessments  # ERROR: greenlet_spawn has not been called\n\n# ✅ CORRECT: selectinload for collections\nfrom sqlalchemy.orm import selectinload\n\nresult = await session.execute(\n    select(User)\n    .where(User.id == user_id)\n    .options(selectinload(User.assessments))\n)\nuser = result.scalar_one()\nassessments = user.assessments  # Works - already loaded\n\n# ✅ CORRECT: joinedload for single relationships\nfrom sqlalchemy.orm import joinedload\n\nresult = await session.execute(\n    select(Assessment)\n    .where(Assessment.id == assessment_id)\n    .options(joinedload(Assessment.user))\n)\nassessment = result.scalar_one()\nuser = assessment.user  # Works - already loaded\n```\n\n**When to use which:**\n\n| Relationship | Loading Strategy |\n|--------------|------------------|\n| One-to-many (collections) | `selectinload()` |\n| Many-to-one (single) | `joinedload()` |\n| Nested relationships | Chain: `.options(selectinload(A.b).selectinload(B.c))` |\n\n---\n\n## Pattern: N+1 Query Detection\n\n**Problem:** Fetching related objects one-by-one instead of in batch.\n\n```python\n# ❌ WRONG: N+1 queries\nusers = await session.execute(select(User))\nfor user in users.scalars():\n    # Each access triggers a query!\n    print(user.team.name)  # Query 1, 2, 3... N\n\n# ✅ CORRECT: Single query with eager loading\nusers = await session.execute(\n    select(User).options(joinedload(User.team))\n)\nfor user in users.scalars():\n    print(user.team.name)  # No additional queries\n\n# Detection: Enable SQL echo in development\nengine = create_async_engine(DATABASE_URL, echo=True)\n# Watch logs for repeated similar queries\n```\n\n---\n\n## Pattern: Model vs Schema Separation\n\n**Problem:** SQLModel blurs models (DB) and schemas (API). Need clear separation.\n\n```python\n# Database Model - represents table\nclass User(SQLModel, table=True):\n    id: UUID = Field(default_factory=uuid4, primary_key=True)\n    email: str = Field(index=True, unique=True)\n    hashed_password: str  # Never expose this\n    created_at: datetime = Field(default_factory=datetime.utcnow)\n    \n    # Relationships\n    assessments: list[\"Assessment\"] = Relationship(back_populates=\"user\")\n\n# API Schema - Create (input)\nclass UserCreate(SQLModel):\n    email: str\n    password: str  # Plain password, will be hashed\n\n# API Schema - Read (output)\nclass UserRead(SQLModel):\n    id: UUID\n    email: str\n    created_at: datetime\n    # Note: No password field!\n\n# API Schema - Update (partial)\nclass UserUpdate(SQLModel):\n    email: str | None = None\n    password: str | None = None\n```\n\n**Naming convention:**\n- `ModelName` - Database table model\n- `ModelNameCreate` - Input for creation\n- `ModelNameRead` - Output for reading\n- `ModelNameUpdate` - Input for partial updates\n\n---\n\n## Pattern: Session State Management\n\n**Problem:** Understanding `expire_on_commit` and when objects become stale.\n\n```python\n# This codebase setting\nasync_session = async_sessionmaker(\n    engine,\n    expire_on_commit=False,  # Objects stay valid after commit\n)\n\n# With expire_on_commit=False:\nuser = User(email=\"test@example.com\")\nsession.add(user)\nawait session.commit()\nprint(user.email)  # Works - object still valid\n\n# With expire_on_commit=True (default):\nawait session.commit()\nprint(user.email)  # Would need refresh() first\n\n# ✅ CORRECT: Refresh when you need DB-generated values\nawait session.commit()\nawait session.refresh(user)  # Get id, created_at, updated DB values\nreturn user\n```\n\n---\n\n## Pattern: UUID Handling\n\n**Problem:** Inconsistent UUID handling between Python and PostgreSQL.\n\n```python\nfrom uuid import UUID, uuid4\n\n# ✅ CORRECT: UUID with default factory\nclass Assessment(SQLModel, table=True):\n    id: UUID = Field(default_factory=uuid4, primary_key=True)\n    user_id: UUID = Field(foreign_key=\"user.id\")\n\n# ✅ CORRECT: UUID in queries\nawait session.execute(\n    select(Assessment).where(Assessment.id == UUID(\"...\"))\n)\n\n# ❌ WRONG: String comparison\nawait session.execute(\n    select(Assessment).where(Assessment.id == \"some-uuid-string\")\n)\n\n# ✅ CORRECT: Converting in API layer\n@router.get(\"\u002Fassessments\u002F{assessment_id}\")\nasync def get_assessment(assessment_id: UUID):  # FastAPI converts string to UUID\n    ...\n```\n\n---\n\n## Pattern: Nullable Fields\n\n**Problem:** SQLModel requires specific syntax for optional fields.\n\n```python\n# ✅ CORRECT: Optional field with None default\nclass Assessment(SQLModel, table=True):\n    id: UUID = Field(default_factory=uuid4, primary_key=True)\n    title: str  # Required\n    description: str | None = Field(default=None)  # Optional\n    completed_at: datetime | None = Field(default=None)  # Optional\n    \n    # Foreign key that's optional\n    coach_id: UUID | None = Field(default=None, foreign_key=\"user.id\")\n\n# ❌ WRONG: Optional without Field default\nclass BadModel(SQLModel, table=True):\n    description: str | None  # Missing default - causes issues\n```\n\n---\n\n## Pattern: Relationship Definitions\n\n```python\nfrom sqlmodel import Relationship\n\nclass User(SQLModel, table=True):\n    id: UUID = Field(default_factory=uuid4, primary_key=True)\n    \n    # One-to-many: User has many assessments\n    assessments: list[\"Assessment\"] = Relationship(back_populates=\"user\")\n    \n    # One-to-many: User has many answers\n    answers: list[\"UserAnswer\"] = Relationship(back_populates=\"user\")\n\nclass Assessment(SQLModel, table=True):\n    id: UUID = Field(default_factory=uuid4, primary_key=True)\n    user_id: UUID = Field(foreign_key=\"user.id\")\n    \n    # Many-to-one: Assessment belongs to user\n    user: User = Relationship(back_populates=\"assessments\")\n    \n    # One-to-many: Assessment has many questions\n    questions: list[\"Question\"] = Relationship(back_populates=\"assessment\")\n\nclass Question(SQLModel, table=True):\n    id: UUID = Field(default_factory=uuid4, primary_key=True)\n    assessment_id: UUID = Field(foreign_key=\"assessment.id\")\n    \n    # Many-to-one\n    assessment: Assessment = Relationship(back_populates=\"questions\")\n```\n\n---\n\n## Pattern: Query Patterns\n\n```python\n# Get one or None\nresult = await session.execute(\n    select(User).where(User.id == user_id)\n)\nuser = result.scalar_one_or_none()\n\n# Get one or raise\nuser = result.scalar_one()  # Raises if 0 or >1 results\n\n# Get list\nresult = await session.execute(\n    select(Assessment).where(Assessment.user_id == user_id)\n)\nassessments = result.scalars().all()\n\n# Get with pagination\nresult = await session.execute(\n    select(Assessment)\n    .where(Assessment.user_id == user_id)\n    .order_by(Assessment.created_at.desc())\n    .offset(skip)\n    .limit(limit)\n)\n\n# Count\nresult = await session.execute(\n    select(func.count()).select_from(Assessment).where(...)\n)\ncount = result.scalar_one()\n\n# Exists check\nresult = await session.execute(\n    select(exists().where(User.email == email))\n)\nemail_exists = result.scalar()\n```\n\n---\n\n## Pattern: Upsert (Insert or Update)\n\n```python\nfrom sqlalchemy.dialects.postgresql import insert\n\n# ✅ CORRECT: PostgreSQL upsert\nstmt = insert(UserAnswer).values(\n    user_id=user_id,\n    question_id=question_id,\n    value=value,\n)\nstmt = stmt.on_conflict_do_update(\n    index_elements=[\"user_id\", \"question_id\"],\n    set_={\"value\": value, \"updated_at\": datetime.utcnow()},\n)\nawait session.execute(stmt)\nawait session.commit()\n```\n\n---\n\n## References\n\n- SQLModel documentation: https:\u002F\u002Fsqlmodel.tiangolo.com\u002F\n- SQLAlchemy 2.0 documentation: https:\u002F\u002Fdocs.sqlalchemy.org\u002F\n\n---\n\n## Common Issues\n\n| Issue | Likely Cause | Solution |\n|-------|--------------|----------|\n| \"greenlet_spawn has not been called\" | Lazy loading in async | Use `selectinload`\u002F`joinedload` |\n| N+1 queries (slow) | Missing eager loading | Add appropriate loading strategy |\n| \"Object not bound to session\" | Using object after session closed | Keep operations within session scope |\n| Stale data | Missing `refresh()` | Call `refresh()` after commit |\n| \"None is not valid\" for UUID | Missing `default_factory` | Add `Field(default_factory=uuid4)` |\n\n---\n\n## Detection Commands\n\n```bash\n# Find lazy relationship access\ngrep -rn \"\\.scalars\\(\\)\" --include=\"*.py\" -A5 | grep -E \"\\.\\w+\\s*$\"\n\n# Find models missing relationship loading\ngrep -rn \"select(\" --include=\"*.py\" | grep -v \"options(\"\n\n# Check for N+1 in logs (with echo=True)\n# Look for repeated similar queries\n```\n","# SQLModel Patterns\n\n## Problem Statement\n\nSQLModel combines Pydantic and SQLAlchemy, blurring the line between models and schemas. Async SQLAlchemy has different rules than sync. Mistakes here cause data corruption, N+1 queries, and hard-to-debug errors.\n\n---\n\n## Pattern: Eager Loading for Async\n\n**Problem:** Lazy loading doesn't work with async SQLAlchemy. Accessing relationships without eager loading raises errors.\n\n```python\n# ❌ WRONG: Lazy loading fails in async\nresult = await session.execute(select(User).where(User.id == user_id))\nuser = result.scalar_one()\nassessments = user.assessments  # ERROR: greenlet_spawn has not been called\n\n# ✅ CORRECT: selectinload for collections\nfrom sqlalchemy.orm import selectinload\n\nresult = await session.execute(\n    select(User)\n    .where(User.id == user_id)\n    .options(selectinload(User.assessments))\n)\nuser = result.scalar_one()\nassessments = user.assessments  # Works - already loaded\n\n# ✅ CORRECT: joinedload for single relationships\nfrom sqlalchemy.orm import joinedload\n\nresult = await session.execute(\n    select(Assessment)\n    .where(Assessment.id == assessment_id)\n    .options(joinedload(Assessment.user))\n)\nassessment = result.scalar_one()\nuser = assessment.user  # Works - already loaded\n```\n\n**When to use which:**\n\n| Relationship | Loading Strategy |\n|--------------|------------------|\n| One-to-many (collections) | `selectinload()` |\n| Many-to-one (single) | `joinedload()` |\n| Nested relationships | Chain: `.options(selectinload(A.b).selectinload(B.c))` |\n\n---\n\n## Pattern: N+1 Query Detection\n\n**Problem:** Fetching related objects one-by-one instead of in batch.\n\n```python\n# ❌ WRONG: N+1 queries\nusers = await session.execute(select(User))\nfor user in users.scalars():\n    # Each access triggers a query!\n    print(user.team.name)  # Query 1, 2, 3... N\n\n# ✅ CORRECT: Single query with eager loading\nusers = await session.execute(\n    select(User).options(joinedload(User.team))\n)\nfor user in users.scalars():\n    print(user.team.name)  # No additional queries\n\n# Detection: Enable SQL echo in development\nengine = create_async_engine(DATABASE_URL, echo=True)\n# Watch logs for repeated similar queries\n```\n\n---\n\n## Pattern: Model vs Schema Separation\n\n**Problem:** SQLModel blurs models (DB) and schemas (API). Need clear separation.\n\n```python\n# Database Model - represents table\nclass User(SQLModel, table=True):\n    id: UUID = Field(default_factory=uuid4, primary_key=True)\n    email: str = Field(index=True, unique=True)\n    hashed_password: str  # Never expose this\n    created_at: datetime = Field(default_factory=datetime.utcnow)\n    \n    # Relationships\n    assessments: list[\"Assessment\"] = Relationship(back_populates=\"user\")\n\n# API Schema - Create (input)\nclass UserCreate(SQLModel):\n    email: str\n    password: str  # Plain password, will be hashed\n\n# API Schema - Read (output)\nclass UserRead(SQLModel):\n    id: UUID\n    email: str\n    created_at: datetime\n    # Note: No password field!\n\n# API Schema - Update (partial)\nclass UserUpdate(SQLModel):\n    email: str | None = None\n    password: str | None = None\n```\n\n**Naming convention:**\n- `ModelName` - Database table model\n- `ModelNameCreate` - Input for creation\n- `ModelNameRead` - Output for reading\n- `ModelNameUpdate` - Input for partial updates\n\n---\n\n## Pattern: Session State Management\n\n**Problem:** Understanding `expire_on_commit` and when objects become stale.\n\n```python\n# This codebase setting\nasync_session = async_sessionmaker(\n    engine,\n    expire_on_commit=False,  # Objects stay valid after commit\n)\n\n# With expire_on_commit=False:\nuser = User(email=\"test@example.com\")\nsession.add(user)\nawait session.commit()\nprint(user.email)  # Works - object still valid\n\n# With expire_on_commit=True (default):\nawait session.commit()\nprint(user.email)  # Would need refresh() first\n\n# ✅ CORRECT: Refresh when you need DB-generated values\nawait session.commit()\nawait session.refresh(user)  # Get id, created_at, updated DB values\nreturn user\n```\n\n---\n\n## Pattern: UUID Handling\n\n**Problem:** Inconsistent UUID handling between Python and PostgreSQL.\n\n```python\nfrom uuid import UUID, uuid4\n\n# ✅ CORRECT: UUID with default factory\nclass Assessment(SQLModel, table=True):\n    id: UUID = Field(default_factory=uuid4, primary_key=True)\n    user_id: UUID = Field(foreign_key=\"user.id\")\n\n# ✅ CORRECT: UUID in queries\nawait session.execute(\n    select(Assessment).where(Assessment.id == UUID(\"...\"))\n)\n\n# ❌ WRONG: String comparison\nawait session.execute(\n    select(Assessment).where(Assessment.id == \"some-uuid-string\")\n)\n\n# ✅ CORRECT: Converting in API layer\n@router.get(\"\u002Fassessments\u002F{assessment_id}\")\nasync def get_assessment(assessment_id: UUID):  # FastAPI converts string to UUID\n    ...\n```\n\n---\n\n## Pattern: Nullable Fields\n\n**Problem:** SQLModel requires specific syntax for optional fields.\n\n```python\n# ✅ CORRECT: Optional field with None default\nclass Assessment(SQLModel, table=True):\n    id: UUID = Field(default_factory=uuid4, primary_key=True)\n    title: str  # Required\n    description: str | None = Field(default=None)  # Optional\n    completed_at: datetime | None = Field(default=None)  # Optional\n    \n    # Foreign key that's optional\n    coach_id: UUID | None = Field(default=None, foreign_key=\"user.id\")\n\n# ❌ WRONG: Optional without Field default\nclass BadModel(SQLModel, table=True):\n    description: str | None  # Missing default - causes issues\n```\n\n---\n\n## Pattern: Relationship Definitions\n\n```python\nfrom sqlmodel import Relationship\n\nclass User(SQLModel, table=True):\n    id: UUID = Field(default_factory=uuid4, primary_key=True)\n    \n    # One-to-many: User has many assessments\n    assessments: list[\"Assessment\"] = Relationship(back_populates=\"user\")\n    \n    # One-to-many: User has many answers\n    answers: list[\"UserAnswer\"] = Relationship(back_populates=\"user\")\n\nclass Assessment(SQLModel, table=True):\n    id: UUID = Field(default_factory=uuid4, primary_key=True)\n    user_id: UUID = Field(foreign_key=\"user.id\")\n    \n    # Many-to-one: Assessment belongs to user\n    user: User = Relationship(back_populates=\"assessments\")\n    \n    # One-to-many: Assessment has many questions\n    questions: list[\"Question\"] = Relationship(back_populates=\"assessment\")\n\nclass Question(SQLModel, table=True):\n    id: UUID = Field(default_factory=uuid4, primary_key=True)\n    assessment_id: UUID = Field(foreign_key=\"assessment.id\")\n    \n    # Many-to-one\n    assessment: Assessment = Relationship(back_populates=\"questions\")\n```\n\n---\n\n## Pattern: Query Patterns\n\n```python\n# Get one or None\nresult = await session.execute(\n    select(User).where(User.id == user_id)\n)\nuser = result.scalar_one_or_none()\n\n# Get one or raise\nuser = result.scalar_one()  # Raises if 0 or >1 results\n\n# Get list\nresult = await session.execute(\n    select(Assessment).where(Assessment.user_id == user_id)\n)\nassessments = result.scalars().all()\n\n# Get with pagination\nresult = await session.execute(\n    select(Assessment)\n    .where(Assessment.user_id == user_id)\n    .order_by(Assessment.created_at.desc())\n    .offset(skip)\n    .limit(limit)\n)\n\n# Count\nresult = await session.execute(\n    select(func.count()).select_from(Assessment).where(...)\n)\ncount = result.scalar_one()\n\n# Exists check\nresult = await session.execute(\n    select(exists().where(User.email == email))\n)\nemail_exists = result.scalar()\n```\n\n---\n\n## Pattern: Upsert (Insert or Update)\n\n```python\nfrom sqlalchemy.dialects.postgresql import insert\n\n# ✅ CORRECT: PostgreSQL upsert\nstmt = insert(UserAnswer).values(\n    user_id=user_id,\n    question_id=question_id,\n    value=value,\n)\nstmt = stmt.on_conflict_do_update(\n    index_elements=[\"user_id\", \"question_id\"],\n    set_={\"value\": value, \"updated_at\": datetime.utcnow()},\n)\nawait session.execute(stmt)\nawait session.commit()\n```\n\n---\n\n## References\n\n- SQLModel documentation: https:\u002F\u002Fsqlmodel.tiangolo.com\u002F\n- SQLAlchemy 2.0 documentation: https:\u002F\u002Fdocs.sqlalchemy.org\u002F\n\n---\n\n## Common Issues\n\n| Issue | Likely Cause | Solution |\n|-------|--------------|----------|\n| \"greenlet_spawn has not been called\" | Lazy loading in async | Use `selectinload`\u002F`joinedload` |\n| N+1 queries (slow) | Missing eager loading | Add appropriate loading strategy |\n| \"Object not bound to session\" | Using object after session closed | Keep operations within session scope |\n| Stale data | Missing `refresh()` | Call `refresh()` after commit |\n| \"None is not valid\" for UUID | Missing `default_factory` | Add `Field(default_factory=uuid4)` |\n\n---\n\n## Detection Commands\n\n```bash\n# Find lazy relationship access\ngrep -rn \"\\.scalars\\(\\)\" --include=\"*.py\" -A5 | grep -E \"\\.\\w+\\s*$\"\n\n# Find models missing relationship loading\ngrep -rn \"select(\" --include=\"*.py\" | grep -v \"options(\"\n\n# Check for N+1 in logs (with echo=True)\n# Look for repeated similar queries\n```\n",{"name":5,"description":7},"main","def8531e65114c0fca8fb8551c1871ee0eed705c","skills\u002Faiskillstore\u002Fmarketplace\u002Fcjharmath\u002Fpy-sqlmodel-patterns",24,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub","https:\u002F\u002Fskillshub.wtf","https:\u002F\u002Fgithub.com\u002FComeOnOliver","AI & Blockchain Engineer\r\n","2026-06-24 22:07:19",{"source":8,"skillName":5,"commands":46,"prompt":56,"zipAvailable":57},[47,50,53],{"tool":48,"command":49},"npx","npx skills add ComeOnOliver\u002Fskillshub --skill py-sqlmodel-patterns",{"tool":51,"command":52},"bunx","bunx skills add ComeOnOliver\u002Fskillshub --skill py-sqlmodel-patterns",{"tool":54,"command":55},"pnpm","pnpm dlx skills add ComeOnOliver\u002Fskillshub --skill py-sqlmodel-patterns","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Faiskillstore\u002Fmarketplace\u002Fcjharmath\u002Fpy-sqlmodel-patterns\u002FSKILL.md",true,[59],{"path":60,"resourceType":61,"resourceTypeDesc":62,"sizeBytes":63,"sourceHtmlUrl":64},"skill-report.json","REFERENCE","参考文档",12831,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Faiskillstore\u002Fmarketplace\u002Fcjharmath\u002Fpy-sqlmodel-patterns\u002Fskill-report.json",[66,80,90,99,105,112],{"skillNo":67,"name":68,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":69,"categories":70,"keywords":76,"publishedAt":31},"01M6FKJN13GMG4KY57J3QD8GY5","model-hierarchy-skill","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzscole\u002Fmodel-hierarchy-skill\u002Fmodel-hierarchy-skill\u002FSKILL.md",[71],{"categoryNo":72,"categoryName":73,"taxonomyType":74,"taxonomyTypeDesc":75},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[77,78,79],"model","model hierarchy","model hierarchy skill",{"skillNo":81,"name":82,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":83,"categories":84,"keywords":86,"publishedAt":31},"01M6FKJJJ6GCAMR4PPPRD12M5X","zoom-mcp","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-mcp\u002FSKILL.md",[85],{"categoryNo":72,"categoryName":73,"taxonomyType":74,"taxonomyTypeDesc":75},[87,88,89],"MCP","zoom","zoom mcp",{"skillNo":91,"name":92,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":93,"categories":94,"keywords":95,"publishedAt":31},"01M6FKJE3KYT3KPEZMEEHYKA6K","zoom-apps-sdk","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-apps-sdk\u002FSKILL.md",[],[96,97,98,88],"sdk","zoom apps sdk","apps",{"skillNo":100,"name":101,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":102,"categories":103,"keywords":104,"publishedAt":31},"01M6FKJ9EDH9Q5VWDF8HAJRSP0","windows","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwindows\u002FSKILL.md",[],[101],{"skillNo":106,"name":107,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":108,"categories":109,"keywords":111,"publishedAt":31},"01M6FKJ666BEEFC3AE9GJ72Q93","whiteboard","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwhiteboard\u002FSKILL.md",[110],{"categoryNo":72,"categoryName":73,"taxonomyType":74,"taxonomyTypeDesc":75},[107],{"skillNo":113,"name":114,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":115,"categories":116,"keywords":117,"publishedAt":31},"01M6FKJ21WFCDGTJQ2Q91T9DVW","websockets","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwebsockets\u002FSKILL.md",[],[114]]