项目文件夹
## Current Candidate: Jev and OpenAI Decisions Exact head: `9e7a61a9d85aacd812ec8e77a68b9d2adaecef66`. OpenAI Decisions support and the same sync/async provider/configuration contract family as OpenRouter and TypeSafe are included. Shared suite: **294 passed, 1 existing skip**. Decision source has **373/373 statements covered**; source unchanged since coverage measurement. Full source typing, test typing, and normal commit hooks passed. Six opt-in live provider cases were skipped without explicit opt-in; no billed API calls. Native OpenAI image input and live OpenAI compatibility remain unverified. Documentation: complete MkDocs build passed (13.17s; existing navigation/docstring warnings), primary example model definitions executed without API calls, guide linked in navigation, and OpenAI entry included in 1.18 release notes. Guide documents all three routes, raw wire differences, text-only support and shared/live test configuration. Fresh exact-head CI and required independent approval remain mandatory. Old-head auto-merge was disabled before updates. Previous-head checks below are historical evidence, not current proof. No merge or publication in this continuation. [Implementation and earlier validation details](https://github.com/567-labs/instructor/pull/2708#issuecomment-6052648661). ## Prior Integration Evidence ## Summary Curated Instructor 1.18 integration from main `e12f8b49203b0c1f253d27c1e709d0a09b9fc5a8`, current candidate `b76939ea652202842ae26aec4663ef52d13356d7`. Ready for independent review; this is not approval to merge or publish. - Include the reviewed typed Jev/TypeSafe and OpenRouter decision-mode feature and 1.18.0 metadata from #2707. - Consolidate hook dispatch (#2634), custom batch IDs (#2691), UTF-8 batch I/O (#2667), cache round-trips (#2688), citation validation (#2699), GenAI retry history (#2632), custom-type compatibility (#2629), and example corrections (#2697). - Revise IPv6 SSRF filtering (#2673) and symmetric streaming JSON bounds (#2638); preserve incremental streaming and public network policy. - Unify declared parallel tool names and reject unknown calls across providers (#2675/#2698), including actual retry boundaries and native xAI transport. Preserve the public generator contract and VertexAI class-name wire exception. - Isolate request histories in public retry/reask helpers (#2646) and fix incomplete Responses validation/cache acceptance (issue #2705). - Repair Python 3.9 generic-alias traversal without weakening async-validator rejection; remove redundant helper wrappers, obsolete version-specific test hacks and a duplicate negative test. The selected patches were revised where needed, not merged blindly. New transport contracts use real SDKs and loopback HTTP/gRPC, not new mocked provider clients. Existing legacy mocks are not claimed as live provider evidence. ## Validation Current candidate: `b76939ea652202842ae26aec4663ef52d13356d7`. Earlier local results below are for head `a3137a76159611c080ebcc0c36ccf0383901e2f2` unless a different head is named. - Normal commit hooks: Ruff lint/format and source typing passed. - Whole-test-tree typing passed with the SDK-complete environment. - Read-only final runtime review identified a Python 3.9 nested-generic class-check defect; fixed and independently reverified locally. This is not GitHub approval. - Minimum-version OpenAI loopback retry/cache/parallel contracts: 36 passed. Other SDKs are absent from this temporary core-only environment; their contracts passed in the full SDK-complete Python 3.13 suite, not in the minimum environment. - Focused Python 3.9/Pydantic 2.8.2 compatibility: 174 passed, 6 version skips. - Isolated wheel built from sdist: Python 3.9.25/OpenAI 2.0.0/Pydantic 2.8.0 contracts and credential-free CLI help passed. - Isolated wheel built from sdist: Python 3.13.11/OpenAI 3.3.0/Pydantic 2.13.5 contracts and credential-free CLI help passed. - Release metadata/changelog extraction validates 1.18.0. - All **29 runnable remote checks passed** at `a3137a76159611c080ebcc0c36ccf0383901e2f2`; publication was intentionally skipped. Required independent review remains unsatisfied. - Cursor Bugbot found that parallel parsing of an empty/prose response could escape the retry boundary as an unhandled exception. Head `9bcef9849fa609040c65fec30f1d3869e64d415e` adds `ResponseParsingError` guards and a missing-tool-calls regression test. Its full offline suite passed **3,963 tests**, but the zero-missing-statements gate failed on the untested empty-choices branch. Head `ba0db64bad4d9112fdcaef082bfd9a382a25e57c` adds that SDK-validated regression test; the complete focused parallel suite passed **54 tests**, plus Ruff lint/format and focused test typing. - At `ba0db64bad4d9112fdcaef082bfd9a382a25e57c`, **all 29 runnable CI checks passed** and publication was intentionally skipped. Full offline coverage ran **3,964 passed, 200 skipped, 859 deselected**, with **zero missing statements** and 4 missing branches. No threshold was reduced. - The current head changes only the decisions example and changelog accuracy: its primary example constructs under Python 3.9, and a full `mkdocs build --clean` passed. At `b76939ea652202842ae26aec4663ef52d13356d7`, **all 29 runnable CI checks passed**, publication was intentionally skipped, and full offline coverage reported **3,964 passed, 200 skipped, 859 deselected**, **zero missing statements**, and 4 missing branches. Independent maintainer approval remains outstanding. - Full credential-free offline suite: **3,962 passed, 200 skipped, 859 deselected**, with runtime/unraisable/thread warnings treated as errors. - Combined statement/branch coverage: **99.9700%**, **0 missing statements**, 4 missing branches; unchanged >=99% and zero-missing-statement gates passed. Existing version/optional/runtime exceptions remain disclosed; no threshold reductions. - Focused decision-mode contracts at the same head: **240 passed, 1 skipped** with credentials removed and localhost transport enabled. The initial sandbox-only run could not bind loopback sockets; the unchanged suite passed when loopback binding was permitted. - Opt-in live OpenRouter Jev model (`typesafe/jev-1.13`): **sync and async contracts passed** using the configured local key. No credential or response payload was added to this PR. Direct TypeSafe/Jev live calls remain unverified because `TYPESAFE_API_KEY` is unavailable. - Full `mkdocs build --clean` passed at the same head, writing only to a temporary site directory. It reported existing nav omissions and two griffe annotation warnings; no documentation build errors. No other live provider calls were made in this integration validation. Exhaustive repository security certification is not claimed. The Bugbot finding was addressed and its review thread resolved. Current-head CI passed; required independent maintainer approval remains the merge gate. No publication, tag, deployment, main merge or issue closure. ## Security and Compatibility - Reject the entire local-use NAT64 `64:ff9b:1::/48` prefix. Its translation layout is network-specific; assuming a fixed embedded destination is unsafe for this fetcher's public-network-only policy ([RFC 8215, section 5](https://www.rfc-editor.org/rfc/rfc8215.html#section-5)). Known well-known NAT64/mapped/compatible/6to4/Teredo destinations are checked as well as their IPv6 wrapper. - Streaming input limits are 1,048,576 characters and 128 nested containers, sync/async. Errors remain `ValueError`; complete objects can still emit before EOF. - Unknown parallel calls now raise `ResponseParsingError` inside retry rather than silently losing results. Nonstream validation is eager while the returned public generator type is preserved. - Incomplete Responses raise `IncompleteOutputException` before defaults or caches can turn partial output into an accepted answer. SDK metadata/reason remain attached. - Citation context accepts strings or lists/tuples of strings; malformed supplied sources fail closed. Missing context preserves existing behavior. - Decision mode is opt-in and currently does not support retries, caching, streaming or completion hooks. OpenRouter Jev sync/async compatibility passed live; direct TypeSafe/Jev compatibility is still supported by shared offline contracts only. ## Overlaps and Deferrals Reviewed the current 78-PR/28-issue queue. Compact selected changes received detailed source review; large providers/features/architecture received scope triage, not blanket approval. Absent CI is not passing. The table below records every source head inspected; these heads are not independently certified merge-ready. ## Every Open PR | PR / Inspected Head | Decision | | --- | --- | | [#2707](https://github.com/567-labs/instructor/pull/2707) `a2f0b309464b70b8936054466e6a365d16c9cb39` | Integrate/revise: reviewed compact fixes; preserve compatibility and repair tests. | | [#2704](https://github.com/567-labs/instructor/pull/2704) `5061c6866f2c94f46eedd4336753e9db8215fd9b` | Overlap: selected broader alternatives; older variants regress Python 3.9 or metadata. | | [#2703](https://github.com/567-labs/instructor/pull/2703) `248effa5c97e5c046685d7c6b144c4cbc7863702` | Overlap: selected broader alternatives; older variants regress Python 3.9 or metadata. | | [#2701](https://github.com/567-labs/instructor/pull/2701) `82a083207fe45993e339d74a96c5d2b0cba634fc` | Blocked: recursive described $ref causes infinite recursion; mappings change meaning. | | [#2700](https://github.com/567-labs/instructor/pull/2700) `79aa81e1dec364422dcac7401e67c150a547250c` | Deferred: buffers valid streaming output until EOF, breaking incremental behavior. | | [#2699](https://github.com/567-labs/instructor/pull/2699) `27dd66315794394a9c471c6a75c2ad4b538abae6` | Integrate/revise: reviewed compact fixes; preserve compatibility and repair tests. | | [#2698](https://github.com/567-labs/instructor/pull/2698) `59316edcbe5c1f3cc094d70f042a9d43a26a8db5` | Integrate/revise: reviewed compact fixes; preserve compatibility and repair tests. | | [#2697](https://github.com/567-labs/instructor/pull/2697) `692433fa8e04c21274232d83d042a27f37113924` | Integrate/revise: reviewed compact fixes; preserve compatibility and repair tests. | | [#2693](https://github.com/567-labs/instructor/pull/2693) `bfd56e7dda4d3444fd4d866f1c7399a5bee58b55` | Deferred: reconcile strict-schema required/defaulted fields and mapping policy together. | | [#2692](https://github.com/567-labs/instructor/pull/2692) `89f9db983865175e92a7096615ce2bcc454bfb07` | Separate dependency maintenance: compatibility and supply-chain review required. | | [#2691](https://github.com/567-labs/instructor/pull/2691) `81f28eb416c206c1b8ae702705e66007ac5e107d` | Integrate/revise: reviewed compact fixes; preserve compatibility and repair tests. | | [#2690](https://github.com/567-labs/instructor/pull/2690) `7c829eb06297d07bcd1ff957c481d8c042ef64da` | Deferred editorial: patch still leaves incorrect provider spelling/capitalization. | | [#2689](https://github.com/567-labs/instructor/pull/2689) `9688857ccba01dbebc4d3f5db0c1d158780c6c73` | Deferred docs/examples: maintenance/product choice; no correctness-release necessity. | | [#2688](https://github.com/567-labs/instructor/pull/2688) `f47161c87b872e13e54aecb9aed24e1a131a938b` | Integrate/revise: reviewed compact fixes; preserve compatibility and repair tests. | | [#2686](https://github.com/567-labs/instructor/pull/2686) `545232b6ff01f78fb938e84daeec4e876dfb45da` | Next compact batch: promising fixes, require exact-head runtime and combined validation. | | [#2685](https://github.com/567-labs/instructor/pull/2685) `7782155fc19e435173fa32ab7d5f78815bf99111` | Blocked: rejects native Converse tool histories and loses multiple system blocks. | | [#2683](https://github.com/567-labs/instructor/pull/2683) `3b09a98e768bfd2955164fe320cf0994a6f4b2a5` | Next compact batch: promising fixes, require exact-head runtime and combined validation. | | [#2680](https://github.com/567-labs/instructor/pull/2680) `7f70d2099a4b598f67a1b09e00ad7bed15cb832b` | Overlap: selected broader alternatives; older variants regress Python 3.9 or metadata. | | [#2678](https://github.com/567-labs/instructor/pull/2678) `0bed63816628aec034f5fc965b8d719d48bb0b8e` | Deferred: broader mapping-field response model construction. | | [#2677](https://github.com/567-labs/instructor/pull/2677) `2c0276aea1b25f061b3949b9883bd482ddd183cc` | Next compact batch: promising fixes, require exact-head runtime and combined validation. | | [#2675](https://github.com/567-labs/instructor/pull/2675) `e69a43d3cd7b8a3a8df758c946af510ef036e917` | Integrate/revise: reviewed compact fixes; preserve compatibility and repair tests. | | [#2673](https://github.com/567-labs/instructor/pull/2673) `06d34c3039faf530296960d24d50e8df8f9d9a6b` | Integrate/revise: reviewed compact fixes; preserve compatibility and repair tests. | | [#2672](https://github.com/567-labs/instructor/pull/2672) `4df16706ab588da537f76edec57b33ae9ff6141b` | Deferred: Mistral batch needs failure/error-file retrieval and provider evidence. | | [#2671](https://github.com/567-labs/instructor/pull/2671) `c3d95dccd28e803fa08cd89c87f5692ea044701a` | Deferred: global StrictUndefined is a deliberate compatibility change. | | [#2670](https://github.com/567-labs/instructor/pull/2670) `9763946ad1795ad6428daf277df06a07ee3c5dda` | Overlap: selected broader alternatives; older variants regress Python 3.9 or metadata. | | [#2668](https://github.com/567-labs/instructor/pull/2668) `2b028330d359994d3cd6c7ee6f2274bb950b2310` | Blocked: AliasChoices/AliasPath are unhashable in proposed alias set. | | [#2667](https://github.com/567-labs/instructor/pull/2667) `137b253c9e8b50602c39466c135b2e3c7400e3e0` | Integrate/revise: reviewed compact fixes; preserve compatibility and repair tests. | | [#2666](https://github.com/567-labs/instructor/pull/2666) `f2a1c390cd605c9928029d937c860b22456d26f2` | Next compact batch: promising fixes, require exact-head runtime and combined validation. | | [#2664](https://github.com/567-labs/instructor/pull/2664) `77f427ad196bed5c3bd6d61b3bd0855285d8e8e1` | Split first: useful Mistral usage-only fix, but Google empty candidates can erase safety refusal. | | [#2662](https://github.com/567-labs/instructor/pull/2662) `4c6e06613fc30a3ef6d29374e8df92bfb2a4122d` | Next compact batch: promising fixes, require exact-head runtime and combined validation. | | [#2660](https://github.com/567-labs/instructor/pull/2660) `1207effdd29b1aa1da9e0a283eda5551835f1a01` | Overlap: selected broader alternatives; older variants regress Python 3.9 or metadata. | | [#2657](https://github.com/567-labs/instructor/pull/2657) `8f619b3ab20d5cc6914b42c38bba80f6aa8c4585` | Next compact batch: promising fixes, require exact-head runtime and combined validation. | | [#2656](https://github.com/567-labs/instructor/pull/2656) `01c7bee784497eb87c7edab13ff1c64095f2c93c` | Deferred docs/examples: maintenance/product choice; no correctness-release necessity. | | [#2655](https://github.com/567-labs/instructor/pull/2655) `f4ce1943f2d666c465728062bc342d8934c55e66` | Next compact batch: promising fixes, require exact-head runtime and combined validation. | | [#2652](https://github.com/567-labs/instructor/pull/2652) `4bd39745d0ba809e293973697aa7a0be8ab64c81` | Overlap: selected broader alternatives; older variants regress Python 3.9 or metadata. | | [#2651](https://github.com/567-labs/instructor/pull/2651) `68786153500ce306f5bd65bb051aedd080e48a73` | Next compact batch: promising fixes, require exact-head runtime and combined validation. | | [#2649](https://github.com/567-labs/instructor/pull/2649) `f704f3530caef4891214a00dac7abd8496e92e96` | Overlap: selected broader alternatives; older variants regress Python 3.9 or metadata. | | [#2647](https://github.com/567-labs/instructor/pull/2647) `9bfaa3b75f83568063fa38dbd84d28a0a0848c0d` | Overlap: selected broader alternatives; older variants regress Python 3.9 or metadata. | | [#2646](https://github.com/567-labs/instructor/pull/2646) `a6dce755f054b1b2088faf8fffaea7dbfac05db7` | Integrate/revise: reviewed compact fixes; preserve compatibility and repair tests. | | [#2644](https://github.com/567-labs/instructor/pull/2644) `eda57883460ed8329775e9de4ede4a87b2786c67` | Overlap: selected broader alternatives; older variants regress Python 3.9 or metadata. | | [#2643](https://github.com/567-labs/instructor/pull/2643) `0fd74545d374afb249d01667a280115fa75b1156` | Deferred: main rejects async validators; set traversal is not a release necessity. | | [#2642](https://github.com/567-labs/instructor/pull/2642) `f208aec71909a7b27358bbdbfc2638a574585776` | Overlap: selected broader alternatives; older variants regress Python 3.9 or metadata. | | [#2641](https://github.com/567-labs/instructor/pull/2641) `2506e18dd4ed4e12bcc25069a4ce449138cf03b1` | Deferred: reconcile strict-schema required/defaulted fields and mapping policy together. | | [#2640](https://github.com/567-labs/instructor/pull/2640) `ca1fe9e902abdb5a1aea9eab04afdb133ae39c83` | Separate maintainer metadata hygiene. | | [#2639](https://github.com/567-labs/instructor/pull/2639) `e91095777cf4d031e7414bcaa427ab989c42f96e` | Overlap: selected broader alternatives; older variants regress Python 3.9 or metadata. | | [#2638](https://github.com/567-labs/instructor/pull/2638) `54ee418cad55aa93d9b6d1623a2e1b5ba066796e` | Integrate/revise: reviewed compact fixes; preserve compatibility and repair tests. | | [#2637](https://github.com/567-labs/instructor/pull/2637) `8b580fe0f2503dfa758a2d5be5957db81794c6ef` | Overlap: selected broader alternatives; older variants regress Python 3.9 or metadata. | | [#2636](https://github.com/567-labs/instructor/pull/2636) `3152a697f423b32bbe25af8021a948c35d8af41c` | Overlap: selected broader alternatives; older variants regress Python 3.9 or metadata. | | [#2634](https://github.com/567-labs/instructor/pull/2634) `aab02eaba1215a0f1e6ccf2139e88b1cc5539a8d` | Integrate/revise: reviewed compact fixes; preserve compatibility and repair tests. | | [#2633](https://github.com/567-labs/instructor/pull/2633) `2f337b3148717a76209616b72052ff1d4fb95709` | Deferred: timeout contract needs regression proof; current CI red. | | [#2632](https://github.com/567-labs/instructor/pull/2632) `ad3e32283f0ae51b3f06f5e06dc0415be282c5f5` | Integrate/revise: reviewed compact fixes; preserve compatibility and repair tests. | | [#2630](https://github.com/567-labs/instructor/pull/2630) `e5515c629eb4a94fab9953a1647de0ee66797132` | Overlap: selected broader alternatives; older variants regress Python 3.9 or metadata. | | [#2629](https://github.com/567-labs/instructor/pull/2629) `438debe231c3a49c9168b478ec82a82055983f47` | Integrate/revise: reviewed compact fixes; preserve compatibility and repair tests. | | [#2605](https://github.com/567-labs/instructor/pull/2605) `7e7d33a821b1b1593257a820ab52e656317405a8` | Blocked: cache values inherit and retain weak keys; GC test does not prove collection. | | [#2604](https://github.com/567-labs/instructor/pull/2604) `ce322502e3f4ba1f0ff62d5524965fec5233806a` | Deferred: markdown sanitization needs adversarial regression oracle. | | [#2602](https://github.com/567-labs/instructor/pull/2602) `a1229322d2b865d0224a2a94d222375eae4396bc` | Deferred providers/auth: scope-triaged, need ownership, SDK/wire contracts and live evidence. | | [#2598](https://github.com/567-labs/instructor/pull/2598) `6b153c8ba75e25461c43cd05c9b52f67ae3cb830` | Deferred providers/auth: scope-triaged, need ownership, SDK/wire contracts and live evidence. | | [#2574](https://github.com/567-labs/instructor/pull/2574) `0df33ba1111a6dc9da6788429bab9d4106bef2ae` | Separate dependency maintenance: compatibility and supply-chain review required. | | [#2573](https://github.com/567-labs/instructor/pull/2573) `2485aa6f4b9d7b7cb445214547968e1a7e61b564` | Separate dependency maintenance: compatibility and supply-chain review required. | | [#2572](https://github.com/567-labs/instructor/pull/2572) `c152a36b244b5e2618bd5e06e13ee1ce1876fa65` | Separate dependency maintenance: compatibility and supply-chain review required. | | [#2571](https://github.com/567-labs/instructor/pull/2571) `db4abe9654e386acbe9e64585b56bda419b0daa7` | Separate dependency maintenance: compatibility and supply-chain review required. | | [#2570](https://github.com/567-labs/instructor/pull/2570) `47caa02a3a924ee4f889e6cba9572da58ff40398` | Separate dependency maintenance: compatibility and supply-chain review required. | | [#2531](https://github.com/567-labs/instructor/pull/2531) `4f0a66465f96f08e256cdc3f0608e7578cf2ad9d` | Deferred docs/examples: maintenance/product choice; no correctness-release necessity. | | [#2468](https://github.com/567-labs/instructor/pull/2468) `6e68201124bca8957d4fe5ca42bd4ef5203e77c6` | Deferred docs/examples: maintenance/product choice; no correctness-release necessity. | | [#2435](https://github.com/567-labs/instructor/pull/2435) `bb31451d31df1220509538fbf4e4a01c0d7a79ca` | Deferred providers/auth: scope-triaged, need ownership, SDK/wire contracts and live evidence. | | [#2423](https://github.com/567-labs/instructor/pull/2423) `3b4389f70fdefd30f0be65219d27e981ff4cd98a` | Deferred providers/auth: scope-triaged, need ownership, SDK/wire contracts and live evidence. | | [#2409](https://github.com/567-labs/instructor/pull/2409) `87a9bf8a3a1579b0d394e92226cb315440c79427` | Deferred providers/auth: scope-triaged, need ownership, SDK/wire contracts and live evidence. | | [#2405](https://github.com/567-labs/instructor/pull/2405) `82e90e9bea0da26e20d2d37add94b9cc29b42af7` | Deferred docs/examples: maintenance/product choice; no correctness-release necessity. | | [#2394](https://github.com/567-labs/instructor/pull/2394) `bc55f4f639ad352fd9314b9f6f477971b6ee4e83` | Deferred product/security design: routing and injection-defense guarantees need evaluation/threat model. | | [#2384](https://github.com/567-labs/instructor/pull/2384) `b7371363d705acb8c1cd344efc293cd42369ea69` | Deferred providers/auth: scope-triaged, need ownership, SDK/wire contracts and live evidence. | | [#2357](https://github.com/567-labs/instructor/pull/2357) `182609c2e4789ebb40430ecba3407c27b50ebd52` | Deferred architecture stack: separate migration and release; tests/docs target parent branch. | | [#2356](https://github.com/567-labs/instructor/pull/2356) `913a6053a0047b2c97c07768f9374c8a5243c9a9` | Deferred architecture stack: separate migration and release; tests/docs target parent branch. | | [#2355](https://github.com/567-labs/instructor/pull/2355) `b3c44096ecd5f92619743bf3182ce21a3aef6e1d` | Deferred architecture stack: separate migration and release; tests/docs target parent branch. | | [#2322](https://github.com/567-labs/instructor/pull/2322) `222c4f12430eea028f5895a68c96f15cbcd7513e` | Deferred providers/auth: scope-triaged, need ownership, SDK/wire contracts and live evidence. | | [#2321](https://github.com/567-labs/instructor/pull/2321) `b70f25defed4c8e0927b836fdb9ea01a9b5c1d9f` | Deferred product/security design: routing and injection-defense guarantees need evaluation/threat model. | | [#2311](https://github.com/567-labs/instructor/pull/2311) `d5df24eb3a973a0462c04988a69e05baddd3ad79` | Deferred docs/examples: maintenance/product choice; no correctness-release necessity. | | [#2306](https://github.com/567-labs/instructor/pull/2306) `a960f6462a22a559f05ae14e9159c84e71bae19f` | Deferred providers/auth: scope-triaged, need ownership, SDK/wire contracts and live evidence. | | [#2283](https://github.com/567-labs/instructor/pull/2283) `5bbaa6217e83b5d69d862fd12470aef57a77c5ca` | Deferred providers/auth: scope-triaged, need ownership, SDK/wire contracts and live evidence. | ## All Open Issues - [#2260](https://github.com/567-labs/instructor/issues/2260): #2306 provider ownership needed. - [#2272](https://github.com/567-labs/instructor/issues/2272): no matching PR; benefits unverified. - [#2316](https://github.com/567-labs/instructor/issues/2316): #2321 needs threat model. - [#2383](https://github.com/567-labs/instructor/issues/2383): #2384 broader Azure provider deferred. - [#2393](https://github.com/567-labs/instructor/issues/2393): #2394 routing product choice. - [#2403](https://github.com/567-labs/instructor/issues/2403): memory feature, related #2405 but not duplicate of #2404. - [#2404](https://github.com/567-labs/instructor/issues/2404): #2405 cookbook product choice deferred. - [#2408](https://github.com/567-labs/instructor/issues/2408): #2409 authentication deferred. - [#2603](https://github.com/567-labs/instructor/issues/2603): #2605 does not prove leak fixed; sustained leak not reproduced. - [#2613](https://github.com/567-labs/instructor/issues/2613): #2629 selected, preserve supported schemas/scalars. - [#2631](https://github.com/567-labs/instructor/issues/2631): #2632 selected; #2637/#2639 overlapping. - [#2645](https://github.com/567-labs/instructor/issues/2645): #2646 selected; #2647/#2652/#2704 overlaps. - [#2650](https://github.com/567-labs/instructor/issues/2650): #2651 next batch. - [#2654](https://github.com/567-labs/instructor/issues/2654): #2655 next batch. - [#2659](https://github.com/567-labs/instructor/issues/2659): #2673 selected; #2660/#2680 alternatives. - [#2661](https://github.com/567-labs/instructor/issues/2661): #2662 next batch. - [#2665](https://github.com/567-labs/instructor/issues/2665): #2666 next batch. - [#2669](https://github.com/567-labs/instructor/issues/2669): #2671 deliberate policy deferred. - [#2674](https://github.com/567-labs/instructor/issues/2674): #2675 selected and unified. - [#2676](https://github.com/567-labs/instructor/issues/2676): #2677 next batch. - [#2681](https://github.com/567-labs/instructor/issues/2681): #2686 next batch; forced default remains limitation. - [#2682](https://github.com/567-labs/instructor/issues/2682): #2683 next batch. - [#2684](https://github.com/567-labs/instructor/issues/2684): #2685 blocked on native history. - [#2687](https://github.com/567-labs/instructor/issues/2687): #2688 selected. - [#2694](https://github.com/567-labs/instructor/issues/2694): #2700 policy deferred. - [#2695](https://github.com/567-labs/instructor/issues/2695): #2701 blocked. - [#2696](https://github.com/567-labs/instructor/issues/2696): #2698 selected; #2703 duplicate. - [#2705](https://github.com/567-labs/instructor/issues/2705): new coordinator fix. No superseded item is closed yet: consolidation must receive review first. Use this PR rather than merging overlapping patches separately. Strict-schema #2701 is blocked by recursive $ref overflow and mapping semantics; #2700's EOF buffering is excluded because it breaks streaming. The deferred dependency/provider/architecture groups require separate validation and ownership.
Instructor: Structured Outputs for LLMs
Get reliable JSON from any LLM. Built on Pydantic for validation, type safety, and IDE support.
import instructor
from pydantic import BaseModel
# Define what you want
class User(BaseModel):
name: str
age: int
# Extract it from natural language
client = instructor.from_provider("openai/gpt-4o-mini")
user = client.chat.completions.create(
response_model=User,
messages=[{"role": "user", "content": "John is 25 years old"}],
)
print(user) # User(name='John', age=25)
That's it. No JSON parsing, no error handling, no retries. Just define a model and get structured data.
Use Instructor for fast extraction, reach for PydanticAI when you need agents. Instructor keeps schema-first flows simple and cheap. If your app needs richer agent runs, built-in observability, or shareable traces, try PydanticAI. PydanticAI is the official agent runtime from the Pydantic team, adding typed tools, replayable datasets, evals, and production dashboards while using the same Pydantic models. Dive into the PydanticAI docs to see how it extends Instructor-style workflows.
Why Instructor?
Getting structured data from LLMs is hard. You need to:
- Write complex JSON schemas
- Handle validation errors
- Retry failed extractions
- Parse unstructured responses
- Deal with different provider APIs
Instructor handles all of this with one simple interface:
| Without Instructor | With Instructor |
|
|
Install in seconds
pip install instructor
Or with your package manager:
uv add instructor
poetry add instructor
Works with every major provider
Use the same code with any LLM provider:
# OpenAI
client = instructor.from_provider("openai/gpt-4o")
# Anthropic
client = instructor.from_provider("anthropic/claude-3-5-sonnet")
# Google
client = instructor.from_provider("google/gemini-pro")
# Ollama (local)
client = instructor.from_provider("ollama/llama3.2")
# With API keys directly (no environment variables needed)
client = instructor.from_provider("openai/gpt-4o", api_key="sk-...")
client = instructor.from_provider("anthropic/claude-3-5-sonnet", api_key="sk-ant-...")
client = instructor.from_provider("groq/llama-3.1-8b-instant", api_key="gsk_...")
# All use the same API!
user = client.chat.completions.create(
response_model=User,
messages=[{"role": "user", "content": "..."}],
)
Production-ready features
Automatic retries
Failed validations are automatically retried with the error message:
from pydantic import BaseModel, field_validator
class User(BaseModel):
name: str
age: int
@field_validator('age')
def validate_age(cls, v):
if v < 0:
raise ValueError('Age must be positive')
return v
# Instructor automatically retries when validation fails
user = client.chat.completions.create(
response_model=User,
messages=[{"role": "user", "content": "..."}],
max_retries=3,
)
Streaming support
Stream partial objects as they're generated:
from instructor import Partial
for partial_user in client.chat.completions.create(
response_model=Partial[User],
messages=[{"role": "user", "content": "..."}],
stream=True,
):
print(partial_user)
# User(name=None, age=None)
# User(name="John", age=None)
# User(name="John", age=25)
Nested objects
Extract complex, nested data structures:
from typing import List
class Address(BaseModel):
street: str
city: str
country: str
class User(BaseModel):
name: str
age: int
addresses: List[Address]
# Instructor handles nested objects automatically
user = client.chat.completions.create(
response_model=User,
messages=[{"role": "user", "content": "..."}],
)
Used in production by
Trusted by over 100,000 developers and companies building AI applications:
- 3M+ monthly downloads
- 10K+ GitHub stars
- 1000+ community contributors
Companies using Instructor include teams at OpenAI, Google, Microsoft, AWS, and many YC startups.
Get started
Basic extraction
Extract structured data from any text:
from pydantic import BaseModel
import instructor
client = instructor.from_provider("openai/gpt-4o-mini")
class Product(BaseModel):
name: str
price: float
in_stock: bool
product = client.chat.completions.create(
response_model=Product,
messages=[{"role": "user", "content": "iPhone 15 Pro, $999, available now"}],
)
print(product)
# Product(name='iPhone 15 Pro', price=999.0, in_stock=True)
Multiple languages
Instructor's simple API is available in many languages:
- Python - The original
- TypeScript - Full TypeScript support
- Ruby - Ruby implementation
- Go - Go implementation
- Elixir - Elixir implementation
- Rust - Rust implementation
Learn more
- Documentation - Comprehensive guides
- Examples - Copy-paste recipes
- Blog - Tutorials and best practices
- Discord - Get help from the community
Why use Instructor over alternatives?
vs Raw JSON mode: Instructor provides automatic validation, retries, streaming, and nested object support. No manual schema writing.
vs LangChain/LlamaIndex: Instructor is focused on one thing - structured extraction. It's lighter, faster, and easier to debug.
vs Custom solutions: Battle-tested by thousands of developers. Handles edge cases you haven't thought of yet.
Contributing
We welcome contributions! Check out our good first issues to get started.
License
MIT License - see LICENSE for details.
Built by the Instructor community. Special thanks to Jason Liu and all contributors.