feat(openai-agents): add @temporalio/openai-agents package#2024
feat(openai-agents): add @temporalio/openai-agents package#2024xumaple wants to merge 9 commits into
Conversation
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
…-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.
f173bf2 to
4507fe0
Compare
There was a problem hiding this comment.
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.
| "@temporalio/common": "workspace:*", | ||
| "@temporalio/proto": "workspace:*", | ||
| "nexus-rpc": "^0.0.2" | ||
| "@ungap/structured-clone": "^1.3.0", |
ae2ff35 to
88adedb
Compare
…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.
|
Other thoughts:
|
chris-olszewski
left a comment
There was a problem hiding this comment.
Partial review, sorry I didn't get too far past the package level. Will pick up review this afternoon.
| "require": "./lib/workflow.js", | ||
| "default": "./lib/workflow.js" | ||
| }, | ||
| "./load-polyfills": { |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
I think I did this properly, but not sure... let me know if something is missing.
| "@opentelemetry/api": "^1.9.0", | ||
| "@opentelemetry/sdk-trace-base": "^1.25.1", |
There was a problem hiding this comment.
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:
There was a problem hiding this comment.
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?
| * | ||
| * Mirrors Python's `workflow.new_random()`. | ||
| */ | ||
| export function newRandom(): RNG { |
There was a problem hiding this comment.
Don't. We already have WIP to add a proper API for this: #1992.
There was a problem hiding this comment.
waiting on this PR to be completed.
|
Note that I only skimmed over the actual |
|
You'll need to add the |
… 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 |
There was a problem hiding this comment.
It sounds like that should just be a span which isn't put on the current context, not an instant one.
There was a problem hiding this comment.
changed this to a span not on current context. thanks for the suggestion
There was a problem hiding this comment.
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
192d411 to
6a91435
Compare
| "@openai/agents-openai": "~0.11.5", | ||
| "@opentelemetry/sdk-trace-base": "^1.25.1", | ||
| "openai": "^6.35.0", | ||
| "zod": "^4.0.0" |
There was a problem hiding this comment.
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.
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>
d8bd521 to
00d8c73
Compare
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 realModelProviderlives.API
Also ships
StatelessMCPServerProvider/StatefulMCPServerProvider, a replay-safe tracer provider, and anOpenAIAgentsTraceClientInterceptorfor end-to-end trace propagation.Correctness-critical behavior
Handoffobjects (no mutation); preservesonHandoff,inputType,isEnabled; cycle detection for cyclic handoff graphs.APIErrorfrom the OpenAI SDK, it inspectserror.statusanderror.headers, honorsx-should-retryandretry-after, and maps the result toModelInvocationErrorsubtypes (.RateLimit,.Authentication,.BadRequest,.ServerError,.Timeout,.Conflict).toolsarray (with a hint to usetool()oractivityAsTool()instead), and recurses into handoff agents' tools. Inlinetool()-built FunctionTools are supported and run in the Workflow sandbox; they must be deterministic.TemporalFailures buried in the cause chain are unwrapped rather than re-wrapped.Headers,ReadableStream,structuredClone,crypto.randomUUID(deterministic viauuid4()),EventTarget/Event/CustomEvent(workflow-safe, isolated listener errors).Tests
contrib/openai-agents/src/__tests__/covering classifier, agent conversion, polyfills, serialized model, errors, sink bridge, and client trace interceptor.packages/test/src/test-openai-agents.tsexercising the full plugin path withFakeModelProvider/GeneratorFakeModelProvider.