Skip to content

fix(openai-agents): give agentAsTool runs the run model, model settings and runner defaults - #244

Draft
campoy wants to merge 2 commits into
mainfrom
fix/openai-agents-typescript-agent-tool-run-model-lost
Draft

campoy wants to merge 2 commits into
mainfrom
fix/openai-agents-typescript-agent-tool-run-model-lost

Conversation

@campoy

@campoy campoy commented Oct 27, 2026

Copy link
Copy Markdown
Contributor

What was changed

An agentAsTool run now takes what upstream agent.asTool() passes to a nested run, instead of only the sandbox:

  • the calling run's runConfig.model, for nested agents that set no model of their own. A nested agent with its own model keeps it, as natively;
  • the calling run's runConfig.modelSettings, without toolChoice and parallelToolCalls, which pick the outer agent's tools (upstream getSafeInheritedAgentToolModelSettings leaves out the same two);
  • the calling runner's defaultModelParams, so nested model Activities get the same timeout, summary, retry policy, task queue and local-Activity setting as the rest of the run. The Client header's modelParams still win over them, as for the parent.

How: the runner already handed its sandbox to each agentAsTool tool through a symbol-keyed hook. That hook now carries the run's model, settings and runner defaults too. convertAgent gets an optional modelNameDefault, used only by agents whose model is the framework's empty placeholder, next to the existing modelNameOverride. No public name or signature changes. The README's "Nested agent tools" section says what the nested run takes.

Replay and rollback: taking the run's settings is behind patched('openai-agents.agent-tool-run-config'), asked only when the calling run has a model, settings or runner defaults to pass. Runs with nothing to pass, like the README example, record no marker.

  • Nested runs recorded before this change replay on it the old way. Without the gate, an old run whose runner sets useLocalActivity replays its nested model call as a local Activity instead of the recorded Activity and fails with [TMPRL1100] ... No command scheduled for event ... ActivityTaskScheduled. An inherited modelSettings.retry could likewise add model calls to a run that caught a failed nested call (by reading the code; not run).
  • A run that started before the change and calls a nested agent again after the upgrade takes the run's settings from that call on, and records the marker then.
  • A run that records the marker cannot be replayed by an earlier plugin version ([TMPRL1100] ... Non-deprecated patch marker encountered). To roll back, keep this version and decline the patch with the Worker's patchActivationCallback (experimental in SDK 1.24), or use Worker Versioning. Runs without the marker can roll back to the earlier version.

Why?

See #243. agentAsTool started the nested run with new TemporalOpenAIRunner() and a run config that held only the sandbox. In a run that sets a model or model settings, a nested agent with no model of its own went to the Worker provider's default model without the run's settings, and the run completed with that answer. The nested runner also never saw the calling runner's defaultModelParams, so a Workflow started without the plugin's Client (by a Schedule or the CLI) had no way to set its nested agents' model Activity options: a runner retry limit of 2 attempts became unlimited for a nested call.

