Skip to content

feat(openai-agents): add @temporalio/openai-agents package#2024

Open
xumaple wants to merge 9 commits into
mainfrom
maplexu/openai-agents-plugin
Open

feat(openai-agents): add @temporalio/openai-agents package#2024
xumaple wants to merge 9 commits into
mainfrom
maplexu/openai-agents-plugin

Conversation

@xumaple
Copy link
Copy Markdown

@xumaple xumaple commented Apr 24, 2026

Summary

Adds @temporalio/openai-agents, a Temporal plugin that runs OpenAI Agents SDK agents as durable workflows. The agent loop (model reasoning, tool dispatch, handoffs) executes deterministically inside the workflow sandbox; each model invocation is dispatched to a Temporal activity where the real ModelProvider lives.

API

// Workflow side — from '@temporalio/openai-agents/workflow'
import '@temporalio/openai-agents/load-polyfills'; // first import in any workflow file
import { TemporalOpenAIRunner, activityAsTool, statelessMcpServer, statefulMcpServer } from '@temporalio/openai-agents/workflow';

const result = await new TemporalOpenAIRunner().run(agent, input);

// Worker side — from '@temporalio/openai-agents'
new OpenAIAgentsPlugin({
  modelProvider: new OpenAIProvider(),
  modelParams: { startToCloseTimeout: '30s' },
});

Also ships StatelessMCPServerProvider / StatefulMCPServerProvider, a replay-safe tracer provider, and an OpenAIAgentsTraceClientInterceptor for end-to-end trace propagation.

Correctness-critical behavior

  • Handoff conversion — shallow-clones user Handoff objects (no mutation); preserves onHandoff, inputType, isEnabled; cycle detection for cyclic handoff graphs.
  • Error classification — when the model Activity catches an APIError from the OpenAI SDK, it inspects error.status and error.headers, honors x-should-retry and retry-after, and maps the result to ModelInvocationError subtypes (.RateLimit, .Authentication, .BadRequest, .ServerError, .Timeout, .Conflict).
  • Tool validation — the runner rejects raw functions passed in the tools array (with a hint to use tool() or activityAsTool() instead), and recurses into handoff agents' tools. Inline tool()-built FunctionTools are supported and run in the Workflow sandbox; they must be deterministic.
  • AgentsWorkflowError — wraps non-Temporal errors; TemporalFailures buried in the cause chain are unwrapped rather than re-wrapped.
  • Sandbox polyfillsHeaders, ReadableStream, structuredClone, crypto.randomUUID (deterministic via uuid4()), EventTarget / Event / CustomEvent (workflow-safe, isolated listener errors).

Tests

  • 53 unit tests in contrib/openai-agents/src/__tests__/ covering classifier, agent conversion, polyfills, serialized model, errors, sink bridge, and client trace interceptor.
  • 8 integration tests in packages/test/src/test-openai-agents.ts exercising the full plugin path with FakeModelProvider / GeneratorFakeModelProvider.

@socket-security
Copy link
Copy Markdown

socket-security Bot commented Apr 27, 2026

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addednpm/​@​openai/​agents-openai@​0.3.9991007899100
Addednpm/​@​openai/​agents-core@​0.3.9991008099100

View full report

xumaple added a commit that referenced this pull request May 14, 2026
…-42)

Final review batch on PR #2024. 8 files / +619/-19. Audit fixes folded in
pre-commit.

- Item 36 — exact-count assertions added to comprehensive Test 2
  (`executeActivityCount=0`, `agentRunCount=9`, `generationCount=16`),
  closing the replay-doubling guard gap relative to Test 1.
- Item 37 — error-path comprehensive E2E added. `errorPathComprehensiveWorkflow`
  runs BasicAgent + EchoToolAgent + a FailingAgent whose `instructions` throws;
  the runner wraps it as `ApplicationFailure(type='AgentsWorkflowError')`.
  Test asserts (a) partial span tree for completed agents + the failing one,
  (b) follow-up workflow on the same isolate sees clean trace context.
- Item 38 — multi-workflow config isolation E2E strengthened. Now also
  partitions spans by trace ID and asserts `temporal:*` agent spans appear
  only in the `addTemporalSpans=true` workflow's trace.
