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 awithTrace() / 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 withwrapJevinstead. - Python needs Python 3.12+, as opt-out tracing does. Your own
system_onefunctions are recorded, and the officialtypesafe_sdkclients are recorded whether they are imported before or after the root starts. - Ruby needs Ruby 3.4+, as opt-out tracing does.
system_oneis 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 rewritesx.SystemOne(ctx, ...)calls whose method takes acontext.Contextfirst 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 withbitfab.WrapJevinstead. excludematches the method name (systemOne/system_one/SystemOne). Excluding it runs the call without recording it. Replay mocking follows the root’smockOnReplay/mock_on_replaydefault.- Usage is recorded once. A wrapper around a recorded call adds nothing, and when one
systemOnecalls another (your own client calling TypeSafe’s, say), the usage lands on the inner call. node()/bitfab_node/Nodeon the method configures that call’s one span (Python, Ruby, Go): its name, replay mocking, and other options. Its type staysllmunless the node sets one. In TypeScript,withNodedoes 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
methodmust be a named function (bind the client’s method:jev.systemOne.bind(jev)).options.onReply?: (reply) => voidis called with each reply after it is recorded.
Python
fnmay be sync or async and must have a name. The reply may be a dict or an object withmodelandusageattributes, such as the official client’sSystemOneResponse.
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
modelandusage.
Go
- The span is the one current in the
ctxpassed to the call. The reply may be a struct withjsontags, a pointer to one, amap[string]any, ajson.RawMessage, or a[]byteorstringholding the JSON body.