返回 Skills 目录
samber/developer-platform-skills已通过检查

SKILL DETAIL

sdk-portfolio-strategy

samber/developer-platform-skills/sdk-portfolio-strategy

Decide a public API's language-SDK portfolio - which languages get official SDKs and in what order, generated vs handwritten build model, official and community support tiers with a promotion gate, SDK deprecation and end-of-life, and decoupling SDK SemVer from API versioning and release cadence. Use whenever the user mentions client libraries, SDKs, which languages to support first, an SDK generator (Stainless, Fern, OpenAPI Generator), community SDKs, or sunsetting an SDK - even if they never say "SDK portfolio". Portfolio strategy only, not single-SDK ergonomics or registry publishing. Do NOT use for whether to offer SDKs as a surface at all - use samber/developer-platform-skills@api-integration-surface-strategy instead.

安装量 · 323查看来源

Installation

npx skills add https://github.com/samber/developer-platform-skills --skill sdk-portfolio-strategy

技能文件

SKILL.md

最近同步 · 2026年10月23日

evals/evals.json›
{
  "skill_name": "sdk-portfolio-strategy",
  "evals": [
    {
      "id": 1,
      "prompt": "I'm head of platform at Ledgerwell. We sell a reconciliation and payments API to mid-market banks and enterprise finance teams. About 40 customers have integrated so far, all of them either Java shops or .NET shops, plus a couple of Ruby ones from our early days. We're finally doing real client libraries instead of the curl examples we have now. I pulled the TIOBE index and last year's Stack Overflow developer survey, and the obvious order out of those is Python, JavaScript, Java, then C++. My VP wants nine languages shipped by the end of the year. Which ones do we actually build, and in what order?",
      "expected_output": "A language order derived from the fintech/enterprise buyer stack rather than popularity rankings: a small official core front-loading Java and C#, every other language pushed to spec-driven self-service, a self-set add-a-language threshold, and telemetry instrumented to confirm rather than originate the mapping.",
      "files": [],
      "expectations": [
        "Recommends a small official core of roughly 2-5 languages rather than the nine the VP asked for",
        "Front-loads Java and C# ahead of Python and JavaScript for this buyer base",
        "Rejects TIOBE, the Stack Overflow developer survey, and GitHub Octoverse as decision inputs, stating that no vendor documents choosing languages from a named popularity ranking",
        "Uses the integrators' own stack as the primary input to the language order",
        "Cites Stripe's or Plaid's fintech SDK portfolio by naming its actual languages as the documented precedent",
        "Places every language outside the official core on spec-driven self-service, pointing the long tail at open-source generators driven by the published spec",
        "States an add-a-language threshold such as a sustained double-digit share of API traffic or repeated enterprise-deal requests naming that language",
        "Labels that threshold as self-set rather than a published industry standard",
        "Recommends instrumenting per-language client telemetry via User-Agent or SDK headers",
        "States that the telemetry confirms the audience mapping rather than originating the language order",
        "Names Plaid's cap of five official libraries alongside 40+ languages self-served from its spec",
        "Ranks the coverage rungs explicitly (official SDK vs community tier vs spec-driven self-service) instead of presenting a flat list of languages"
      ]
    },
    {
      "id": 2,
      "prompt": "Northwind Freight here, we run a logistics tracking API with about 1,200 API customers. We've got four engineers on the platform team and we're about to start on client libraries for Python, Node, Java, Go and PHP. My position is that if we're calling them official they have to be hand-written, because generated code always looks like a machine barfed it and customers can tell. Separately, our security org has a hard rule that nothing in our build pipeline may call out to an external SaaS, everything runs inside our own network. We do have an OpenAPI 3.1 spec but honestly it's been drifting from the real API for about six months now. How should we build these five?",
      "expected_output": "A generated build model that dismantles the official-equals-handwritten assumption, treats the air-gap rule as deleting the hosted commercial option rather than demoting it, fixes spec drift first, and records lock-in guardrails including a written exit plan.",
      "files": [],
      "expectations": [
        "States explicitly that 'official' is a support commitment, not a build method",
        "Cites Plaid generating its five official SDKs with the free open-source OpenAPI Generator as the counter-example",
        "Recommends a generated build model rather than hand-writing all five libraries",
        "Treats the air-gapped/no-external-SaaS requirement as deleting the hosted commercial generator option outright rather than demoting it in a ranking",
        "Names OpenAPI Generator and/or Speakeasy as options compatible with fully self-hosted, air-gapped generation",
        "Warns that free OpenAPI Generator output is technically correct but non-idiomatic, and budgets standing curation effort for it",
        "Applies one build model portfolio-wide, permitting at most one handwritten flagship exception",
        "Requires the OpenAPI spec, not a vendor configuration DSL, to remain the single source of truth",
        "Requires a written exit plan naming who regenerates the SDKs if a generator vendor disappears, recorded before any commitment",
        "Tells the team to fix the six months of spec drift before generating anything from it",
        "Expresses the cost of hand-maintaining many languages as an order of magnitude (engineer-years of standing effort) rather than a currency budget",
        "Does not claim that generated SDKs cannot be official or cannot carry a support commitment",
        "Ranks the build-model options on effort, value and efficiency instead of presenting them as interchangeable"
      ]
    },
    {
      "id": 3,
      "prompt": "Bellwether Analytics. We ship API v3 in five weeks and it is a real breaking change: new auth and a new pagination model. We maintain SDKs for Python, Node, Go, Java and Ruby, all currently on 2.4.x. The plan my team likes is to cut 3.0.0 in all five languages the same day the API flips to v3, so the numbers line up and nobody gets confused about which SDK talks to which API. We also want to drop Node 16 and Go 1.21 in that same release. Does this hold up, and what do I write down as the actual policy?",
      "expected_output": "A refusal to couple SDK majors to the API version, split into three separately written policies (SDK SemVer, API versioning, language-runtime support window), a published SDK-major-to-API-version mapping table, and an explicit release cadence choice.",
      "files": [],
      "expectations": [
        "Refuses to bump SDK majors merely because the API released a new version",
        "Separates the SDK package version (SemVer) from the API version as two distinct written policies",
        "Names the language-runtime support window as a third policy, separate from both of the others",
        "States that an SDK major is warranted only when the SDK's own code surface breaks, such as a renamed method or changed constructor",
        "Cites Stripe's stated split: SemVer for SDKs, release-date versioning for the API",
        "Prescribes a published mapping table from SDK major version to the API version(s) it supports",
        "Identifies that mapping table as an artifact Stripe and/or AWS actually maintain and worth copying",
        "Ties the runtime support window mechanically to upstream language lifecycles plus a stated grace window",
        "Cites a concrete runtime-window precedent such as Stripe's four most recent Go versions, Node LTS 18+, or AWS's latest two GA Go versions with a six-month grace",
        "Leaves ownership of the API-side versioning scheme to the separate API versioning policy, recording only the boundary here",
        "Offers a cadence choice between a fixed release train and continuous release-on-change",
        "Carries Azure's own warning not to publish releases just to keep to a regular cadence if a fixed train is proposed",
        "Frames release cadence as a predictability promise to integrators rather than a productivity metric"
      ]
    },
    {
      "id": 4,
      "prompt": "Hartwell Data, I run the SDK team. Our PHP library gets about 180 downloads a month on Packagist. Python does 400k a month and Node does 260k. Our VP of Engineering saw those three numbers in a review and wants the PHP repo archived this sprint so the one engineer maintaining it can move onto Go. I either need to make that case properly or push back with something better than a feeling. What do I do?",
      "expected_output": "An evidence-gated EOL case that makes exclusive-usage revenue at risk the decisive number rather than download counts, executes final release then announcement then archive in that order, names a successor, and schedules post-archival docs cleanup.",
      "files": [],
      "expectations": [
        "Requires isolating the accounts that use the PHP SDK exclusively, with no other SDK of ours, as the decisive evidence",
        "Quantifies revenue at risk from that exclusive-usage segment rather than from raw download counts",
        "Refuses to treat the low download number alone as sufficient justification for retirement",
        "Attributes the evidence-gated process to Sentry's published SDK deprecation playbook",
        "Gathers upstream platform health and registry download trends as supporting rather than decisive evidence",
        "Orders execution as final release, then announcement, then archive",
        "States the final release must be cut before the deprecation is announced",
        "Requires a pinned deprecation issue naming the reason, the successor, and the remaining timeline",
        "Requires naming a specific successor path for affected users rather than issuing a bare end-of-life notice",
        "Requires registry deprecation markers plus README and docs-site banners",
        "Requires notifying support and go-to-market teams as part of execution",
        "Schedules post-archival cleanup 6-12 months later, de-indexing the retired docs while keeping them reachable rather than returning 404, with redirects to the successor",
        "States an announcement-to-archive window within the observed 6-24 month range",
        "Rejects archiving within the current sprint or without an announced notice window"
      ]
    },
    {
      "id": 5,
      "prompt": "Verity Cloud. We're closing a seven-figure deal and their procurement team sent a question we have to answer in writing: how long will we keep supporting v2 of our client libraries once v3 ships? Their exact wording was 'AWS commits to 12 months of maintenance, we expect the same.' Our legal team wants a published support policy page live before signature. What do we commit to, and how do we word it?",
      "expected_output": "A published lifecycle policy that surfaces the genuine disagreement between AWS's own documents instead of quoting one number, states the GA-support and announcement-lead floors, describes phased support, and offers Azure's floor as an alternative anchor.",
      "files": [],
      "expectations": [
        "Flags that AWS's own published policies disagree on the maintenance-phase duration",
        "Names 12 months from the core SDKs-and-Tools maintenance policy and 6 months from the Powertools documentation as the two conflicting figures",
        "Refuses to quote 'AWS's policy' as a single number without naming which document it comes from",
        "States AWS's commitment of at least 24 months of general-availability support",
        "States AWS's maintenance announcement lead time of at least 6 months before maintenance mode begins",
        "Describes a phased lifecycle (developer preview, GA, maintenance announcement, maintenance, end-of-support) rather than one flat support window",
        "Notes that the maintenance phase means critical bug fixes and security issues only, with no API updates",
        "Notes that the maintenance announcement is timed with the successor major version's GA so users have a migration target from day one of the notice",
        "Cites a worked AWS timeline as evidence the default flexes, such as JavaScript v2 announced September 2024 with end-of-support September 2025, or the .NET v3 window of only about three months",
        "Offers Azure's floor as an alternative anchor: at least 12 months of critical fixes, or 3 years when breaking changes are involved",
        "Produces the answer as a published support policy page rather than a verbal or deal-specific commitment",
        "Does not invent a single industry-standard support duration presented as universal"
      ]
    },
    {
      "id": 6,
      "prompt": "Orbital Grid, we do fleet management for industrial IoT. We ship official SDKs in Python, Go and Java. There is a Rust crate named `orbital-grid` built by an independent developer, roughly 60k downloads, and frankly it is better than what we would write ourselves. Our CTO wants to make it official next quarter. I've been handed the job of writing the tier definitions and the promotion policy for the whole portfolio. What goes in it?",
      "expected_output": "A two-tier policy with an explicit community non-guarantee and support routing, plus a written promotion gate turning on canonical namespace transfer and maintainer cooperation, with any fuller rubric labeled as self-set rather than a published standard.",
      "files": [],
      "expectations": [
        "Makes transfer of the canonical registry package name an explicit condition of promotion",
        "Makes the original maintainer's cooperation and consent a condition, not a unilateral vendor decision",
        "Cites the Anthropic Ruby SDK case, where the community maintainer donated the canonical gem name, as the documented promotion precedent",
        "Includes crediting the original maintainer publicly as part of the promotion",
        "Labels any fuller promotion rubric (usage volume, feature completeness, support commitment) as inferred or self-set rather than a published standard",
        "Recommends the two-tier official-plus-community shape as the default",
        "Attaches an explicit non-guarantee to the community tier covering accuracy, completeness, or being kept up to date",
        "Routes community-SDK support requests to the community repository rather than the vendor's own ticket queue",
        "Instructs writing the promotion gate down before it is needed rather than deciding case by case",
        "Defines what the official tier buys the user (a support commitment) and what the community tier explicitly does not",
        "Encodes the quality level where users already look, in the version number and package metadata, not only on a docs page",
        "Cites a concrete metadata precedent such as Google Cloud requiring version 1.0 or higher plus the Production/Stable development-status classifier for GA",
        "Offers numbered tiers (MCP's Tier 1/2/3 or Azure's named tier-1 languages) as the alternative once 'official' alone stops discriminating",
        "States that MCP's tiers rank implementation completeness rather than feature ambition"
      ]
    },
    {
      "id": 7,
      "prompt": "Tessel Labs, nine people, we run an inference routing API. We're picking a code generation vendor this month for SDKs in TypeScript, Python, Go and Java. I've sat through three demos and I'm leaning toward whichever one has the nicest configuration layer, because writing a clean config file beats maintaining a giant OpenAPI document by hand. Pricing is roughly comparable across all three. Which should we sign, and what should I actually be comparing them on?",
      "expected_output": "A selection framed on continuity and exit cost rather than demo features: the 2026 consolidation cited by name, the proprietary-DSL sync and non-transferable-config risk spelled out, the spec kept as source of truth, self-hosting preferred, and a written exit plan before signing.",
      "files": [],
      "expectations": [
        "Raises vendor acquisition and continuity risk as a first-order selection criterion, not an afterthought",
        "Cites Postman's acquisition of Fern in January 2026",
        "Cites Anthropic's acquisition of Stainless and the wind-down of its hosted SDK generator",
        "States that Stainless customers kept their already-generated SDKs but lost the pipeline that kept those SDKs in sync with API changes",
        "Warns that a proprietary configuration DSL is a second artifact that must stay synchronized with the spec",
        "Warns that investment in a vendor's config DSL does not transfer, deepening the exit cost if the vendor disappears",
        "Distinguishes OpenAPI-native generators from DSL-interposing ones, naming at least one vendor on each side",
        "Requires the OpenAPI spec to remain the single source of truth regardless of which vendor is chosen",
        "Prefers a generator that can run self-hosted",
        "Requires a written exit plan naming who regenerates the SDKs if the vendor exits, recorded in the decision record before signing",
        "Notes the vendor landscape is time-sensitive and instructs re-verifying each vendor's current status before committing",
        "Declines to endorse adopting the vendor's configuration DSL as the source of truth in place of the spec",
        "Treats the build model as one portfolio-wide decision rather than a per-language vendor choice"
      ]
    },
    {
      "id": 8,
      "prompt": "Hey, I'm the new PM on the platform team at Halcyon Ops (workflow automation for ops teams, around 600 paying accounts). Our CEO is presenting to the board on Friday and asked me for a slide listing the six languages we're going to ship SDKs in. Can you just give me the six? I started three weeks ago so I don't really have the background here yet.",
      "expected_output": "A refusal to hand over a language list cold: an interview run one question at a time, verification that SDKs were actually chosen as an integration surface, 2-3 candidate portfolio shapes with trade-offs and a recommendation, and section-by-section approval toward seven written policies.",
      "files": [],
      "expectations": [
        "Asks clarifying questions before proposing any language list",
        "Asks one question per message rather than delivering the whole questionnaire in a single block",
        "Asks which developer vertical the integrators belong to",
        "Asks whether a machine-readable OpenAPI-style spec exists and what state it is in",
        "Asks which languages the team can genuinely maintain in-house over years",
        "Asks whether procurement and security can accept a hosted commercial generator",
        "Asks whether per-language client traffic telemetry exists today",
        "Asks whether this is a one-off catch-up or a compounding portfolio policy the team will run for years",
        "Verifies that SDKs were actually chosen as an integration surface, and defers that decision to the separate integration-surface-strategy skill if it has not been made",
        "Uses the Friday deadline as an explicit re-ranking input, noting a hard deadline promotes generated coverage over handwritten SDKs",
        "Presents 2-3 candidate portfolio shapes with trade-offs and a recommendation instead of a single answer",
        "Names candidate shapes such as a lean core plus self-service long tail, broad generated coverage on one pipeline, or a handwritten flagship plus generated rest",
        "States that the strategy is complete only when all seven workflow steps end in a written, user-approved policy"
      ]
    }
  ],
  "trigger_queries": [
    {
      "query": "Which language SDKs should we build first for our new public API?",
      "should_trigger": true
    },
    {
      "query": "we're launching an API next quarter, do we hand-write the client libraries or generate them?",
      "should_trigger": true
    },
    {
      "query": "Help me define official versus community support tiers for our client libraries.",
      "should_trigger": true
    },
    {
      "query": "Should our SDK version numbers track our API version numbers?",
      "should_trigger": true
    },
    {
      "query": "Our PHP client library has almost no downloads. Should we kill it?",
      "should_trigger": true
    },
    {
      "query": "How do I decide which languages get official libraries and which ones don't?",
      "should_trigger": true
    },
    {
      "query": "The vendor that generates our client libraries just got acquired and is shutting down the hosted product. What now?",
      "should_trigger": true
    },
    {
      "query": "Is OpenAPI Generator good enough for libraries we'd call official?",
      "should_trigger": true
    },
    {
      "query": "write me a policy for retiring one of our client libraries",
      "should_trigger": true
    },
    {
      "query": "A community member built a Go client for us. Can we adopt it as the official one?",
      "should_trigger": true
    },
    {
      "query": "We have 11 client libraries and 3 engineers. Which ones do we drop?",
      "should_trigger": true
    },
    {
      "query": "What's a sensible release cadence for our client libraries across seven languages?",
      "should_trigger": true
    },
    {
      "query": "Our customers keep asking for a Rust library. How do I decide whether it's worth it?",
      "should_trigger": true
    },
    {
      "query": "Should we pay for a codegen vendor or use the free open-source one?",
      "should_trigger": true
    },
    { "query": "how many client libraries is too many", "should_trigger": true },
    {
      "query": "We need a written support commitment for our client libraries to close an enterprise deal.",
      "should_trigger": true
    },
    {
      "query": "Draft the deprecation timeline for our v2 client libraries.",
      "should_trigger": true
    },
    {
      "query": "Our Java library is hand-written and the other five are generated. Is that a problem?",
      "should_trigger": true
    },
    {
      "query": "what languages does a fintech API need client libraries in",
      "should_trigger": true
    },
    {
      "query": "Which Python and Node versions should our libraries promise to support?",
      "should_trigger": true
    },
    {
      "query": "we want to add official Kotlin and Swift support, talk me out of it",
      "should_trigger": true
    },
    {
      "query": "Set up a promotion path so third-party libraries can become official ones.",
      "should_trigger": true
    },
    {
      "query": "I need to pick a codegen vendor without getting locked in.",
      "should_trigger": true
    },
    {
      "query": "How do other API companies decide the order they ship client libraries in?",
      "should_trigger": true
    },
    {
      "query": "our client libraries have drifted apart, each language behaves a bit differently now",
      "should_trigger": true
    },
    {
      "query": "Should we generate from our OpenAPI spec or from a vendor config DSL?",
      "should_trigger": true
    },
    {
      "query": "We're an AI infra startup. Python and TypeScript libraries first, then what?",
      "should_trigger": true
    },
    {
      "query": "Write the non-guarantee wording for our community-maintained libraries.",
      "should_trigger": true
    },
    {
      "query": "how do i justify killing a library to the exec team",
      "should_trigger": true
    },
    {
      "query": "Do we need to bump all our libraries to 4.0 when the API goes to v4?",
      "should_trigger": true
    },
    {
      "query": "Our security team won't allow a hosted SaaS anywhere in the build pipeline for our client libraries.",
      "should_trigger": true
    },
    {
      "query": "Plan the order we ship client libraries over the next 18 months.",
      "should_trigger": true
    },
    {
      "query": "What evidence do I need before announcing end of life for a client library?",
      "should_trigger": true
    },
    {
      "query": "Should we archive the repo before or after we announce the deprecation?",
      "should_trigger": true
    },
    {
      "query": "I want a Tier 1 / Tier 2 / Tier 3 system for our libraries.",
      "should_trigger": true
    },
    {
      "query": "we support 4 languages officially, should it be more or fewer",
      "should_trigger": true
    },
    {
      "query": "Is it fine for an officially supported library to be code-generated?",
      "should_trigger": true
    },
    {
      "query": "Our buyers are all Java and .NET shops but everyone tells me to ship Python first.",
      "should_trigger": true
    },
    {
      "query": "How long do we have to keep patching an old major version of our libraries?",
      "should_trigger": true
    },
    {
      "query": "Put together the strategy doc for our client library program.",
      "should_trigger": true
    },
    {
      "query": "Which of our client libraries should we invest in next year?",
      "should_trigger": true
    },
    {
      "query": "there are community libraries for our API in six languages, what do we do about them",
      "should_trigger": true
    },
    {
      "query": "Do we list third-party client libraries on our docs site or ignore them?",
      "should_trigger": true
    },
    {
      "query": "We're rewriting all our client libraries. What should we decide before we start?",
      "should_trigger": true
    },
    {
      "query": "How do I use client traffic data to decide the next language we support?",
      "should_trigger": true
    },
    {
      "query": "Our API is the product. Should we hand-roll the flagship library?",
      "should_trigger": true
    },
    {
      "query": "Should we even offer SDKs, or is a great REST API plus webhooks enough?",
      "should_trigger": false
    },
    {
      "query": "Do we need client libraries at all, or should we invest in a Postman collection and good docs?",
      "should_trigger": false
    },
    {
      "query": "Design our API versioning scheme: header, URL path, or date-based?",
      "should_trigger": false
    },
    {
      "query": "How long do we support an old API version after we ship a breaking change?",
      "should_trigger": false
    },
    {
      "query": "Write the deprecation notice for the /v1/charges endpoint.",
      "should_trigger": false
    },
    {
      "query": "Audit our API reference docs for missing code samples in each language.",
      "should_trigger": false
    },
    {
      "query": "Our docs snippets don't match what the SDKs actually return. Fix the review process.",
      "should_trigger": false
    },
    {
      "query": "Review our new endpoints for naming consistency before we freeze the API.",
      "should_trigger": false
    },
    {
      "query": "Design the error code taxonomy for our public API.",
      "should_trigger": false
    },
    {
      "query": "Should our API keys be hashed or encrypted at rest?",
      "should_trigger": false
    },
    {
      "query": "How do we do zero-downtime API key rotation?",
      "should_trigger": false
    },
    {
      "query": "Design an idempotency key mechanism for our payments endpoints.",
      "should_trigger": false
    },
    {
      "query": "What rate limits should we set per plan tier?",
      "should_trigger": false
    },
    {
      "query": "Set up a status page and incident communication process for our API.",
      "should_trigger": false
    },
    {
      "query": "Build a sandbox test mode with fake data for our API.",
      "should_trigger": false
    },
    {
      "query": "Design our webhook delivery retries and signature scheme.",
      "should_trigger": false
    },
    {
      "query": "Should we build an MCP server for our product?",
      "should_trigger": false
    },
    {
      "query": "Plan the information architecture for our developer portal.",
      "should_trigger": false
    },
    {
      "query": "Design our OAuth 2.0 authorization server and consent screen.",
      "should_trigger": false
    },
    {
      "query": "Should we expose GraphQL alongside our REST API?",
      "should_trigger": false
    },
    {
      "query": "Design the proto files and streaming semantics for our gRPC API.",
      "should_trigger": false
    },
    {
      "query": "How should customers bulk-export their data, S3 dumps or a query API?",
      "should_trigger": false
    },
    {
      "query": "Give customers read-only SQL access to their warehouse data over JDBC.",
      "should_trigger": false
    },
    {
      "query": "Which data connectors should our pipeline product build first?",
      "should_trigger": false
    },
    {
      "query": "Should we launch a connector marketplace or keep building integrations ourselves?",
      "should_trigger": false
    },
    {
      "query": "Draft the partnership terms for a technology integration with a CRM vendor.",
      "should_trigger": false
    },
    {
      "query": "Optimize our listing on a major app marketplace so it converts better.",
      "should_trigger": false
    },
    {
      "query": "Write the review checklist for third-party apps submitted to our marketplace.",
      "should_trigger": false
    },
    {
      "query": "Should we take a revenue share or charge a listing fee in our app marketplace?",
      "should_trigger": false
    },
    {
      "query": "Plan the launch marketing for our new app marketplace.",
      "should_trigger": false
    },
    {
      "query": "Set the listing quality standards for apps published in our marketplace.",
      "should_trigger": false
    },
    {
      "query": "Design the onboarding flow for partners building apps on our platform.",
      "should_trigger": false
    },
    {
      "query": "How do we monitor and alert on failing customer integrations?",
      "should_trigger": false
    },
    {
      "query": "What does a career path look like for a platform engineer on an API team?",
      "should_trigger": false
    },
    {
      "query": "Write the job description for a developer platform lead.",
      "should_trigger": false
    },
    {
      "query": "I'm joining a developer platform team next week. Where do I even start?",
      "should_trigger": false
    },
    {
      "query": "Make our Python SDK feel more idiomatic: better error types and pagination helpers.",
      "should_trigger": false
    },
    {
      "query": "Improve the developer experience of our TypeScript client: retries, timeouts, logging.",
      "should_trigger": false
    },
    {
      "query": "How do I publish our Java SDK to Maven Central?",
      "should_trigger": false
    },
    {
      "query": "Write the README for our npm package so it converts on the registry page.",
      "should_trigger": false
    },
    {
      "query": "Help me install and configure the Sentry Node SDK in our app.",
      "should_trigger": false
    },
    {
      "query": "Migrate our code from AWS SDK for JavaScript v2 to v3.",
      "should_trigger": false
    },
    {
      "query": "Upgrade our project from AI SDK v6 to v7.",
      "should_trigger": false
    },
    {
      "query": "Show me how to stream responses with the Vercel AI SDK.",
      "should_trigger": false
    },
    {
      "query": "Add the Apify SDK to my scraper project.",
      "should_trigger": false
    },
    {
      "query": "Build an agent using the Claude Agent SDK.",
      "should_trigger": false
    }
  ]
}
references/build-model-vendor-landscape.md›
# Build-model vendor landscape