- Item 39 — stateful-MCP comprehensive E2E. `statefulMcpComprehensiveWorkflow`
  exercises BasicAgent + WeatherToolAgent + StatefulMcpAgent + TriageAgent
  →Specialist in a single run.
- Item 40 — `TEMPORAL_ACTIVITY_TOOL_MARKER` symbol and the writer that
  stamped it removed entirely. Zero readers existed in the codebase; the
  prior `(t as any)[MARKER]` was dead infrastructure. Cleaner than swapping
  it for an also-dead WeakMap.
- Item 41 — `BaseAgentTracingProcessor` constructor now throws loudly when
  the global TracerProvider's delegate isn't a `ReplaySafeTracerProvider`.
  Replaces the prior silent no-op fallback for the misconfiguration case.
  WARNING comment documents both the "OTel internals changed" trigger and
  the "user enabled addTemporalSpans without registering a provider" trigger.
- Item 42 — three user-facing error messages rewritten to be actionable
  (stateful MCP schedule/heartbeat/not-connected). Public-contract JSDoc
  above `DEDICATED_WORKER_*_FAILURE_MESSAGE` constants updated to reflect
  the pre-publish iteration window (the load-bearing contract is
  `DEDICATED_WORKER_FAILURE_TYPE`, not the messages).

Tests: 14/14 tracing + openai-agents suite passes (modulo 3 pre-existing
rate-limit flakes unrelated to this batch). Lint clean for all source
files in scope.
@xumaple xumaple force-pushed the maplexu/openai-agents-plugin branch 2 times, most recently from f173bf2 to 4507fe0 Compare May 18, 2026 19:55
@brianstrauch brianstrauch requested a review from Copilot May 18, 2026 20:23
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds @temporalio/openai-agents, a new Temporal integration package for running OpenAI Agents SDK agent loops durably in workflows while delegating model/tool/MCP operations to Temporal activities.

Changes:

  • Adds the OpenAI Agents package with workflow/worker/client tracing, model activity delegation, MCP support, polyfills, and tests.
  • Adds deterministic newRandom() support and shared workflow sandbox polyfills.
  • Wires the new package into the workspace, lockfile, and integration test suite.

Reviewed changes