Checklist

  1. Closes [Bug] openai-agents (TypeScript): agentAsTool runs drop the run's model, model settings and runner defaults #243

  2. How was this tested:

    • New Worker test agentAsTool runs take the run model, model settings and runner defaults in test-openai-agents.ts: a lead with two agentAsTool tools, one agent with no model and one with its own, under runConfig: { model: 'run-model', modelSettings: { temperature: 0.33, toolChoice: 'auto' } } and a runner with a 17-second timeout and a summary. It checks the model name and settings each call gets and the timeout and summary of all four model Activities. On main it fails at the first check (- '', + 'run-model': the nested agent with no model got the Worker's default); it passes with the change.
    • New convertAgent case for modelNameDefault: an agent with no model and a handoff target with no model take it, an agent with its own model keeps it, and modelNameOverride still wins.
    • New replay test agentAsTool runs recorded before they took the runner defaults still replay, with src/__tests__/histories/agent-tool-local-activity-before-fix.json, recorded on main from a Workflow whose runner sets useLocalActivity, so its nested model call is an Activity. It passes on main and with the change, and fails with the change minus its gate ([TMPRL1100] ... No command scheduled for event HistoryEvent(id: 6, ActivityTaskScheduled)).
    • Locally, in a Linux container with Node 24.22.0 and pnpm 10.27.0: make lint (the 8 warnings already on main, none in changed files), make test (210 tests, main's 207 and the three new ones), make build, the npm package check, the smoke install, check_conventions.py and Prettier with the SDK settings pass. The Node 22, macOS and Windows cells did not run locally.
    • [Bug] openai-agents (TypeScript): agentAsTool runs drop the run's model, model settings and runner defaults #243's reproduction exits 1 on npm 1.24.0 and on main at c664a34, and 0 with the change: the nested call goes to run-model with temperature: 0.33 and a 17-second timeout, as the native control does.
    • Replay check, with Workers with no Workflow cache, on runs with no run config, with a run model and settings, and with runner defaults that use local Activities, each finished and (for the first two) waiting at a held model call:
      • all 16 histories replay on the change: the 7 from runs started on main (two of them finished on the change) and the 9 from runs started on it;
      • on main, the 10 histories without the marker replay, and the 6 with it fail with [TMPRL1100] ... Non-deprecated patch marker encountered, as expected for a gate;
      • runs waiting on main finish on the change; one with a run model takes it from its next nested call on and records the marker then;
      • with the patch declined through patchActivationCallback, a marked run waiting on the change finishes on its new path, and a new run takes the old path with no marker;
      • a marked run waiting on the change cannot continue on main, and finishes once the change is back; an unmarked one finishes on main;
      • the change without its gate fails main's local-Activity history with [TMPRL1100] ... No command scheduled for event HistoryEvent(id: 6, ActivityTaskScheduled);
      • a renamed model Activity fails with [TMPRL1100] on both builds.
    • The branch has two commits: the change, then a rename of the patch ID to match the plugin's other patches and the replay test. Review the combined diff against main. All results above are from the combined change.
  3. Any docs updates needed?
    The README's "Nested agent tools" section is updated here.

Not covered:

  • Upstream also passes toolExecution, toolNotFoundBehavior, toolNameCollisionPolicy, tracing and tracingDisabled to nested runs. This change covers the model, settings and Activity options only.
  • A run-scoped modelProvider is not part of the plugin's run config, so there is nothing to pass.
  • Streaming nested runs: agentAsTool runs are not streamed.
  • modelSettings.retry inheritance and its replay effect were checked by reading the code, not run.

Related: the plugin's top-level runConfig.model replaces every agent's model, while upstream uses it only for agents that set none. This change does not touch that; nested runs follow upstream, so a nested agent with its own model keeps it.

Overlap: #236 (agent hooks) also adds a fifth parameter to convertAgent and edits runner.ts, #238 edits convertAgent and #240 edits runner.ts, so whichever merges later may need a small rebase.

Open questions:

  • Gate boundary: the patch is asked at each nested call that has something to take. Asking it once per Workflow would keep old runs on the old path in every case, but would put a marker in every new run on a plugin Worker.
  • Should nested runs also take the other run-config fields upstream passes (tracingDisabled, tracing, tool execution settings)?

Draft while the gate and these questions are open.

…gs and runner defaults

An agentAsTool run started a new TemporalOpenAIRunner with only the sandbox,
so a nested agent with no model of its own went to the Worker's default model
without the run's settings, and its model Activities lost the runner's
defaultModelParams (timeout, summary, retry, task queue, local Activity).

As upstream agent.asTool() does, the nested run now takes the run's
runConfig.model for agents that set no model, runConfig.modelSettings without
toolChoice and parallelToolCalls, and the runner's defaultModelParams.

This is behind a patched() marker, asked only when there is something to
take, so nested runs recorded before this change replay without them.
…rs and test old histories

Rename the patch to openai-agents.agent-tool-run-config and add a replay test with a history recorded before this change, whose nested model call is an Activity under a runner that sets useLocalActivity.

This branch has not been deployed

No deployments
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.

[Bug] openai-agents (TypeScript): agentAsTool runs drop the run's model, model settings and runner defaults

1 participant