Snapshot of the SDK-generation vendor market as of mid-2026. Named-vendor facts here are time-sensitive - the 2026 consolidation below is proof - so re-check a vendor's current status before the user commits to it.

## Vendor comparison table

| Vendor                                               | Model                                                                 | Languages                                                          | Runtime type safety                                                 | Notable users                                     |
| ---------------------------------------------------- | --------------------------------------------------------------------- | ------------------------------------------------------------------ | ------------------------------------------------------------------- | ------------------------------------------------- |
| Speakeasy                                            | Commercial, VC-backed ($15M Series A, Oct 2024)                       | 10 (TS, Python, Go, Java, C#, PHP, Ruby, Kotlin, Unity, Terraform) | Yes (Zod for TS); single runtime dependency for TS                  | Vercel, Mistral AI, Clerk, Kong, Airbyte          |
| Fern (now Postman)                                   | Commercial + open-source core; acquired Jan 2026                      | 9 major languages post-acquisition                                 | Server-stub generation supported                                    | Square, Auth0, Twilio, ElevenLabs, Cohere         |
| Stainless (now Anthropic; hosted product wound down) | Was commercial ($25M Series A, a16z, Dec 2024); closed to new signups | 7-9                                                                | No runtime validation (casts response data) - vendor-authored claim | OpenAI, Anthropic, Google, Cloudflare, Perplexity |
| APIMatic                                             | Commercial since 2014; also sells a developer portal                  | 7+                                                                 | No; TS SDKs carry 40+ dependencies - vendor-authored claim          | Enterprise API providers                          |
| OpenAPI Generator                                    | Open source, free                                                     | 50+ targets                                                        | No                                                                  | Plaid (for its official SDKs) and many others     |

Free-tier and per-language subscription pricing existed across the commercial vendors at this snapshot. Treat any specific figure as stale and check current pricing directly. The ordering that persists: OpenAPI Generator costs no license and the most curation effort, commercial generators cost a subscription and the least.

## The structural fault line: OpenAPI-native vs proprietary DSL

Speakeasy, APIMatic, and OpenAPI Generator treat the OpenAPI spec itself as the source of truth. Stainless and Fern interpose a proprietary configuration layer between the spec and the generated output - a second artifact that must stay synchronized with the spec, and "in long-running API programs with frequent schema changes, that synchronization cost is not theoretical" (Speakeasy/WorkOS framing, 2026). A DSL layer also deepens the exit cost if the vendor disappears: the config investment doesn't transfer.

Air-gap axis: at this snapshot only Speakeasy and OpenAPI Generator supported fully self-hosted, air-gapped generation. The others required vendor-hosted connectivity. Speakeasy CEO Sagar Batchu's framing: "SDK generation has moved from a developer convenience to a piece of enterprise infrastructure that security, compliance, and platform teams all care about" - i.e., this is a procurement question, not only a technical one.

## The 2026 consolidation - the lock-in cautionary tale, dated

**Fern → Postman (January 8, 2026, terms undisclosed).** Postman acquired Fern with a continuity commitment ("The product, brand, and roadmap remain unchanged"). Fern continues as a product inside Postman. The soft lesson: even a benign acquisition changes the roadmap owner your pipeline depends on.

**Stainless → Anthropic (announced May 18, 2026, reported at more than $300M via TechCrunch/The Information).** An acquisition-driven wind-down, not an organic shutdown: Anthropic is winding down all hosted Stainless products including the SDK generator - no new signups, projects, or generation. Existing customers keep full ownership of already-generated SDKs but lose the auto-maintenance pipeline that kept them in sync with API changes. The strategic reading (The New Stack): the weight is "not the Stainless technology landing inside Anthropic. It is the effect on everyone else" - Anthropic removed a shared supplier that OpenAI, Google, and Cloudflare all depended on.

What this validates for a portfolio strategy:

- SDK generation is strategic infrastructure worth nine-figure M&A, not a commodity utility.
- Hosted, vendor-locked generation carries real continuity risk.

Both push the same guardrails regardless of vendor choice: OpenAPI as the source of truth, a self-host or escrow fallback, and a written exit plan.

## When an in-house pipeline beats any vendor

WorkOS's criteria for building your own generation pipeline (Stripe's path): the API is a core product, not an afterthought, and the team wants:

- No vendor pricing or acquisition-risk exposure.
- Idiomatic output matching exact in-house SDK conventions.
- Full ownership of the pipeline.

Otherwise a turnkey generator removes work an in-house pipeline would only relocate.

The cost side, both vendor-sourced - cite as order-of-magnitude, never as budget figures: APIMatic estimates hand-maintaining SDKs across many languages and APIs at multiple engineer-years of standing cost. A Stripe alumnus, via Fern's marketing: "I know how much effort goes into it. It's one of those things that I'm very happy to buy, not build."

Speakeasy names the failure mode of under-resourced handwriting: teams "assign developers or contractors to handroll SDKs… punt on a long-term support system," ending with "SDKs with divergent behavior" across languages.

## The Plaid counter-example: official ≠ handwritten

Plaid generates its five _official_ client libraries (Ruby, Node, Python, Java, Go) with the free, open-source OpenAPI Generator - documented in the `plaid/plaid-openapi` repo (e.g. `openapi-generator-cli generate -g java --library=retrofit2`) - and lets everyone else self-serve from the same spec in 40+ languages. Use this whenever someone equates "official" with "handwritten": the tier is a support commitment. The build model is a separate decision.

The standing knock on the free path is idiomaticity - OpenAPI Generator output is widely described as technically correct but non-idiomatic ("Java-like rather than native" for Python/TS/Go, per Speakeasy's vendor-authored critique), and enterprise forks typically absorb multiple FTEs of curation. Plaid shows the model works. It does not show it is free.

## Snippet parity: the docs by-product of the build model

The OpenAPI `x-codeSamples` extension is how a spec carries per-operation, per-language code samples into rendered reference docs.

- Commercial generators can push these overlays automatically for every operation, keeping docs snippets in lockstep with the generated SDKs.
- The alternative is a hand-maintained, CI-tested snippet repository (Twilio's model: one repo, one test harness, one fake-API server).

Whichever build model wins, decide who owns snippet parity in the same pass - `samber/developer-platform-skills@api-reference-quality` audits the result.
references/language-order-and-versioning-cases.md›
# Language-order cases and versioning decoupling

Documented company cases for step 2 (language order) and step 5 (versioning and cadence) of the workflow.

## Language order is audience-driven - the documented cases

No major API vendor publishes a ranking algorithm. Each maps its buyer's stack, then confirms with its own traffic and registry telemetry. The fintech-vs-AI/dev-tools contrast is the clearest documented pattern:

- **Twilio.** Its engineering blog states the rationale directly: "For a long time we've supported and maintained helper libraries and tooling in the most popular languages and environments used by developers." Documented growth path: from a few languages and 12 endpoints to "8 subdomains and over 200 endpoints in 7 languages: C#, Java, Python, PHP, Ruby, Node.js and Salesforce". Go was then added later as a deliberate, named, sequenced expansion: "We're now expanding that coverage by providing a Twilio Helper for Go". Twilio also runs the documented two-tier model (official + "Community Supported Libraries") and moved its official libraries to auto-generation from an in-house generator "inspired by boto3, raml-codegen and swagger."
- **Plaid (fintech).** Exactly 5 official libraries - Ruby, Node, Python, Java, Go - plus a documented long tail: the OpenAPI spec lets developers "auto-generate your own client libraries in over 40 different languages," with C#, PHP, and Rust explicitly named as third-party-generation-only.
- **Stripe (fintech).** Official server-side SDKs for Ruby, PHP, Java, Python, Node, .NET, and Go, plus a separate community-libraries page. The set is read as reflecting its merchant/web-developer base - Ruby and PHP trace to early web-commerce adoption, not to general popularity rankings.
- **OpenAI / Anthropic (AI/dev-tools).** Both lead with Python and TypeScript - the dominant AI-integration languages - then expand to Go, Java, Kotlin, Ruby. Both portfolios were generated via Stainless, covering "the five languages that cover the bulk of production AI integration work."

**Sequencing pattern across the cases:**

1. Ship the language the earliest customers already use.
2. Add the second-most-common next.
3. Achieve breadth via codegen or OpenAPI self-service rather than more official SDKs.

Twilio's one-language-at-a-time additions and Plaid's "5 official + 40 via OpenAPI" both illustrate the official-core-plus-generated-long-tail model.

## Audience-mapping practice and documented patterns

Vendors uniformly map their buyer's stack as the primary input to language ordering, not generic popularity rankings. No company cites Stack Overflow Developer Survey, TIOBE, or GitHub Octoverse by name as a formal decision input.

Telemetry-driven prioritization ("usage analytics decide the next language") is stated only as general practice by SDK tooling vendors - no company publishes its own telemetry-driven decision as policy. When you instrument client `User-Agent`/SDK-header telemetry, use the data to confirm the audience mapping rather than originate it.

The add-a-language threshold this skill recommends (a sustained double-digit share of API traffic, or repeated enterprise-deal requests naming the language) is self-set. Make it explicit in your policy as your own decision, not a published standard.

## Stripe's three decoupled versioning policies - the canonical worked example

Stripe states the split directly: "We use the semantic versioning standard for SDKs, and version APIs by release date." Three genuinely separate policies:

1. **SDK package version - SemVer per package** (e.g. `stripe-python` 6.0.0). A breaking change to the SDK's code surface (renamed method, changed constructor) is a different event from a breaking change to the API contract. Conflating the two forces an SDK major release every time the API changes even when no client code broke, and vice versa.
2. **API version - date-based with account pinning.**
   - Each account is pinned to the API version active at its first request. Every breaking change ships as a new dated version (e.g. `2024-09-30.acacia`) rather than mutating the pinned one.
   - Cadence: two named major releases per year that may break, plus monthly backward-compatible releases.
   - A per-request `Stripe-Version` header overrides the pin for a single call: how canary-testing a new version works before migrating an account's default.

   Owning this policy is `samber/developer-platform-skills@api-versioning-policy`'s job. This skill only records the boundary.

3. **Language-runtime support window** - which host-language versions the SDK runs on:
   - Go: "the 4 most recent Go versions".
   - Node: "all LTS versions of Node.js 18+".
   - Python: 3.9+, with a 1-year extended-support window after a Python version's own upstream end-of-life.

   AWS runs the same policy as an explicitly separate axis (e.g. its Go SDK supports the latest two GA Go versions plus a 6-month grace window).

**The artifact that keeps decoupling workable: a published mapping table from SDK major version to the API version(s) it supports.** Both Stripe and AWS maintain this in GitHub wikis/READMEs - copy the artifact, not just the principle. The inferred recommendation to write into policy: bump SDK majors only on SDK-surface breaks, maintain the mapping table, and never let an API version change force an SDK major (or the reverse).

## Release cadence norms - a predictability promise, not a productivity metric

- **Azure:** a fixed monthly release train across all supported languages (its Java client BOM moved to monthly cadence in September 2021) - with Azure's own explicit warning: "YOU SHOULD NOT publish new package releases just to keep to a regular cadence." The train exists for integrator predictability, not to manufacture releases.
- **AWS:** continuous GA releases as changes land - new services, API updates, bug and security fixes - no calendar cadence.
- **Google Cloud:** continuous, auto-generated releases via the GAPIC Generator - release when the generator has new input.

Pick one model and state it in the strategy document. The choice follows the build model (a generated portfolio releases naturally on-change, a handwritten one benefits from a train that batches work).
references/tier-promotion-and-eol-playbooks.md›
# Tier frameworks, promotion gates, and EOL playbooks

Named, citable frameworks for step 3 (tiers and promotion) and step 6 (deprecation and EOL) of the workflow.

## Tier frameworks

**Two-tier (official + community) - the simplest documented norm.**

- Stripe: "Stripe-maintained SDKs are available for Ruby, PHP, Java, Python, Node, .NET and Go. Community libraries are also available for other server languages."
- Twilio, on its community tier: "these libraries are not supported by Twilio, and we can't speak to their accuracy/completeness."
- Plaid: "community libraries are not officially supported by Plaid… Plaid cannot… guarantee that they will be kept up-to-date."

Copy the structure: an official tier with a support commitment, a community tier with an explicit non-guarantee, support routed to the community repo.

**MCP's SDK Tiering System** (modelcontextprotocol.io/community/sdk-tiers) - the cleanest numbered ladder:

- Tier 1: fully supported, with complete protocol implementation and all non-experimental features.
- Tier 2: actively maintained, still working toward full spec support.
- Tier 3: experimental, partial, or specialized.

Tiering is by implementation completeness, never by feature ambition - experimental features are required at no tier.

**Azure - tier 1 names concrete languages.** Azure's SDK policy requires a GA library to "support all four tier-1 languages (.NET, Java, Python, TypeScript) unless there is a good (and documented) reason to not include support for one." Its beta gate is four checkable requirements:

- At least 2 languages (one statically typed, one dynamically typed).
- A beta available for at least one month.
- No known critical bugs.
- Three reference customers external to the Azure organization.

Post-GA states: Active (minimum 12 months) and Deprecated (critical-fixes-only for at least 12 months, or 3 years if the deprecation involves breaking changes).

**Google Cloud - quality level encoded in the version and package metadata**, not a separate policy page.

- GA requires version ≥1.0 plus the `"Development Status :: 5 - Production/Stable"` classifier.
- Beta and Alpha use the corresponding classifiers.
- Alpha/Preview carries an explicit warning that libraries can "get deprecated and deleted before ever being promoted."

Most Google Cloud libraries are auto-generated (GAPIC). The hand-maintained minority is identifiable by an `.OwlBot.yaml` file, a mechanical way to audit generated-vs-handwritten in an existing portfolio.

Google Cloud Looker's support policy gives the checkable community-status criteria: an SDK stays community when it:

- Lacks required features.
- Lacks support/automation infrastructure (automated testing, packaging, docs, examples).
- Is built on deprecated technology.
- Hasn't been tested by enough distinct users.

## The promotion gate - one documented case, the rest inferred

**Anthropic's Ruby SDK (the Alex Rudall case) is the only cleanly documented community-to-official promotion on record.** The canonical `anthropic` RubyGem name belonged to Rudall's community library. When Anthropic shipped its official Ruby SDK (beta ~April 2025, `anthropics/anthropic-sdk-ruby`), Rudall donated the gem name and renamed his project to `ruby-anthropic`.

Anthropic's official README credits him: "Thank you @alexrudall for giving feedback, donating the anthropic Ruby Gem name, and paving the way by building the first Anthropic Ruby SDK." The mechanism promotion actually turned on the maintainer's willingness to transfer the canonical package namespace, plus vendor support commitment - not a vendor decision alone.

Other commonly-cited "promotions" (DigitalOcean's `godo`, Stripe's `stripe-go`) are now official, but no announcement documents a formal promotion event for either. A fuller promotion rubric spans sustained usage/download volume, feature completeness (auth, pagination, retries), maintainer cooperation on namespace, and a vendor support commitment. Write this explicitly into your own policy rather than pointing to any published checklist.

## AWS's five-phase SDK lifecycle

Per docs.aws.amazon.com/sdkref/latest/guide/maint-policy.html, each major SDK version moves through:

- **Phase 0 - Developer Preview**: not supported, not for production, breaking changes expected.
- **Phase 1 - General Availability**: fully supported; AWS commits to "at least 24 months" of GA support - the floor to cite when asked how soon an SDK can be deprecated.
- **Phase 2 - Maintenance Announcement**: public announcement at least 6 months before maintenance mode, typically timed with the next major version's GA so users get a migration target on day one of the notice.
- **Phase 3 - Maintenance**: critical bug fixes and security issues only. No API updates. **Internal inconsistency to cite honestly:** the core SDKs-and-Tools policy defaults this phase to 12 months, while AWS's own Powertools docs state a 6-month default - the two AWS policies genuinely differ by product line, so never quote "AWS's policy" as one number without naming which document.
- **Phase 4 - End-of-Support**: no further releases; published packages remain on registries, the repo may be archived.

Communication mechanism: a pinned GitHub RFC issue plus updates to reference docs, guides, marketing pages, and READMEs. AWS also ties dependency support to a mechanical downstream rule worth copying: support ends 6 months after the community or vendor ends support for that dependency.

Worked timelines:

- AWS SDK for JavaScript v2: maintenance announced Sept 8, 2024, end-of-support Sept 8, 2025 (the 12-month default).
- AWS SDK for Java v1.x: maintenance July 31, 2024, end-of-support Dec 31, 2025.
- AWS SDK for .NET v3: maintenance March 1, 2026, end-of-support June 1, 2026, only a 3-month window, proof the default flexes per product line.

## Sentry's three-phase full-SDK EOL playbook

Sentry's published playbook (develop.sentry.dev, "Deprecating an SDK") is the most rigorous public evidence-gated process, written in RFC-2119 MUST/SHOULD terms:

**Phase 1 - Build the case, before any announcement.**

- Document upstream platform health ("Has the platform reached end of life?").
- Gather usage data (orgs, projects actively using the SDK).
- Pull download trends from the language's own registry analytics (npmtrends, PyPI Stats, NuGet, Maven Central).
- Quantify revenue at risk by isolating "orgs that use the SDK exclusively (no other Sentry SDKs) - this is the true at-risk segment."

Document opportunity cost against higher-growth SDKs, identify migration paths, and record engineering-manager approval in the team tracker. This is the sourced answer to "what data justifies killing a low-usage SDK."

**Phase 2 - Execute, order matters:** "cut the final release before announcing, and announce before archiving." Steps in order:

1. Final release pinned to up-to-date dependencies.
2. Pinned GitHub deprecation issue stating why, alternatives, and remaining timeline.
3. Backlog closed with uniform messaging.
4. A prominent README notice naming successor SDKs.
5. Docs-site warning banners.
6. Registry deprecation marker.
7. Repo archived.
8. Support and GTM teams notified.

High-impact deprecations should also get a blog post.

**Phase 3 - Post-EOL cleanup, 6-12 months after archival:** de-index retired docs but keep them reachable at their direct URLs (don't 404), and redirect to the successor SDK's docs.

Documented executions, each naming a specific successor:

- `sentry-cordova` archived March 2026 (users routed to Capacitor/React Native/Flutter SDKs).
- `sentry-xamarin` archived after Xamarin's own end-of-life (routed to `sentry-dotnet` via .NET MAUI).

## Other citable sunset floors

- **Stripe, language-runtime deprecation** (a separate axis from API deprecation): when a language runtime reaches its own end of life, Stripe marks it deprecated and runs an extended support window of 1 to 2 years depending on the language, pre-announced in docs, READMEs, and changelogs. Documented example: Python 2.7 support dropped at `stripe-python` 6.0.0.
- **Azure:** 12 months of critical fixes minimum after deprecation, 3 years if breaking changes are involved. For a tiny remaining user base, Azure's guidance is white-glove: "consider working with them individually to migrate" instead of a blanket timeline.
- **Google Cloud:** Preview/Alpha libraries carry no promotion guarantee at all and can be deleted before ever reaching GA, the harshest documented policy. Make sure your own alpha tier says which model it follows.

**Six-step sunset sequence** - gathered from AWS, Sentry, Stripe, and Azure practices:

1. Gather usage and revenue-at-risk evidence per Sentry's exclusive-user model.
2. Confirm a migration path exists.
3. Announce with a fixed timeline - 6 to 24 months is the observed range.
4. Cut a clean final release.
5. Mark the package deprecated on its registry.
6. Archive only after the announced window closes.

Write this as your own policy when you adopt it.
SKILL.md›
---
name: sdk-portfolio-strategy
description: Decide a public API's language-SDK portfolio - which languages get official SDKs and in what order, generated vs handwritten build model, official and community support tiers with a promotion gate, SDK deprecation and end-of-life, and decoupling SDK SemVer from API versioning and release cadence. Use whenever the user mentions client libraries, SDKs, which languages to support first, an SDK generator (Stainless, Fern, OpenAPI Generator), community SDKs, or sunsetting an SDK - even if they never say "SDK portfolio". Portfolio strategy only, not single-SDK ergonomics or registry publishing. Do NOT use for whether to offer SDKs as a surface at all - use samber/developer-platform-skills@api-integration-surface-strategy instead.
license: MIT
metadata:
  author: Samuel Berthe
  version: "1.0.1"
---

# SDK Portfolio Strategy

You are an SDK portfolio strategist for a platform team. Decide which language SDKs the platform ships, in what order, built how, supported at what tier, versioned on what scheme, and retired by what process - as one written, approved strategy document, not a pile of per-SDK improvisations.

This is a portfolio decision, upstream of any single SDK's design. The distinct question of whether SDKs belong in the integration mix at all is owned by the umbrella surface-selection skill (see References); start here only once that answer is yes.

**Memory (advised):** When memory lives in a file, consider using `developer-platform-context.md`; if a different memory system is in use, rely on that instead. The file is an advisory reference, not a mandatory requirement. Separate task info in different sections. Remove finished tasks. Add a date to a task; no date for general project context. Some interview responses may differ between 2 tasks.

## Interview

Ask one question per message and wait for the answer - each one changes a later step. Offer multiple-choice options where given.

1. Who integrates with you - which developer vertical? (a) fintech / enterprise backend, (b) AI / dev-tools, (c) web / commerce, (d) infrastructure / cloud, (e) mixed or other. This drives the language order more than any popularity ranking.
2. Does a machine-readable spec (OpenAPI or equivalent) exist, and in what state? (a) linted source of truth in CI, (b) exists but drifts from the API, (c) none. Every generated-SDK option depends on this answer.
3. What exists today: no SDKs yet, official SDKs (how many, generated or handwritten?), community-built SDKs in the wild, or a mix?
4. Which languages can your team genuinely maintain in-house - review idiomatically, debug, and keep releasing for years?
5. Build-vs-buy appetite: can procurement and security accept a hosted commercial generator, or is self-hosted/air-gapped generation a hard requirement?
6. Do you have per-language API traffic telemetry (client `User-Agent` or SDK headers)? If not, plan to instrument it - decisions below want that data.
7. By when must the first portfolio decision land - is there a launch or deal deadline?
8. Is this a one-off catch-up (ship the missing SDKs) or a compounding asset (a portfolio policy the team runs for years)?
9. What is your effort ceiling: engineer-hours available, appetite for a standing maintenance commitment per extra language, and how reversible each choice must be?

Answers 7-9 re-rank both option menus below - a hard deadline promotes generated coverage; a compounding mandate promotes policy work over shipping one more SDK.

## Developer vertical split

The split that changes the strategy is the target-developer vertical, and it is the clearest documented pattern in the field:

- Fintech and enterprise platforms front-load Java, C#, Ruby, and Go. Stripe: Ruby, PHP, Java, Python, Node, .NET, Go. Plaid: Ruby, Node, Python, Java, Go.
- AI and dev-tools platforms front-load Python and TypeScript first, then expand to Go, Java, Kotlin, Ruby. OpenAI and Anthropic both follow this pattern.

Map your interview answer 1 onto this contrast before looking at any generic language ranking.

## Brainstorm candidate portfolios

Before writing the strategy, present 2-3 candidate portfolio shapes with trade-offs and a recommendation, and let the user pick or blend. Typical candidates:

- **Lean core + self-service long tail** - 2-4 official SDKs for the confirmed audience languages; publish the spec and point everyone else at generators (Plaid's model: 5 official libraries, 40+ languages via its OpenAPI spec).
- **Broad official coverage on a generator** - 6-10 languages generated from one pipeline; widest official surface, largest standing maintenance and review commitment.
- **Handwritten flagship + generated rest** - full idiomatic investment in the one language carrying most integration traffic, generated coverage elsewhere.

Then draft the strategy document section by section (one section per workflow step below), validating each section with the user before moving to the next. Do not finalize until every section is approved. If your harness has persistent memory, record the approved decisions - language order, build model, tier policy, versioning split, EOL thresholds - so later tactical runs load them instead of re-interviewing.

## Workflow

1. Confirm the surface decision.
2. Map the audience to a language order.
3. Set support tiers and the promotion gate.
4. Choose the build model.
5. Decouple the three versioning policies.
6. Write the deprecation and EOL playbook.
7. Publish the community policy.

Each step has a section below, in order. Every step ends in a written policy - a step that ends in a conversation is not done.

## 1. Confirm the surface decision

Verify that SDKs were actually chosen as an integration surface, and for which audiences - that decision belongs to the umbrella surface-strategy skill, not here. If it hasn't been made, stop and make it first; an SDK portfolio built for a surface nobody chose is pure maintenance debt. Record which audiences the SDK surface serves, because step 2 prioritizes for exactly those audiences.

## 2. Map the audience to a language order

Rank per-language coverage options by what each language's demand actually justifies. Three coverage rungs per language:

- effort: `official SDK > community tier with promotion gate > spec-driven self-service`
- value (integration success and support burden absorbed): `official SDK > community tier > spec-driven self-service`
- efficiency: `spec-driven self-service > community tier > official SDK`

- **Default rung: spec-driven self-service for every language, official SDKs only for the 2-5 languages your vertical map and telemetry confirm.** Publish the spec and point the long tail at open-source generators - the documented "official core + generated long tail" pattern (Twilio grew from a few languages to 7 official ones deliberately, adding Go as a named, sequenced expansion; Plaid caps official support at 5).
- **The middle rung, a community tier with a promotion gate**, extends coverage without the standing commitment; step 7 defines it.
- **The starved option: an official SDK in a language below the traffic threshold.** High value to the accounts that ask, high effort forever, so it loses every efficiency round. What promotes it anyway: repeated enterprise-deal requests naming that language, or a strategic vertical you are entering ahead of the traffic.
- Add-a-language threshold: a sustained double-digit share of API traffic in that language, or those repeated named deal requests. Label this self-set when you write it down - no vendor publishes a numeric threshold, and none names Stack Overflow, TIOBE, or Octoverse as a decision input. Telemetry-driven prioritization is inferred best practice across the field, not a documented company policy. Instrument client-language telemetry (interview answer 6) so it confirms the audience mapping rather than originates it.

This ranking is a default, not a law. Re-rank against the interview: a team already fluent in a language gets its official SDK nearly free (answer 4), and a deal deadline (answer 7) can promote one language over the telemetry order.

See [references/language-order-and-versioning-cases.md](references/language-order-and-versioning-cases.md) for the documented Twilio, Plaid, Stripe, and OpenAI/Anthropic sequencing cases.

## 3. Set support tiers and the promotion gate

Define what "official" buys the user and what any other tier explicitly does not. Pick a shape and write it down:

- **Two-tier (official + community)** - the Stripe/Twilio/Plaid pattern: official SDKs carry a support commitment; community SDKs route to their own repos with an explicit non-guarantee. Cheapest to run; the default.
- **Numbered tiers** - MCP's Tier 1/2/3 (tiering by implementation completeness) or Azure's model, where "tier 1" names four concrete languages (.NET, Java, Python, TypeScript) that every GA library must support. Adopt when the portfolio is large enough that "official" alone stops discriminating.
- Encode the quality level where users already look: version number and package metadata (Google Cloud requires ≥1.0 plus the Production/Stable classifier for GA), not only a docs page.

Write the promotion gate - the checkable criteria for a community SDK to become official - before you need it. Anthropic's Ruby SDK is the only cleanly documented promotion on record: community maintainer Alex Rudall donated the canonical `anthropic` gem name when Anthropic shipped its official SDK, and the official README credits him.

That case shows promotion turns on namespace transfer and maintainer cooperation, not just a vendor decision. Any fuller promotion rubric (usage volume, feature completeness, support commitment) is inferred synthesis - label it that way in your policy.

See [references/tier-promotion-and-eol-playbooks.md](references/tier-promotion-and-eol-playbooks.md) for the full tier frameworks, gate criteria, and disclaimer language worth copying.

## 4. Choose the build model

The build model is one decision applied portfolio-wide, with at most one flagship exception. Three rungs:

- effort (what you spend, standing): `handwritten or in-house pipeline > free OpenAPI Generator > commercial codegen`
- value (idiomatic output and full control): `handwritten or in-house pipeline > commercial codegen > free OpenAPI Generator`
- efficiency: `commercial codegen > free OpenAPI Generator > handwritten or in-house pipeline`
- review and reversibility cost: `commercial codegen > free OpenAPI Generator == handwritten`. A commercial generator triggers procurement and security review and costs reversibility if the vendor exits (see failure modes). The tie is genuine because both other rungs are fully self-owned, with no vendor to lose.

- **Default rung: a commercial generator driven by the OpenAPI spec.** It removes work an in-house pipeline would only relocate, and multi-language idiomatic output is exactly what it sells. Condition on the spec being a real source of truth (interview answer 2). Fix the spec first if it drifts.
- **Step down to the free OpenAPI Generator** when procurement rules out vendors, air-gapped generation is required, or the language set is small and the team accepts the maintenance load - its output is widely described as technically correct but non-idiomatic, so budget curation effort. It is fully official-grade: Plaid generates its five official SDKs with it (documented in `plaid/plaid-openapi`) - "official" is a support commitment, not a build method.
- **The starved option: the handwritten flagship** (or an in-house pipeline, Stripe's path). Highest value, highest standing effort - vendor-order-of-magnitude estimates put hand-maintaining many languages at multiple engineer-years - so it loses every efficiency round. What promotes it: the API is the core product and one language carries the bulk of revenue traffic. Handwrite that one, generate the rest.
- Guardrails at every rung: keep the OpenAPI spec - not a vendor DSL - the single source of truth, prefer generators that can run self-hosted, and write the exit plan (who regenerates the SDKs if this vendor disappears?) into the decision record before signing.

This ranking is a default, not a law: re-rank against interview answers 4, 5, and 9. A hard self-host requirement deletes the hosted rung outright rather than demoting it.

See [references/build-model-vendor-landscape.md](references/build-model-vendor-landscape.md) for the vendor table, the 2026 consolidation case studies, and the in-house-beats-vendor criteria.

## 5. Decouple the three versioning policies

Stripe states the split directly: SDKs use SemVer; the API is versioned by release date. Write three separate policies and refuse to merge them:

1. **SDK package version** - SemVer per package. Major bump only when the SDK's own surface breaks (renamed method, changed constructor), never merely because the API released a new version.
2. **API version** - owned by the sibling versioning-policy skill (see References); this strategy only records which scheme it is and pins the boundary.
3. **Language-runtime support window** - which host-language versions each SDK supports (Stripe: last 4 Go versions, Node LTS 18+; AWS runs this as an explicitly separate policy from SDK lifecycle). Tie it mechanically to upstream language lifecycles plus a stated grace window.

Publish a mapping table from SDK major version to supported API version(s) - Stripe and AWS both maintain this artifact, and it is what lets the two schemes stay decoupled without confusing integrators. Then set release cadence:

- Fixed monthly train (Azure's model), with Azure's own warning not to publish releases just to keep the cadence.
- Continuous release-on-change (AWS, Google Cloud).

Cadence is a predictability promise to integrators, not a productivity metric.

See [references/language-order-and-versioning-cases.md](references/language-order-and-versioning-cases.md) for the Stripe mechanics and cadence norms.

## 6. Write the deprecation and EOL playbook

Retiring a whole language SDK is a distinct, heavier process than deprecating one API inside it. Adopt the evidence-gated shape of Sentry's published playbook (develop.sentry.dev, the most rigorous public one):

1. **Build the case before announcing anything.** Platform health, registry download trends, usage counts - and the decisive number: revenue at risk, isolating accounts that use this SDK _exclusively_, since customers who also use your other SDKs would barely notice. No EOL announcement without this evidence.
2. **Execute in order: final release → announcement → archive.** Pinned deprecation issue naming the why, the successor, and the timeline; registry deprecation markers; README and docs banners; support/GTM notified. Sentry's real executions each named a specific successor SDK, not just a goodbye.
3. **Clean up 6-12 months after archival** - keep retired docs reachable but de-indexed, redirect to the successor.

Set the timeline numbers from published floors, and cite them honestly.

- AWS commits to ≥24 months of GA support and a ≥6-month maintenance announcement, but its own policies disagree on maintenance duration: 12 months in the core SDKs-and-Tools policy, 6 months in the Powertools docs. Never quote "AWS's policy" as one number without naming which document.
- Azure floors deprecated-library fixes at 12 months (3 years with breaking changes).
- The observed announcement-to-archive range across vendors is 6-24 months. A synthesized 6-step sunset sequence is in the reference file, labeled inferred.

See [references/tier-promotion-and-eol-playbooks.md](references/tier-promotion-and-eol-playbooks.md) for the full AWS phases, Sentry playbook detail, and worked timeline examples.

## 7. Publish the community policy

Decide, in writing, how community SDKs are treated: welcomed and listed with an explicit non-guarantee (Twilio: "not supported by Twilio, and we can't speak to their accuracy/completeness"), ignored, or discouraged. Listing them with a disclaimer is the documented norm and the cheapest coverage extension - it staffs your long tail for free and feeds the step-3 promotion gate. State where support requests route (their repo, not your tickets), and revisit the list when a community SDK's language crosses the step-2 threshold: that is the moment to invoke the promotion gate rather than building a competitor from scratch.

## Failure modes

- **Lock-in through an acquired vendor.** The 2026 consolidation is the cautionary tale to cite by name.
  - Postman acquired Fern (January 8, 2026).
  - Anthropic acquired Stainless (announced May 18, 2026, reported at more than $300M) and wound down its hosted generator. Customers kept their generated code but lost the pipeline that kept SDKs in sync with API changes, while OpenAI, Google, and Cloudflare all depended on it.
  - The fix is step 4's guardrails: spec as source of truth, self-host option, written exit plan.
- **The official-equals-handwritten myth.** Teams over-invest in handwriting because they assume generated SDKs can't be "official". Plaid's five official SDKs are generated with the free OpenAPI Generator. Official is the support commitment in step 3, not the build method in step 4.
- **EOL by gut feeling.** Killing a low-download SDK without Sentry's exclusive-usage revenue check mistakes "small" for "safe to drop" - the few users left may have no other path to your product.
- **Language order from a popularity chart.** Generic rankings put Python first for a fintech platform whose integrators live in Java and Go. No vendor documents deciding from a named ranking. Every documented case maps the buyer's stack first.
- **One version number ruling everything.** Coupling SDK majors to API versions forces breaking releases on integrators whose code didn't break, and vice versa. Three policies, step 5.

## Measurement

- Decision coverage gate: all seven workflow steps end in a written, user-approved policy - 7 of 7, or the strategy is incomplete. Iterate until it passes.
- Language coverage gate: zero languages above your recorded add-threshold without an explicit build-or-decline decision on file.
- Trends to watch after adoption (not pass thresholds): per-language traffic share from client telemetry, per-SDK adoption vs. the direct-HTTP share in each language, and exclusive-usage account counts per SDK - refresh that last one before any EOL conversation, it is the step-6 evidence base.

## Invocation examples

- "We're launching our public API next quarter - which language SDKs should we build first, and should we generate them?"
- "We have handwritten Python and Ruby SDKs and community ones for Go and PHP - define support tiers and a promotion policy."
- "Our PHP SDK has almost no downloads. Build me the case for retiring it - or for keeping it."
- "Should our SDK versions track our API versions? Design the versioning and release-cadence policy."

## References

- [references/build-model-vendor-landscape.md](references/build-model-vendor-landscape.md) - generator vendor table, the 2026 Fern/Stainless consolidation case studies, in-house-pipeline criteria, snippet-parity mechanics.
- [references/tier-promotion-and-eol-playbooks.md](references/tier-promotion-and-eol-playbooks.md) - MCP/Azure/Google tier frameworks, two-tier disclaimer language, the Anthropic-Ruby promotion case, AWS's five phases, Sentry's three-phase EOL playbook, worked timelines.
- [references/language-order-and-versioning-cases.md](references/language-order-and-versioning-cases.md) - documented language-order cases by vertical, Stripe's three decoupled versioning policies, release-cadence norms, the SDK-to-API mapping table artifact.

Registry publishing mechanics (trusted publishing, dist-tags, rollback, private feeds) belong to `samber/developer-platform-skills@sdk-package-publishing`: this skill decides which SDKs exist, that one ships each package. The third-party `sdk-dx` skill on skills.sh covers single-SDK ergonomics and polish - this skill decides the portfolio, not any one SDK's developer experience.

See also, same owner:

- `samber/developer-platform-skills@api-integration-surface-strategy` - the umbrella surface-selection decision that step 1 assumes already answered yes for SDKs; run it first if that hasn't been decided.
- `samber/developer-platform-skills@api-versioning-policy` - owns the API-side versioning and deprecation policy that step 5 deliberately decouples SDK versioning from.
- `samber/developer-platform-skills@api-reference-quality` - audits per-language code-snippet parity in the reference docs, which the SDK portfolio feeds.
- `samber/developer-platform-skills@public-api-design-review` - reviews the API surface consistency every generated SDK inherits and projects into its language.
- `samber/developer-relations-skills@coding-agent-docs-optimization` - structuring SDK source and docstrings so coding agents integrate them unattended; the agent-consumption angle of the SDKs this portfolio ships.