Copilot reviewed 79 out of 80 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
pnpm-workspace.yaml Adds packages/openai-agents to the workspace.
pnpm-lock.yaml Adds dependencies and workspace links for the new package and tests.
package.json Adds root workspace dependency on @temporalio/openai-agents.
eslint.config.mjs Adds restricted-import lint rules for the new package.
packages/ai-sdk/package.json Moves shared workflow polyfill dependencies to @temporalio/workflow.
packages/ai-sdk/src/load-polyfills.ts Reuses the shared workflow polyfills module.
packages/workflow/package.json Adds shared Web API polyfill dependencies.
packages/workflow/src/alea.ts Allows readonly seeds for deterministic RNG construction.
packages/workflow/src/internals.ts Tracks the current randomness seed and seed version.
packages/workflow/src/polyfills.ts Adds workflow sandbox Web API polyfills.
packages/workflow/src/workflow.ts Adds newRandom() deterministic RNG helper.
packages/openai-agents/package.json Defines the new package metadata, exports, dependencies, and scripts.
packages/openai-agents/tsconfig.json Adds TypeScript project config for the new package.
packages/openai-agents/src/index.ts Exposes worker/client-side public API.
packages/openai-agents/src/workflow.ts Exposes workflow-safe public API.
packages/openai-agents/src/client/trace-interceptor.ts Adds client-side trace/config propagation.
packages/openai-agents/src/common/agent-sink-types.ts Defines workflow-to-host agent tracing sink wire types.
packages/openai-agents/src/common/base-tracing-processor.ts Maps OpenAI Agents tracing events to OTel spans.
packages/openai-agents/src/common/errors.ts Adds Temporal failure unwrapping helper.
packages/openai-agents/src/common/headers.ts Adds trace/config/OTel header helpers.
packages/openai-agents/src/common/mcp-types.ts Defines shared MCP activity names and types.
packages/openai-agents/src/common/model-activity-options.ts Defines model activity configuration types.
packages/openai-agents/src/common/otel-internals.ts Adds OTel internal provider/id-generator helpers.
packages/openai-agents/src/common/otel-sink-types.ts Defines workflow-to-host OTel sink wire types.
packages/openai-agents/src/common/serialized-model.ts Defines JSON-safe model request/response wire shapes.
packages/openai-agents/src/common/trace-context.ts Restores and isolates OpenAI Agents trace context.
packages/openai-agents/src/common/tracing-bridge.ts Bridges OpenAI Agents IDs/span data to OTel.
packages/openai-agents/src/tracer-provider.ts Adds replay-safe OTel tracer provider.
packages/openai-agents/src/worker/activities.ts Adds model invocation activity implementation.
packages/openai-agents/src/worker/activity-tracing.ts Adds activity-side tracing processor registration.
packages/openai-agents/src/worker/agent-sink-bridge.ts Bridges workflow agent tracing sink events to host processors.
packages/openai-agents/src/worker/heartbeat.ts Adds adaptive activity heartbeat helper.
packages/openai-agents/src/worker/mcp-provider.ts Adds stateless MCP provider activity registration.
packages/openai-agents/src/worker/otel-sink-bridge.ts Bridges workflow OTel sink events to host processors.
packages/openai-agents/src/worker/plugin.ts Adds worker plugin integration and sink/interceptor wiring.
packages/openai-agents/src/worker/stateful-mcp-provider.ts Adds stateful MCP provider with dedicated per-run worker.
packages/openai-agents/src/worker/trace-interceptor.ts Adds activity inbound trace interceptor.
packages/openai-agents/src/workflow/activity-backed-model.ts Delegates model calls from workflows to activities.
packages/openai-agents/src/workflow/agent-sink-processor.ts Emits workflow agent tracing events through sinks.
packages/openai-agents/src/workflow/convert-agent.ts Converts agent graphs to activity-backed models.
packages/openai-agents/src/workflow/load-polyfills.ts Adds OpenAI Agents workflow polyfills.
packages/openai-agents/src/workflow/mcp-client.ts Adds workflow-side stateless MCP client.
packages/openai-agents/src/workflow/otel-context-manager.ts Adds workflow OTel context manager.
packages/openai-agents/src/workflow/otel-sink-processor.ts Emits workflow OTel spans through sinks.
packages/openai-agents/src/workflow/placeholder-model-provider.ts Adds safety placeholder model provider.
packages/openai-agents/src/workflow/plugin-config-store.ts Stores per-workflow plugin config.
packages/openai-agents/src/workflow/prng.ts Adds PRNG/span ID helpers for handler tracing.
packages/openai-agents/src/workflow/runner.ts Adds Temporal OpenAI runner implementation.
packages/openai-agents/src/workflow/span-helpers.ts Adds temporal span/header injection helpers.
packages/openai-agents/src/workflow/stateful-mcp-client.ts Adds workflow-side stateful MCP client.
packages/openai-agents/src/workflow/tools.ts Adds activity-as-tool wrapper.
packages/openai-agents/src/workflow/trace-interceptor.ts Adds workflow inbound/outbound trace interceptor.
packages/openai-agents/src/workflow/tracing.ts Adds workflow tracing processor setup.
packages/openai-agents/src/__tests__/classifier.test.ts Adds model error classification tests.
packages/openai-agents/src/__tests__/client-trace-interceptor.test.ts Adds client interceptor tests.
packages/openai-agents/src/__tests__/convert-agent.test.ts Adds agent conversion tests.
packages/openai-agents/src/__tests__/errors.test.ts Adds error normalization tests.
packages/openai-agents/src/__tests__/polyfills.test.ts Adds polyfill tests.
packages/openai-agents/src/__tests__/serialized-model.test.ts Adds model serialization tests.
packages/openai-agents/src/__tests__/sink-bridge.test.ts Adds tracing sink bridge tests.
packages/test/package.json Adds test dependencies for OpenAI Agents integration tests.
packages/test/tsconfig.json Adds project reference for the new package.
packages/test/src/activities/openai-agents.ts Adds basic activity fixtures for agent tests.
packages/test/src/activities/openai-agents-comprehensive.ts Adds comprehensive activity fixtures.
packages/test/src/helpers-integration.ts Adds plugin forwarding for test workflow bundling/environment setup.
packages/test/src/stubs/openai-agents.ts Adds reusable model/provider test stubs.
packages/test/src/stubs/openai-agents-comprehensive.ts Adds comprehensive MCP/model stubs.
packages/test/src/stubs/openai-agents-fakes.ts Adds fake model response builders.
packages/test/src/test-openai-agents.ts Adds OpenAI Agents integration tests.
packages/test/src/test-otel.ts Removes obsolete lint suppression.
packages/test/src/test-workflows.ts Adds newRandom() workflow tests.
packages/test/src/workflows/index.ts Exports new random test workflows.
packages/test/src/workflows/new-random.ts Adds workflows for deterministic newRandom() behavior.
packages/test/src/workflows/openai-agents.ts Adds workflow fixtures for OpenAI Agents tests.
packages/test/src/workflows/openai-agents-tracing.ts Adds tracing workflow fixtures.
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread contrib/openai-agents/src/worker/activities.ts
Comment thread contrib/openai-agents/src/workflow/convert-agent.ts
Comment thread packages/workflow/package.json Outdated
"@temporalio/common": "workspace:*",
"@temporalio/proto": "workspace:*",
"nexus-rpc": "^0.0.2"
"@ungap/structured-clone": "^1.3.0",
Comment thread packages/openai-agents/src/worker/plugin.ts Outdated
Comment thread packages/openai-agents/src/workflow/prng.ts Outdated
Comment thread contrib/openai-agents/src/workflow.ts
Comment thread contrib/openai-agents/package.json
Comment thread packages/openai-agents/src/worker/activities.ts Outdated
Comment thread contrib/openai-agents/README.md Outdated
@xumaple xumaple marked this pull request as ready for review May 18, 2026 21:14
@xumaple xumaple requested a review from a team as a code owner May 18, 2026 21:14
@xumaple xumaple force-pushed the maplexu/openai-agents-plugin branch from ae2ff35 to 88adedb Compare May 18, 2026 22:04
Comment thread contrib/workflow-polyfills/src/index.ts Outdated
xumaple added a commit that referenced this pull request May 18, 2026
…b package

