{
  "schemaVersion": "1.0",
  "item": {
    "slug": "fastapi",
    "name": "FastAPI",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/ivangdavila/fastapi",
    "canonicalUrl": "https://clawhub.ai/ivangdavila/fastapi",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/fastapi",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=fastapi",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "SKILL.md"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-04-30T16:55:25.780Z",
      "expiresAt": "2026-05-07T16:55:25.780Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=network",
        "contentDisposition": "attachment; filename=\"network-1.0.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/fastapi"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/fastapi",
    "agentPageUrl": "https://openagent3.xyz/skills/fastapi/agent",
    "manifestUrl": "https://openagent3.xyz/skills/fastapi/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/fastapi/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "Async Traps",
        "body": "Mixing sync database drivers (psycopg2, PyMySQL) in async endpoints blocks the event loop — use async drivers (asyncpg, aiomysql) or run sync code in run_in_executor\ntime.sleep() in async endpoints blocks everything — use await asyncio.sleep() instead\nCPU-bound work in async endpoints starves other requests — offload to ProcessPoolExecutor or background workers\nAsync endpoints calling sync functions that do I/O still block — the entire call chain must be async"
      },
      {
        "title": "Pydantic Validation",
        "body": "Default values in models become shared mutable state: items: list = [] shares the same list across requests — use Field(default_factory=list)\nOptional[str] doesn't make a field optional in the request — add = None or use Field(default=None)\nPydantic v2 uses model_validate() not parse_obj(), and model_dump() not .dict() — v1 methods are deprecated\nUse Annotated[str, Field(min_length=1)] for reusable validated types instead of repeating constraints"
      },
      {
        "title": "Dependency Injection",
        "body": "Dependencies run on every request by default — use lru_cache on expensive dependencies or cache in app.state for singletons\nDepends() without an argument reuses the type hint as the dependency — clean but can confuse readers\nNested dependencies form a DAG — if A depends on B and C, and both B and C depend on D, D runs once (cached per-request)\nyield dependencies for cleanup (DB sessions, file handles) — code after yield runs even if the endpoint raises"
      },
      {
        "title": "Lifespan and Startup",
        "body": "@app.on_event(\"startup\") is deprecated — use lifespan async context manager\nStore shared resources (DB pool, HTTP client) in app.state during lifespan, not as global variables\nLifespan runs once per worker process — with 4 Uvicorn workers you get 4 DB pools\n\nfrom contextlib import asynccontextmanager\n@asynccontextmanager\nasync def lifespan(app):\n    app.state.db = await create_pool()\n    yield\n    await app.state.db.close()\napp = FastAPI(lifespan=lifespan)"
      },
      {
        "title": "Request/Response",
        "body": "Return dict from endpoints, not Pydantic models directly — FastAPI handles serialization and it's faster\nUse status_code=201 on POST endpoints returning created resources — 200 is the default but semantically wrong\nResponse with media_type=\"text/plain\" for non-JSON responses — returning a string still gets JSON-encoded otherwise\nSet response_model_exclude_unset=True to omit None fields from response — cleaner API output"
      },
      {
        "title": "Error Handling",
        "body": "raise HTTPException(status_code=404) — don't return Response objects for errors, it bypasses middleware\nCustom exception handlers with @app.exception_handler(CustomError) — but remember they don't catch HTTPException\nUse detail= for user-facing messages, log the actual error separately — don't leak stack traces"
      },
      {
        "title": "Background Tasks",
        "body": "BackgroundTasks runs after the response is sent but still in the same process — not suitable for long-running jobs\nTasks execute sequentially in order added — don't assume parallelism\nIf a background task fails, the client never knows — add your own error handling and alerting"
      },
      {
        "title": "Security",
        "body": "OAuth2PasswordBearer is for documentation only — it doesn't validate tokens, you must implement that in the dependency\nCORS middleware must come after exception handlers in middleware order — or errors won't have CORS headers\nDepends(get_current_user) in path operation, not in router — dependencies on routers affect all routes including health checks"
      },
      {
        "title": "Testing",
        "body": "TestClient runs sync even for async endpoints — use httpx.AsyncClient with ASGITransport for true async testing\nOverride dependencies with app.dependency_overrides[get_db] = mock_db — cleaner than monkeypatching\nTestClient context manager ensures lifespan runs — without with TestClient(app) as client: startup/shutdown hooks don't fire"
      }
    ],
    "body": "FastAPI Patterns\nAsync Traps\nMixing sync database drivers (psycopg2, PyMySQL) in async endpoints blocks the event loop — use async drivers (asyncpg, aiomysql) or run sync code in run_in_executor\ntime.sleep() in async endpoints blocks everything — use await asyncio.sleep() instead\nCPU-bound work in async endpoints starves other requests — offload to ProcessPoolExecutor or background workers\nAsync endpoints calling sync functions that do I/O still block — the entire call chain must be async\nPydantic Validation\nDefault values in models become shared mutable state: items: list = [] shares the same list across requests — use Field(default_factory=list)\nOptional[str] doesn't make a field optional in the request — add = None or use Field(default=None)\nPydantic v2 uses model_validate() not parse_obj(), and model_dump() not .dict() — v1 methods are deprecated\nUse Annotated[str, Field(min_length=1)] for reusable validated types instead of repeating constraints\nDependency Injection\nDependencies run on every request by default — use lru_cache on expensive dependencies or cache in app.state for singletons\nDepends() without an argument reuses the type hint as the dependency — clean but can confuse readers\nNested dependencies form a DAG — if A depends on B and C, and both B and C depend on D, D runs once (cached per-request)\nyield dependencies for cleanup (DB sessions, file handles) — code after yield runs even if the endpoint raises\nLifespan and Startup\n@app.on_event(\"startup\") is deprecated — use lifespan async context manager\nStore shared resources (DB pool, HTTP client) in app.state during lifespan, not as global variables\nLifespan runs once per worker process — with 4 Uvicorn workers you get 4 DB pools\nfrom contextlib import asynccontextmanager\n@asynccontextmanager\nasync def lifespan(app):\n    app.state.db = await create_pool()\n    yield\n    await app.state.db.close()\napp = FastAPI(lifespan=lifespan)\n\nRequest/Response\nReturn dict from endpoints, not Pydantic models directly — FastAPI handles serialization and it's faster\nUse status_code=201 on POST endpoints returning created resources — 200 is the default but semantically wrong\nResponse with media_type=\"text/plain\" for non-JSON responses — returning a string still gets JSON-encoded otherwise\nSet response_model_exclude_unset=True to omit None fields from response — cleaner API output\nError Handling\nraise HTTPException(status_code=404) — don't return Response objects for errors, it bypasses middleware\nCustom exception handlers with @app.exception_handler(CustomError) — but remember they don't catch HTTPException\nUse detail= for user-facing messages, log the actual error separately — don't leak stack traces\nBackground Tasks\nBackgroundTasks runs after the response is sent but still in the same process — not suitable for long-running jobs\nTasks execute sequentially in order added — don't assume parallelism\nIf a background task fails, the client never knows — add your own error handling and alerting\nSecurity\nOAuth2PasswordBearer is for documentation only — it doesn't validate tokens, you must implement that in the dependency\nCORS middleware must come after exception handlers in middleware order — or errors won't have CORS headers\nDepends(get_current_user) in path operation, not in router — dependencies on routers affect all routes including health checks\nTesting\nTestClient runs sync even for async endpoints — use httpx.AsyncClient with ASGITransport for true async testing\nOverride dependencies with app.dependency_overrides[get_db] = mock_db — cleaner than monkeypatching\nTestClient context manager ensures lifespan runs — without with TestClient(app) as client: startup/shutdown hooks don't fire"
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/ivangdavila/fastapi",
    "publisherUrl": "https://clawhub.ai/ivangdavila/fastapi",
    "owner": "ivangdavila",
    "version": "1.0.0",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/fastapi",
    "downloadUrl": "https://openagent3.xyz/downloads/fastapi",
    "agentUrl": "https://openagent3.xyz/skills/fastapi/agent",
    "manifestUrl": "https://openagent3.xyz/skills/fastapi/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/fastapi/agent.md"
  }
}