项目文件夹

0
Jason Liu 035c77b7b0 feat(release): consolidate reviewed Instructor 1.18 changes (#2708)
## 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.
2026-10-10 14:48:08 -07:00
2023-12-09 16:09:14 -05:00
2024-02-18 11:50:45 -05:00
2023-06-14 19:42:23 +09:00

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.

PyPI Downloads GitHub Stars Discord Twitter

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:

  1. Write complex JSON schemas
  2. Handle validation errors
  3. Retry failed extractions
  4. Parse unstructured responses
  5. Deal with different provider APIs

Instructor handles all of this with one simple interface:

Without Instructor With Instructor
response = openai.chat.completions.create(
    model="gpt-5.4-mini",
    messages=[{"role": "user", "content": "..."}],
    tools=[
        {
            "type": "function",
            "function": {
                "name": "extract_user",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "name": {"type": "string"},
                        "age": {"type": "integer"},
                    },
                },
            },
        }
    ],
)

# Parse response
tool_call = response.choices[0].message.tool_calls[0]
user_data = json.loads(tool_call.function.arguments)

# Validate manually
if "name" not in user_data:
    # Handle error...
    pass
client = instructor.from_provider("openai/gpt-5.4-mini")

user = client.chat.completions.create(
    response_model=User,
    messages=[{"role": "user", "content": "..."}],
)

# That's it! user is validated and typed

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

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.