Skip to main content
If your app uses the OpenAI Python SDK, wrap its client once to build a dataset from real traffic. The same client still calls OpenAI directly. Apprentice only records the completed call. The wrapper covers create and parse on both chat.completions and responses. parse is the structured-output helper, and it posts on its own rather than going through create, so it needs wrapping in its own right.

Install

Capture Responses API calls

Capture Chat Completions calls

Both sync OpenAI and async AsyncOpenAI clients work. Each completed call logs its input, text output, model name, latency, and any token counts OpenAI returns to the support-bot task.

It cannot break your app

The capture path is fail-open by contract. If the Apprentice backend is slow, down, or unreachable, your OpenAI call still returns unchanged. The only loss is that one trace. OpenAI errors still reach your code unchanged. Captured traces arrive as raw rows: live, unverified. Verify them to gold, or upload curated rows as silver, before you rely on them for optimization.

Streaming passes through uncaptured

Calls with stream=True return an iterator that Apprentice must not consume. They pass through uncaptured and unchanged. The OpenAI SDK’s responses.stream(...) and chat.completions.stream(...) helpers are left untouched and uncaptured for the same reason.

Redact before anything leaves your process

If your inputs contain sensitive data, pass a redact function. It runs in your process, before the trace is sent:

Next

Once you have traces, optimize the prompt with the JSON extraction guide, or read the capture reference for the manual path.