Code architecture
Target: small core, provider adapters at edges.
File layout
src/
root.zig public package exports
client.zig common client and stable resource handles
decisions.zig typed questions and decision validation
request_options.zig body, header, and query merging
transport.zig shared HTTP transport
core/
mod.zig core re-exports + tests
types.zig shared public structs: Usage, Completion, StructuredSchema, Hooks
options.zig Options + schema profile defaults
session.zig Session arena owner + session() helper
create.zig createWithArena/createDetailedWithArena parse/retry loop
util.zig tiny comptime helpers
providers/
mod.zig provider re-exports
openai.zig OpenAI-compatible provider adapter backed by openai.zig SDK
anthropic.zig Anthropic Messages adapter
system_one.zig TypeSafe-compatible Decisions translation
testing.zig fake provider for core tests/examplesBoundaries
Core owns orchestration
Core does:
- build schema for
T - call provider
- parse JSON into caller/session arena
- validate parsed values with
jsonschema.validateValue - retry parse or validation failures
- accumulate usage
- emit hooks
- retain per-call text/raw response for detailed results
Core does not:
- know provider request internals
- implement full JSON Schema validation itself
- own HTTP details
- store provider-specific data
Session owns result lifetime
Session owns arena for returned values. session.create(T, req, .{}) returns T directly. session.createDetailed(T, req, .{}) returns value plus response text, raw response, and per-call usage. Returned values and detailed response slices die at session.deinit() or session.reset().
Provider owns transport + retry mutation
Provider adapter implements:
completeStructured(...)
appendRetry(...)Provider decides:
- HTTP endpoint
- authentication headers and request-header merging
- OpenAI-compatible URL override
- request JSON shape
- output text extraction
- provider error diagnostics
- retry message append format
appendRetry receives borrowed slices. Provider adapters must copy retry data if they retain it after returning.
Providers may expose diagnostics with:
pub fn diagnostic(self: *const Provider) instructor.Diagnostic;Core helpers instructor.writeError(writer, err, provider) and instructor.printError(err, provider) print provider status/body when available.
Public imports
Users should import only package root:
const instructor = @import("instructor");Then use:
var client = instructor.OpenAI.init(...);
var session = instructor.session(gpa, &client);
const value = try session.create(MyType, req, .{});Internal modules stay available for maintainers but not needed by app users.