# OpenAI Agents SDK integration

> For the complete documentation index, see [llms.txt](https://docs.temporal.io/llms.txt).
> Any documentation page is available as raw Markdown by appending `.md` to its URL.

> Run OpenAI Agents SDK agents as durable Temporal Workflows in TypeScript, with model calls executed as Activities.

Temporal's integration with the [OpenAI Agents SDK for JavaScript/TypeScript](https://openai.github.io/openai-agents-js/)
lets you run agents as Temporal Workflows. Agent orchestration—the agent loop, tool selection, and handoffs—runs inside
the Workflow, while model calls run as [Activities](/glossary#activity).

Like with other types of API calls, in a [Temporal Application](/glossary#temporal-application), you make LLM calls in your Activities. This
integration handles that for you: model calls are executed as Activities, so they retry durably and are not repeated
during Workflow replay. Your agents survive Worker restarts and can run for extended periods without losing state.

> **Pre-release**

## Prerequisites

- This guide assumes you are already familiar with the OpenAI Agents SDK. If you aren't, refer to the
  [OpenAI Agents SDK documentation](https://openai.github.io/openai-agents-js/) for more details.
- If you are new to Temporal, we recommend you read the [Understanding Temporal](/evaluate/understanding-temporal)
  document or take the [Temporal 101](https://learn.temporal.io/courses/temporal_101/) course to understand the basics
  of Temporal.
- Ensure you have set up your local development environment by following the
  [Set up your local with the TypeScript SDK](/develop/typescript/set-up-your-local-typescript) guide. When you are
  done, leave the Temporal Development Server running if you want to test your code locally.

## Install

```bash
# Or `pnpm add`/`yarn add`
npm install @temporalio/openai-agents @openai/agents-core @openai/agents-openai openai
```

`@openai/agents-core`, `@openai/agents-openai`, and `openai` are peer dependencies.

### Import paths

Most applications use two import paths: `@temporalio/openai-agents` in Worker and Client code, and
`@temporalio/openai-agents/workflow` in Workflow code. The other subpaths are for tracing setup or manual Worker wiring.

| Import path                                      | Import from      | Use for                                                     |
| :----------------------------------------------- | :--------------- | :---------------------------------------------------------- |
| `@temporalio/openai-agents`                      | Worker or Client | Plugin setup, MCP providers, model option types             |
| `@temporalio/openai-agents/workflow`             | Workflow         | Runner, Workflow-safe tools, sessions, MCP handles          |
| `@temporalio/openai-agents/otel`                 | Worker or Client | Replay-safe OpenTelemetry setup                             |
| `@temporalio/openai-agents/workflow-interceptor` | Worker bundling  | Manual `workflowInterceptorModules` wiring without a plugin |

## Create a Hello World Workflow

A Temporal-backed agent needs three pieces: a Workflow that runs the agent, a Worker configured with the integration
plugin, and a Client configured with the same plugin.

### Write the Workflow

Use `TemporalOpenAIRunner` instead of the upstream `Runner`. The runner runs the agent loop inside the Workflow and
dispatches each model call to an Activity.

<!--SNIPSTART typescript-openai-agents-hello-world-workflow-->
[openai-agents/src/basic/workflows.ts](https://github.com/temporalio/samples-typescript/blob/main/openai-agents/src/basic/workflows.ts)
```ts
export async function helloWorld(prompt: string): Promise<string> {
  const agent = new Agent({ name: 'HelloAgent', instructions: 'You are a helpful assistant.' });
  const result = await new TemporalOpenAIRunner().run(agent, prompt);
  return result.finalOutput ?? '';
}
```
<!--SNIPEND-->

`TemporalOpenAIRunner` mirrors the OpenAI Agents SDK `Runner`, with familiar options such as `maxTurns`, `context`,
and `session`. A few differences apply for Workflow-safe execution:

- `runConfig.model` must be a model name string. The Worker's `modelProvider` resolves it inside the model Activity.
- `signal` is not supported. Use Temporal cancellation APIs, such as `CancellationScope`, to cancel Workflow work.

### Configure the Worker

Register `OpenAIAgentsPlugin` on the Worker. The plugin registers the model Activity, adds the trace-propagation
interceptors, installs the Workflow-bundle polyfills the OpenAI Agents SDK needs, and registers any configured MCP
server providers.

<!--SNIPSTART typescript-openai-agents-hello-world-worker-->
[openai-agents/src/basic/worker.ts](https://github.com/temporalio/samples-typescript/blob/main/openai-agents/src/basic/worker.ts)
```ts
const worker = await Worker.create({
  connection,
  taskQueue: 'openai-agents-basic',
  workflowsPath: require.resolve('./workflows'),
  activities,
  plugins: [
    new OpenAIAgentsPlugin({
      modelProvider: new OpenAIProvider({ apiKey }),
      modelParams: { useLocalActivity: true },
    }),
  ],
  bundlerOptions: {
    webpackConfigHook: (config) => ({
      ...config,
      resolve: {
        ...config.resolve,
        conditionNames: ['require', 'browser', 'default'],
      },
    }),
  },
});
await worker.run();
```
<!--SNIPEND-->

`modelParams` controls scheduling for the model Activity—including `startToCloseTimeout`, `retry`, and
`useLocalActivity`. See `ModelActivityOptions` for the public field list. The Worker above sets
`useLocalActivity: true`, which runs model calls as Local Activities to keep the event history smaller.

You must ensure the Worker process has access to your model-provider credentials. Most provider SDKs read credentials
from environment variables.

### Configure the Client

Register the same plugin type on the Client so model parameters and tracing options propagate to new Workflows. Attach
one `OpenAIAgentsPlugin` instance per Client or Connection configuration.

<!--SNIPSTART typescript-openai-agents-hello-world-client-->
[openai-agents/src/basic/client.ts](https://github.com/temporalio/samples-typescript/blob/main/openai-agents/src/basic/client.ts)
```ts
const connection = await Connection.connect();
const client = new Client({
  connection,
  plugins: [new OpenAIAgentsPlugin({ modelProvider: new OpenAIProvider({ apiKey }) })],
});

const taskQueue = 'openai-agents-basic';
const workflowId = 'openai-agents-' + nanoid();
```
<!--SNIPEND-->

From there, start or execute Workflows as you normally would. The plugin does not change the Client API.

## Tools

Inline function tools, hosted tools, Activity-backed tools, Nexus operation tools, and nested agent tools can all be
used from a Temporal-backed agent. Any tool that performs I/O must run outside the Workflow sandbox, usually through an
Activity or a Nexus Operation.

### Activity-backed tools

Use `activityAsTool` for HTTP calls, database access, file system work, or other I/O. The tool name must match a
registered Activity.

<!--SNIPSTART typescript-openai-agents-activity-tool-workflow-->
[openai-agents/src/basic/workflows.ts](https://github.com/temporalio/samples-typescript/blob/main/openai-agents/src/basic/workflows.ts)
```ts
export async function tools(prompt: string): Promise<string> {
  const weatherTool = activityAsTool<typeof activities.getWeather>(
    {
      name: 'getWeather',
      description: 'Get the current weather for a city.',
      parameters: {
        type: 'object',
        properties: { city: { type: 'string', description: 'The city name' } },
        required: ['city'],
        additionalProperties: false,
      },
    },
    { startToCloseTimeout: '1 minute' },
  );

  const agent = new Agent({
    name: 'WeatherAgent',
    instructions: 'You are a helpful weather assistant. Always use the getWeather tool to answer weather questions.',
    tools: [weatherTool],
  });
  const result = await new TemporalOpenAIRunner().run(agent, prompt);
  return result.finalOutput ?? '';
}
```
<!--SNIPEND-->

That type parameter is only used at compile time. At runtime, the Activity is invoked by name through `proxyActivities`.

### Inline and hosted tools

For deterministic computation, use `tool()` from `@openai/agents-core` directly. Inline tools run in the Workflow
sandbox and must not perform non-deterministic activities like, I/O or reading wall-clock time beyond Temporal's replacements. Hosted tools from `@openai/agents-openai`, such as `webSearchTool()`, run server-side
through the model provider during the model Activity.

<!--SNIPSTART typescript-openai-agents-inline-tool-workflow-->
[openai-agents/src/basic/workflows.ts](https://github.com/temporalio/samples-typescript/blob/main/openai-agents/src/basic/workflows.ts)
```ts
export async function inlineTool(prompt: string): Promise<string> {
  const addTool = tool({
    name: 'add',
    description: 'Add two numbers together.',
    parameters: z.object({ a: z.number().describe('First number'), b: z.number().describe('Second number') }),
    execute: async ({ a, b }) => String(a + b),
  });

  const agent = new Agent({
    name: 'MathAgent',
    instructions: 'You are a math assistant. Use the add tool to compute sums.',
    tools: [addTool],
  });
  const result = await new TemporalOpenAIRunner().run(agent, prompt);
  return result.finalOutput ?? '';
}
```
<!--SNIPEND-->

A hosted tool is declared the same way, and the model provider runs it during the model Activity:

<!--SNIPSTART typescript-openai-agents-hosted-tool-workflow-->
[openai-agents/src/tools/workflows.ts](https://github.com/temporalio/samples-typescript/blob/main/openai-agents/src/tools/workflows.ts)
```ts
export async function webSearch(prompt: string): Promise<string> {
  const agent = new Agent({
    name: 'WebSearchAgent',
    instructions: 'Use the web search tool to find current information, then answer concisely.',
    tools: [webSearchTool()],
  });
  const result = await new TemporalOpenAIRunner().run(agent, prompt);
  return result.finalOutput ?? '';
}
```
<!--SNIPEND-->

### Nexus operation tools

Use `nexusOperationAsTool` to expose a [Nexus](/nexus) Operation as an agent tool. The Workflow
starts the Operation through a Nexus client and feeds the stringified result back to the agent.

Define the service and its Operations:

<!--SNIPSTART typescript-openai-agents-nexus-tools-api-->
[openai-agents/src/nexus-tools/api.ts](https://github.com/temporalio/samples-typescript/blob/main/openai-agents/src/nexus-tools/api.ts)
```ts
export interface GetWeatherInput {
  city: string;
}

export interface GetWeatherOutput {
  city: string;
  temperatureC: number;
  conditions: string;
}

export const weatherService = nexus.service('weather', {
  getWeather: nexus.operation<GetWeatherInput, GetWeatherOutput>(),
});
```
<!--SNIPEND-->

Then turn the Operation into a tool:

<!--SNIPSTART typescript-openai-agents-nexus-tool-workflow-->
[openai-agents/src/nexus-tools/workflows.ts](https://github.com/temporalio/samples-typescript/blob/main/openai-agents/src/nexus-tools/workflows.ts)
```ts
export async function nexusToolWorkflow(prompt: string): Promise<string> {
  const weatherTool = nexusOperationAsTool(
    weatherService.operations.getWeather,
    {
      name: 'getWeather',
      description: 'Get the current weather for a city.',
      parameters: {
        type: 'object',
        properties: { city: { type: 'string', description: 'The city name' } },
        required: ['city'],
        additionalProperties: false,
      },
    },
    { service: weatherService, endpoint: WEATHER_ENDPOINT, scheduleToCloseTimeout: '1 minute' },
  );

  const agent = new Agent({
    name: 'WeatherAgent',
    instructions: 'You are a weather assistant. Always use the getWeather tool to answer weather questions.',
    tools: [weatherTool],
  });

  const result = await new TemporalOpenAIRunner().run(agent, prompt);
  return result.finalOutput ?? '';
}
```
<!--SNIPEND-->

### Nested agent tools

Use `agentAsTool` to expose another `Agent` as a tool while keeping nested model calls durable:

<!--SNIPSTART typescript-openai-agents-agent-as-tool-workflow-->
[openai-agents/src/agent-patterns/workflows.ts](https://github.com/temporalio/samples-typescript/blob/main/openai-agents/src/agent-patterns/workflows.ts)
```ts
export async function agentsAsTools(prompt: string): Promise<string> {
  const specialistAgent = new Agent({
    name: 'SpecialistAgent',
    instructions: 'You are a specialist. Answer questions concisely.',
  });

  const specialistTool = agentAsTool(specialistAgent, {
    toolName: 'ask_specialist',
    toolDescription: 'Ask the specialist agent a question and get a concise answer.',
  });

  const orchestratorAgent = new Agent({
    name: 'OrchestratorAgent',
    instructions:
      'You orchestrate tasks. Use the ask_specialist tool to get answers, then synthesize a final response.',
    tools: [specialistTool],
  });

  const runner = new TemporalOpenAIRunner();
  const result = await runner.run(orchestratorAgent, prompt);
  return result.finalOutput ?? '';
}
```
<!--SNIPEND-->

Nested approval interruptions are not supported. If a nested run pauses for approval, the tool invocation fails with an
`ApplicationFailure` of type `NestedAgentInterruption`.

## MCP servers

The integration supports stateless and stateful [Model Context Protocol (MCP)](https://modelcontextprotocol.io/)
servers.

Register a provider for each server on the Worker. Both kinds go in the same `mcpServerProviders` list; a stateful
provider additionally takes the `NativeConnection` it should run its dedicated Worker on.

<!--SNIPSTART typescript-openai-agents-mcp-worker-->
[openai-agents/src/mcp/worker.ts](https://github.com/temporalio/samples-typescript/blob/main/openai-agents/src/mcp/worker.ts)
```ts
// A stateless provider reconnects per operation, so each tool call stands alone.
const statelessProviders = [
  new StatelessMCPServerProvider(
    'filesystem',
    () =>
      new MCPServerStdio({
        command: 'npx',
        args: ['ts-node', filesystemServerPath],
        name: 'filesystem',
      }),
  ),
  new StatelessMCPServerProvider(
    'streamableHttp',
    () => new MCPServerStreamableHttp({ url: toolsHttp.url, name: 'streamableHttp' }),
  ),
  new StatelessMCPServerProvider('sse', () => new MCPServerSSE({ url: toolsSse.url, name: 'sse' })),
];

// A stateful provider also takes the connection, which the plugin uses to run a
// dedicated Worker holding the MCP session open for the life of the Workflow run.
const statefulProviders = [new StatefulMCPServerProvider('memory', () => createNotesServer(), connection)];

const worker = await Worker.create({
  connection,
  taskQueue: 'openai-agents-mcp',
  workflowsPath: require.resolve('./workflows'),
  activities,
  plugins: [
    new OpenAIAgentsPlugin({
      modelProvider: new OpenAIProvider({ apiKey }),
      modelParams: { useLocalActivity: true },
      mcpServerProviders: [...statelessProviders, ...statefulProviders],
    }),
  ],
```
<!--SNIPEND-->

### Stateless MCP servers

Use stateless servers when each tool call is independent. Reference the provider name from Workflow code with
`statelessMcpServer`:

<!--SNIPSTART typescript-openai-agents-stateless-mcp-workflow-->
[openai-agents/src/mcp/workflows.ts](https://github.com/temporalio/samples-typescript/blob/main/openai-agents/src/mcp/workflows.ts)
```ts
export async function filesystem(prompt: string): Promise<string> {
  const agent = new Agent({
    name: 'FilesystemAgent',
    instructions: 'You are a helpful assistant with access to a filesystem.',
    mcpServers: [statelessMcpServer('filesystem')],
  });
  const result = await new TemporalOpenAIRunner().run(agent, prompt);
  return result.finalOutput ?? '';
}
```
<!--SNIPEND-->

### Stateful MCP servers

Use stateful servers when a persistent connection or session is required. The plugin starts a dedicated in-process
Worker pinned to a per-run Task Queue and routes MCP operations to it.

In the Workflow, call `connect()` before use and `cleanup()` in a `finally` block:

<!--SNIPSTART typescript-openai-agents-stateful-mcp-workflow-->
[openai-agents/src/mcp/workflows.ts](https://github.com/temporalio/samples-typescript/blob/main/openai-agents/src/mcp/workflows.ts)
```ts
export async function statefulMemory(prompt: string): Promise<string> {
  const server = statefulMcpServer('memory');
  await server.connect();
  try {
    const agent = new Agent({
      name: 'MemoryAgent',
      instructions: 'You are a helpful assistant with access to a persistent notes store.',
      mcpServers: [server],
    });
    const result = await new TemporalOpenAIRunner().run(agent, prompt);
    return result.finalOutput ?? '';
  } finally {
    await server.cleanup();
  }
}
```
<!--SNIPEND-->

Dedicated Worker startup and heartbeat failures surface as an `ApplicationFailure` whose type is exported as
`DEDICATED_WORKER_FAILURE_TYPE`.

## Sessions and human-in-the-loop

Because the agent loop runs inside a Workflow, conversation history and pending approvals must be replay safe.

### Replay-safe sessions

Use `WorkflowSafeMemorySession` for conversation history. It replaces the upstream `MemorySession`, which is not replay
safe because it depends on host process state.

<!--SNIPSTART typescript-openai-agents-session-workflow-->
[openai-agents/src/sessions/workflows.ts](https://github.com/temporalio/samples-typescript/blob/main/openai-agents/src/sessions/workflows.ts)
```ts
export async function multiTurnChat(prompts: string[]): Promise<string[]> {
  const agent = new Agent({ name: 'ChatAgent', instructions: 'You are a helpful assistant.' });
  const session = new WorkflowSafeMemorySession();
  const runner = new TemporalOpenAIRunner();
  const replies: string[] = [];
  for (const prompt of prompts) {
    const result = await runner.run(agent, prompt, { session });
    replies.push(result.finalOutput ?? '');
  }
  return replies;
}
```
<!--SNIPEND-->

Session history lives on the Workflow heap and is rebuilt by replay within a single run. It does **not** automatically
survive `continueAsNew`—a continued run starts with an empty session. To carry history across a Continue-As-New
boundary, capture the items and re-seed the new run's session through the constructor's `initialItems`:

<!--SNIPSTART typescript-openai-agents-session-carryover-workflow-->
[openai-agents/src/sessions/workflows.ts](https://github.com/temporalio/samples-typescript/blob/main/openai-agents/src/sessions/workflows.ts)
```ts
export async function carryoverChat(input: CarryoverChatInput): Promise<string[] | void> {
  const agent = new Agent({ name: 'ChatAgent', instructions: 'You are a helpful assistant.' });
  const session = new WorkflowSafeMemorySession({ initialItems: input.initialItems });
  const runner = new TemporalOpenAIRunner();
  const accumulated = input.accumulated ?? [];

  const [prompt, ...remaining] = input.prompts;
  if (prompt === undefined) {
    return accumulated;
  }

  const result = await runner.run(agent, prompt, { session });
  accumulated.push(result.finalOutput ?? '');

  if (remaining.length === 0) {
    return accumulated;
  }

  const items = await session.getItems();
  await continueAsNew<typeof carryoverChat>({
    prompts: remaining,
    initialItems: items,
    accumulated,
  });
}
```
<!--SNIPEND-->

### Run state and approvals

`TemporalOpenAIRunner.run` accepts a `RunState` as its second argument, matching the upstream runner. This supports
human-approval flows that pause, wait for a Signal or Update, then Continue-As-New for as long as the approval
takes.

<!--SNIPSTART typescript-openai-agents-approval-workflow-->
[openai-agents/src/human-approval/workflows.ts](https://github.com/temporalio/samples-typescript/blob/main/openai-agents/src/human-approval/workflows.ts)
```ts
export async function approvalWorkflow(input: ApprovalInput = {}): Promise<string> {
  const action = tool({
    name: 'dangerousAction',
    description: 'Performs a dangerous action that requires human approval before execution.',
    parameters: {
      type: 'object',
      properties: {
        reason: { type: 'string', description: 'The reason for performing the dangerous action.' },
      },
      required: ['reason'],
      additionalProperties: false,
    } as const,
    needsApproval: true,
    execute: async (args) => `did: ${(args as { reason: string }).reason}`,
  });

  const agent = new Agent({
    name: 'Approver',
    instructions: "You carry out the user's request using the dangerousAction tool.",
    tools: [action],
    modelSettings: { toolChoice: 'required' },
  });

  const runner = new TemporalOpenAIRunner();

  if (input.resumeFromRunState !== undefined) {
    const state = await RunState.fromString(agent, input.resumeFromRunState);
    for (const interruption of state.getInterruptions()) {
      state.approve(interruption);
    }
    const resumed = await runner.run(agent, state);
    return resumed.finalOutput ?? '';
  }

  let approved = false;
  setHandler(approveSignal, () => {
    approved = true;
  });

  const result = await runner.run(agent, 'Delete the old backup files.');

  if (result.interruptions.length === 0) {
    return result.finalOutput ?? '';
  }

  await condition(() => approved);
  await continueAsNew<typeof approvalWorkflow>({ resumeFromRunState: result.state.toString() });
  throw new Error('unreachable');
}
```
<!--SNIPEND-->

The agent passed to `RunState.fromString` must define the same tool names, handoff graph, and MCP servers as the run
that produced the serialized state.

## Streaming

`run` supports streaming with `{ stream: true }`. The streaming model Activity publishes each model event to a [Workflow Stream](/workflow-streams) topic as the model produces it, so an external client can observe a run live while it stays durable. Streaming is experimental.

Set the topic name in `modelParams.streamingTopic` on the Client's `OpenAIAgentsPlugin`, not the Worker's; `run` fails with a `StreamingTopicNotConfigured` error if no topic is configured.

Streaming requires the `@temporalio/workflow-streams` package:

<!--SNIPSTART typescript-openai-agents-streaming-workflow -->
[openai-agents/src/streaming/workflows.ts](https://github.com/temporalio/samples-typescript/blob/main/openai-agents/src/streaming/workflows.ts)
```ts
import { Agent } from '@openai/agents-core';
import { TemporalOpenAIRunner } from '@temporalio/openai-agents/workflow';
import { WorkflowStream } from '@temporalio/workflow-streams/workflow';
import { condition, defineSignal, setHandler } from '@temporalio/workflow';

export const streamingTopic = 'model-stream';

export const consumerDoneSignal = defineSignal('consumer-done');

export async function streamingChat(prompt: string): Promise<string> {
  new WorkflowStream();

  let consumerDone = false;
  setHandler(consumerDoneSignal, () => {
    consumerDone = true;
  });

  const agent = new Agent({ name: 'StreamingAgent', instructions: 'You are a helpful assistant.' });
  const result = await new TemporalOpenAIRunner().run(agent, prompt, { stream: true });
  // The external client is the event consumer; the Workflow only drives the run to completion.
  for await (const _event of result);
  await result.completed;
  // Completing discards the stream log, racing a subscriber's final poll; the timeout covers no subscriber.
  await condition(() => consumerDone, '10 seconds');
  return result.finalOutput ?? '';
}
```
<!--SNIPEND-->

Streaming from within the Workflow is replay-safe. Subscribe from an external client with `WorkflowStreamClient` from `@temporalio/workflow-streams/client`; see the [`@temporalio/workflow-streams`](https://github.com/temporalio/sdk-typescript/tree/main/contrib/workflow-streams) docs for the subscriber API.

## Tracing

OpenAI Agents SDK tracing works across Client, Workflow, Activity, Nexus, and MCP boundaries.

### OpenAI hosted traces

Enable the upstream hosted exporter before constructing the plugin, in the Worker process (not inside Workflow code):

```typescript
import { OpenAITracingExporter } from '@openai/agents-openai';
import { addTraceProcessor, BatchTraceProcessor } from '@openai/agents-core';

addTraceProcessor(new BatchTraceProcessor(new OpenAITracingExporter()));
```

> **⚠️ Warning:**
>
> We don't recommend calling `setDefaultOpenAITracingExporter()`. If you do need to call it, be aware that it overwrites
> internal state on any `OpenAIAgentsPlugin` instances you've already constructed. Set up hosted tracing with
> `addTraceProcessor` instead, as shown above.
>

### OpenTelemetry

If you already collect traces with OpenTelemetry, the integration can emit the agent's spans through your OpenTelemetry
pipeline. Model calls, tools, and orchestration then land in the same backend as the rest of your application's traces,
instead of living only in the OpenAI dashboard.

To turn this on, install the optional `@opentelemetry/sdk-trace-base` peer dependency:

```bash
# Or `pnpm add`/`yarn add`
npm install @opentelemetry/sdk-trace-base
```

Then register the tracer provider and enable OpenTelemetry instrumentation in the plugin options:

```typescript
import { trace } from '@opentelemetry/api';
import { createTracerProvider } from '@temporalio/openai-agents/otel';

// NOTE: TracerProvider must be declared before plugin creation
trace.setGlobalTracerProvider(createTracerProvider());
```

Then set `useOtelInstrumentation` in the plugin's `interceptorOptions`:

<!--SNIPSTART typescript-openai-agents-tracing-worker-->
[openai-agents/src/tracing/worker.ts](https://github.com/temporalio/samples-typescript/blob/main/openai-agents/src/tracing/worker.ts)
```ts
plugins: [
  new OpenAIAgentsPlugin({
    modelProvider: new OpenAIProvider({ apiKey }),
    modelParams: { useLocalActivity: true },
    interceptorOptions: { useOtelInstrumentation, addTemporalSpans: true },
  }),
],
```
<!--SNIPEND-->

If you need a different provider class, configure it with `TemporalIdGenerator` and mark it with
`markReplaySafeTracerProvider` before registering it.

### Temporal orchestration spans

Set `addTemporalSpans: true` to emit `temporal:*` agent-SDK spans for orchestration operations such as Workflow starts,
Signals, Queries, Updates, Activities, child Workflows, Nexus Operations, and Continue-As-New. It sits alongside
`useOtelInstrumentation` in `interceptorOptions`, as shown in the Worker above.

These are agent-SDK spans, so they reach the hosted OpenAI dashboard, custom `TracingProcessor`s, and OpenTelemetry when
enabled.

## Resources

- [OpenAI Agents SDK samples](https://github.com/temporalio/samples-typescript/tree/main/openai-agents) — runnable
  examples for the patterns in this guide.
- [`@temporalio/openai-agents` README](https://github.com/temporalio/sdk-typescript/blob/main/contrib/openai-agents/README.md)
  — the full plugin reference, including pre-built Workflow bundles and the complete feature-support matrix.
- [OpenAI Agents SDK for JavaScript/TypeScript](https://openai.github.io/openai-agents-js/)
- [Temporal Plugins guide](/develop/plugins-guide) — the Plugin system this integration is built on, which you can also
  use to build your own integrations.
