Skip to main content
Generate business models, scoped IDs, collection and relationship descriptors, operations, functions, and declared questions from the same public contract used by the TypeScript SDK. Application developers install the generated package and supply business credentials at runtime. Importing it performs no network I/O.

Generate a package

Copy exact resource references from bijection discover --format json into bijection.sdk.json. Select the endpoints of each relationship and the target collection of each object-bound operation.
Each language target is optional. The Python distribution name and import module are separate; the module is one lowercase Python identifier. Generated names use snake case for attributes and PascalCase for models. Ambiguous normalization is refused. Python 3.12 or later is required.
Generation captures public metadata once at a fixed timestamp. The adjacent bijection.sdk.lock.json contains the selected contract and exact runtime pins. The executable digest is independent of target languages, package names and versions. Commit the config, lock and generated sources. The package contains py.typed, contract.json, selected resource documentation and sync/async examples. It pins the Python runtime and includes its async and observation dependencies. Generation and building never publish a distribution.
Frozen generation is offline and rejects changed resource or language selections. Diff reports executable and documentation changes and contracts that cannot generate supported bindings. Outputs must be disjoint and owned by the generator; unrelated files and symlinks are refused. Review drift, choose package versions and regenerate without --frozen. --python-runtime-version overrides the CLI’s Python compatibility pin when testing a specific runtime release.

Typed business objects and composition

The names below illustrate a selected order/customer ontology. Read the generated models.py, docs/index.md and examples/usage.py for your actual contract.
Expressions are immutable and lazy. Filters capture arguments when constructed. Use & and | for conjunction and disjunction; Python and/or are refused. Disjunction lowers to a union and requires admitted object identity. Object sets support union, intersect and subtract within the same workspace and collection. Relationships are generated only for selected edges and check both endpoints. Unkeyed remote rowsets expose row composition without identity navigation. Selected results are typed tuples; grouped rows have typed keys and metrics tuples. Optional selected values and keys include Missing in their types. They lose object navigation. Use order_results(0, descending=True) after projection or grouping to order by result column position (keys precede metrics). A named generated result model can be selected with as_model(ModelType); its schema must match the prepared result, including when there are no rows. Numeric, integer, decimal and nullable descriptors expose their supported measures. Native admission remains authoritative about available operators, ordering, index access and compute execution. Models are frozen dataclasses. Omitted or undisclosed properties are MISSING; explicit null is None. Check absence by identity. Exact integers decode as Int64; plain Python integers are schema-encoded for bigint arguments. Bytes, special floating-point values, signed zero, scoped IDs and semantic constraints retain their native meanings. Root and component IDs have different generated types. A selected ID domain does not automatically expose a collection reader.

Reads, continuation and diagnostics

describe() reports preparation, bounds, input digest and execution support. explain() obtains the existing planner’s explanation. A native read() must return a complete bounded result; it never silently executes external work. Use explicit run() for retained or external execution. Collection and composition page() return rows, basis, binding, next_cursor and end. Continuations retain the original selection, native position, caller and read timestamp. Contract drift, expired history or changed authority produce errors; the SDK does not restart at latest. Relationship pages retain target identities even when their document is unavailable.
Composition pages slice a complete bounded native result at its original basis; they do not turn a bounded read into an unbounded scan. Structured ReadError values carry code, step, recovery and native data when available. Regenerate on contract mismatch and explicitly restart when history has expired.

Retained requests and durable recovery

execution passes an explicit existing executor selection to native admission. Bijection continues to use external compute. ReadRequirement exposes observed, fixed and snapshot consistency. A held answer can supply from_answer for a compatible subsequent request in the same workspace. No answer grants new access. Requests expose status, result, cancel and close. collect(max_rows=...) requires an explicit materialization bound. Pages verify immutable answer coordinates, schemas and row counts. Context managers release request ownership on exit. Closing marks a handle inactive immediately; an uncertain remote close remains in the journal for retry. Native retention bounds still apply. The journal stores immutable original inputs and request identities before submission, including the prepared input digest. It stores no credentials. After a process restart, resume(id) inspects the captured request and retry(id) replays its exact original submission. A pending close replays only close. recoverable() lists retained identities. Dynamic resume returns a generic handle; generated question submissions retain their named output types. Local timeouts detach the caller and keep the journal so an uncertain submission can be recovered. Explicitly close or cancel work that should no longer be retained. Ordinary generated functions validate declared inputs and results. Operations capture typed arguments and retain the original request for preview, recovery, proposal review, approval and invocation. Invoke recovery runs before dispatch and a lost response does not authorize a new business request. Generated questions return named outputs with typed table or singleton access. captured_operation.propose() returns a protected Proposal with the exact native reference and preview. An authorized independent reviewer can pass that reference to the generated operation’s review, approve or revoke methods. Invocation with proposal=proposal binds the saved proposal to the original request. Captured operations also retain the native deployment, incarnation and request owner; recovery refuses substitution of that lifetime.

Asynchronous applications and subscriptions

The async transport uses asynchronous HTTP I/O and shares protocol effects and decoders with the sync client. Arguments are captured before awaiting. Async request cleanup is shielded from task cancellation; unresolved remote cleanup remains recoverable. query.watch(callback) returns an owned native WebSocket subscription for compositions admitting native dependency observation. Callbacks receive typed QueryObservation values: loading, ready, reconnecting or unavailable. Only ready has a current result. Reconnect clears prior values and waits for a fresh native transition; permission failures also clear values. Sync observations close with close() or a context manager; async observations use await close() or async with. Closing the workspace closes its observations. Retained execution is not emulated by polling a live query.

Arrow, DataFrames and external compute

Install the generated package’s tabular extra to add Arrow and pandas.
Conversions require an explicit native row schema. They preserve exact integer columns and record schema, component scope and absence policy in metadata. The default missing="preserve" adds presence information, including nested objects; missing="null" explicitly collapses absence and null, and missing="error" refuses omitted properties. Heterogeneous or undeclared representations refuse conversion. Decimal strings remain exact strings rather than inferred floats. Retained tables provide bounded arrow_batches(batch_rows=...) and dataframe(max_rows=...). Generated dataset/artifact reference types reuse bijection_compute.references. computation_reference(value, expected_schema) validates the declared native reference; the external compute host still admits and opens it. An Arrow table or DataFrame is local data and does not create a native dataset reference or compute authority.