Per @brianstrauch on #2024: `packages/workflow/src/polyfills.ts` pulled `headers-polyfill`, `@ungap/structured-clone`, and `web-streams-polyfill` (the latter is ~140KB) into `@temporalio/workflow`, the core Workflow package. Every consumer of `@temporalio/workflow` paid the install cost for polyfills only the OpenAI Agents and AI SDK integrations actually load.

New `@temporalio/workflow-polyfills` package at `contrib/workflow-polyfills/`:
- Owns the three Web-API polyfill deps.
- Side-effect import; same module body as before, repointed to `@temporalio/workflow` exports.

`contrib/ai-sdk` and `contrib/openai-agents` depend on it directly (`workspace:*`) and update their `load-polyfills.ts` shims to `import '@temporalio/workflow-polyfills'`.

`packages/workflow/package.json` drops the three deps. Pure restructure, no behavioral change — same polyfill code runs in the same Workflow contexts.
Comment thread pnpm-workspace.yaml Outdated
Comment thread packages/workflow/src/workflow.ts Outdated
Comment thread packages/test/tsconfig.json Outdated
Comment thread contrib/openai-agents/src/worker/otel-sink-bridge.ts Outdated
@brianstrauch
Copy link
Copy Markdown
Member

Other thoughts:

Copy link
Copy Markdown
Member

@chris-olszewski chris-olszewski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Partial review, sorry I didn't get too far past the package level. Will pick up review this afternoon.

