Skip to main content
Bitfab records calls to Jev, TypeSafe’s System One model, the way it records BAML calls: the model, provider, token counts, and duration land in the span the call belongs to, with no manual addContext calls. Under an opt-out trace root, Jev calls are recorded on their own, whichever client makes them (see below). Anywhere else, wrap the function that calls Jev with wrapJev / wrap_jev / WrapJev.

Supported Languages

Under a trace root, Bitfab recognizes a Jev call by the method’s name and the reply’s shape, so it works with TypeSafe’s official clients (@typesafe-ai/sdk, typesafe-sdk), third-party clients, and your own.

What Gets Captured

Each call adds one entry to the span’s contexts, read from the reply Jev returns ({ model, answers, usage: { input_tokens, output_tokens } }): A call that fails passes its error through unchanged and records nothing.

Under a trace root (opt-out tracing)

Beneath a withTrace() / trace() / bitfab_trace / Client.Trace root, Jev calls are recorded without a wrapper. A call to a method named systemOne (Python and Ruby: system_one, Go: SystemOne) becomes its own llm span, named after the client and method the way other recorded calls are (for example TypeSafeClient.systemOne). When the reply looks like Jev’s, with a text model and a usage object, the span carries the fields above. Any other reply leaves the span without them.
  • TypeScript needs the SDK’s build transform in the server build, the same requirement as the rest of opt-out tracing. The transform rewrites x.systemOne(...) calls in your own files, including optional chaining, so it works in bundled apps (Next.js with Turbopack, for example) with nothing extra to import. The call still returns the client’s own result, so @typesafe-ai/sdk’s .withResponse() keeps working. A method taken out first (const ask = jev.systemOne.bind(jev)) is not recognized; wrap it with wrapJev instead.
  • Python needs Python 3.12+, as opt-out tracing does. Your own system_one functions are recorded, and the official typesafe_sdk clients are recorded whether they are imported before or after the root starts.
  • Ruby needs Ruby 3.4+, as opt-out tracing does. system_one is recorded in your own code and in gems; other methods in those gems stay unrecorded.
  • Go needs bitfab-instrument, as opt-out tracing does. It rewrites x.SystemOne(ctx, ...) calls whose method takes a context.Context first and returns (reply, error), including clients from other packages and calls through an interface. A method value taken first (ask := c.SystemOne) is not recognized; wrap it with bitfab.WrapJev instead.
  • exclude matches the method name (systemOne / system_one / SystemOne). Excluding it runs the call without recording it. Replay mocking follows the root’s mockOnReplay / mock_on_replay default.
  • Usage is recorded once. A wrapper around a recorded call adds nothing, and when one systemOne calls another (your own client calling TypeSafe’s, say), the usage lands on the inner call.
  • node() / bitfab_node / Node on the method configures that call’s one span (Python, Ruby, Go): its name, replay mocking, and other options. Its type stays llm unless the node sets one. In TypeScript, withNode does not reach a recognized Jev call: the call’s span keeps its own name and settings.
  • Outside a trace root, calls run exactly as before and record nothing.

Wrapping a Jev call

wrapJev / wrap_jev / WrapJev wraps any function that calls Jev and returns its reply: the official client’s systemOne / system_one, or your own function that sends the request and returns the JSON body. Like wrapBAML, it opens no span of its own. It writes into the span that is current when the call starts, so call it inside a traced function.

Signatures

TypeScript
  • method must be a named function (bind the client’s method: jev.systemOne.bind(jev)).
  • options.onReply?: (reply) => void is called with each reply after it is recorded.
Python
  • fn may be sync or async and must have a name. The reply may be a dict or an object with model and usage attributes, such as the official client’s SystemOneResponse.
Ruby
  • Pass a callable or a block, not both. The reply may be a Hash with string or symbol keys, or an object that responds to model and usage.
Go
  • The span is the one current in the ctx passed to the call. The reply may be a struct with json tags, a pointer to one, a map[string]any, a json.RawMessage, or a []byte or string holding the JSON body.