Skip to main content
Mortem wraps the OpenAI client structurally, patching chat.completions.create at runtime. It does not import the openai package itself, so the wrapper works with any version of the SDK and adds no extra dependency to your agent.

What gets captured

For each call to chat.completions.create, Mortem records an llm_call event containing:
  • Prompts — the full message array passed to the model
  • Completion — the assistant message content returned
  • Model — the model string from the request parameters
  • Token usageprompt_tokens, completion_tokens, and total_tokens from the response
  • Cost estimate — calculated from token counts and recorded on the event
  • Finish reasonstop, length, tool_calls, or any other finish reason the model returns
  • Tool calls — structured tool call arguments when the model uses function calling
Both standard (non-streaming) and streaming responses are captured. For streaming, Mortem accumulates content deltas as they arrive and records the assembled completion when the stream ends.

Prerequisites

Install the SDK and create an agent in the dashboard before continuing. You need MORTEM_API_KEY and MORTEM_AGENT_ID set in your environment.

Integration

1

Initialize the Mortem client

Create a Mortem instance at module scope. This is typically done once at the start of your agent process.
verifyToken is only needed during your first deployment. Once the dashboard shows the agent as verified, remove MORTEM_VERIFY_TOKEN from your environment and code.
2

Wrap the OpenAI client

Pass your OpenAI client instance to mortem.wrapOpenAI. The wrapper patches chat.completions.create in place and returns the same client reference. All subsequent calls on the wrapped client are automatically traced.
You can replace the original variable if you want tracing for every call in the module:
3

Start a session and run the agent

Create a session with mortem.startSession, then run your agent logic inside session.run. All chat.completions.create calls made through the wrapped client inside the callback are automatically associated with this trace.
Always call mortem.close() in a finally block. It flushes the trace buffer and ensures all events reach the ingest service before the process exits.

Complete example

Streaming

When you pass stream: true to chat.completions.create, the wrapper detects the async-iterable response and taps it with a generator that accumulates content deltas. The llm_call event is completed with the assembled text once the stream is exhausted.
No additional configuration is needed — the same wrapped client handles both streaming and non-streaming calls.

Function calling

When the model returns tool calls, Mortem captures each tool call block under the output.toolCalls field of the llm_call event. Each entry includes the tool call ID, function name, and raw arguments string as returned by the API.
If you want to trace the execution of tool functions themselves — not just the model’s decision to call them — add a tool_call event with session.beginEvent("tool_call", payload) around your tool handler, or use the Vercel AI SDK wrapper which instruments tool execution automatically.