Comment thread contrib/ai-sdk/src/load-polyfills.ts Outdated
Comment thread contrib/workflow-polyfills/src/index.ts Outdated
Comment thread contrib/openai-agents/package.json Outdated
Comment thread contrib/openai-agents/package.json Outdated
"require": "./lib/workflow.js",
"default": "./lib/workflow.js"
},
"./load-polyfills": {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to expose the polyfills and require users to manually import them? Could we copy the pattern from the AI SDK and import the polyfills in entrypoints of the package?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I did this properly, but not sure... let me know if something is missing.

Comment thread contrib/openai-agents/README.md Outdated
Comment thread contrib/openai-agents/README.md Outdated
Comment thread contrib/openai-agents/package.json Outdated
Comment on lines +67 to +68
"@opentelemetry/api": "^1.9.0",
"@opentelemetry/sdk-trace-base": "^1.25.1",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unsure if worth the squeeze, but this is forcing all users to take OTEL dependencies even if they don't enable them. For Lambda we defined a separate entrypoint that allows us to declare these as optional peer deps:

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved the sdk-trace-base to an opt-in, but the opentelemtry/api stuff is pretty tightly coupled to the entire tracing module, I left it alone. Is that okay for you?

Comment thread contrib/workflow-polyfills/package.json Outdated
*
* Mirrors Python's `workflow.new_random()`.
*/
export function newRandom(): RNG {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't. We already have WIP to add a proper API for this: #1992.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

waiting on this PR to be completed.

Comment thread contrib/openai-agents/src/__tests__/test-openai-agents.ts
@mjameswh
Copy link
Copy Markdown
Contributor

Note that I only skimmed over the actual @temporalio/openai-agents package, as that's under the AI team's responsibility. I raised several concerns regarding things outside of that package.

@mjameswh
Copy link
Copy Markdown
Contributor

You'll need to add the contrib/openai-agents path to the .github/CODEOWNERS file.

xumaple added a commit that referenced this pull request May 23, 2026
… comment

- otel-sink-bridge: use hrTimeDuration from @opentelemetry/core; manual
  [s,ns] subtraction produced [1,-1] instead of [0,999999999] when
  nanoseconds borrowed across the second boundary.
- workflow.ts (newRandom): remove "Mirrors Python's workflow.new_random()"
  JSDoc line — cross-SDK parity references add no value for TS users.

Addresses review comments from brianstrauch on PR #2024.
next: Next<WorkflowOutboundCallsInterceptor, 'scheduleActivity'>
): Promise<unknown> {
// Fire-and-forget infra Activities (e.g. stateful MCP session) need an
// INSTANT span — a lifetime span would swallow every subsequent Activity
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It sounds like that should just be a span which isn't put on the current context, not an instant one.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed this to a span not on current context. thanks for the suggestion

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm actually this is not possible based on the current API that openai exposes for us. because we don't have a way of pushing out a span until it's completed. Will wait on them to give us a new API before I call this completed

Comment thread contrib/openai-agents/src/worker/agent-sink-bridge.ts Outdated
Comment thread contrib/openai-agents/src/worker/agent-sink-bridge.ts
@xumaple xumaple force-pushed the maplexu/openai-agents-plugin branch from 192d411 to 6a91435 Compare May 28, 2026 04:01
Comment thread contrib/openai-agents/README.md Outdated
Comment thread contrib/openai-agents/README.md Outdated
"@openai/agents-openai": "~0.11.5",
"@opentelemetry/sdk-trace-base": "^1.25.1",
"openai": "^6.35.0",
"zod": "^4.0.0"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unsure if this was from before, but I'm not finding any usage of zod in this package so I don't think it should be a peer dependency.

xumaple and others added 9 commits May 29, 2026 16:57
Adds a new Temporal contrib package that runs OpenAI Agents SDK agent
loops as durable Workflows. The agent loop (model reasoning, tool
dispatch, handoffs) executes deterministically inside the Workflow
sandbox; each model invocation is dispatched to a Temporal Activity
where the real ModelProvider lives.

Ships `TemporalOpenAIRunner`, `activityAsTool`, `nexusOperationAsTool`,
`agentAsTool`, `WorkflowSafeMemorySession`, `statelessMcpServer` /
`statefulMcpServer`, a replay-safe tracer provider, and an
`OpenAIAgentsTraceClientInterceptor` for end-to-end trace propagation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drop the public ./load-polyfills subpath — users always go through
OpenAIAgentsPlugin, which auto-installs polyfills via its bundler hook
(configureBundler), and bundleWorkflowCode accepts plugins too. Merge
install-polyfills.ts body into load-polyfills.ts (pure exports). The
2-line preload-polyfills.ts is the only call site for installPolyfills().
Remove the dead polyfill import from tracing.ts — by the time it
evaluates, the entry-prepended preload-polyfills has already installed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@xumaple xumaple force-pushed the maplexu/openai-agents-plugin branch from d8bd521 to 00d8c73 Compare May 29, 2026 20:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants