Skip to content

fix(langgraph): keep _on_started backward-compatible with overrides predating cause#7987

Merged
Nick Hollon (nick-hollon-lc) merged 1 commit into
mainfrom
nh/transformers-on-started-cause-backcompat
Jun 2, 2026
Merged

fix(langgraph): keep _on_started backward-compatible with overrides predating cause#7987
Nick Hollon (nick-hollon-lc) merged 1 commit into
mainfrom
nh/transformers-on-started-cause-backcompat

Conversation

@nick-hollon-lc

@nick-hollon-lc Nick Hollon (nick-hollon-lc) commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Problem

#7928 added a keyword-only cause argument to the _TasksLifecycleBase._on_started hook and passes it unconditionally. Subclasses that override _on_started without a cause parameter — including downstream/third-party transformers like deepagents' SubagentTransformer (which subclasses this base) — then raise:

TypeError: _on_started() got an unexpected keyword argument 'cause'

erroring the run whenever a subagent/subgraph is discovered. deepagents pulls langgraph transitively (langchain<1.3.0,>=1.2.2, no direct pin), so shipping the cause change in a 1.2.x release would break published deepagents.

Fix

Deliver cause via instance state rather than the call signature: _handle_task_start sets self._pending_cause immediately before calling _on_started, and overrides that surface cause read it from there. _on_started reverts to its original (self, ns, graph_name, trigger_call_id) signature.

Why this shape:

  • The _on_started signature is identical to what every existing override implements, so no override — old or new — breaks. No introspection/reflection.
  • Signature-stable: future "started" context is another instance attr, never a signature change → this class of cross-package break can't recur.
  • LifecycleTransformer reads self._pending_cause (it surfaces cause on the wire LifecyclePayload); SubgraphTransformer ignores it, as before.

Tests

  • Regression test: an _on_started(self, ns, graph_name, trigger_call_id) override (no cause) processes a task-start event without raising. Existing transformer tests unchanged (27 pass); format/lint/mypy clean.
  • Verified end-to-end against a local langgraph-api stack running this core + published deepagents: deep_agent subagent runs (which previously errored) complete cleanly, 6/6; full sdk-py integration suite green.

(Switched from an earlier introspection-based approach to this instance-state delivery — cleaner and signature-stable.)

… state

#7928 added a keyword-only `cause` argument to the `_TasksLifecycleBase._on_started` hook and passed it unconditionally, breaking overrides that predate it — including downstream/third-party transformers like deepagents' `SubagentTransformer` (`TypeError: _on_started() got an unexpected keyword argument 'cause'`), which errored subagent runs.

Deliver `cause` via instance state (`self._pending_cause`, set immediately before the call) instead of the call signature. `_on_started` reverts to its original `(ns, graph_name, trigger_call_id)` signature, so no override — old or new — ever breaks, with no introspection and no lockstep downstream release. `LifecycleTransformer` reads `self._pending_cause`; `SubgraphTransformer` ignores it as before. Adds a regression test.
@nick-hollon-lc Nick Hollon (nick-hollon-lc) force-pushed the nh/transformers-on-started-cause-backcompat branch from 6690d67 to 8ad9263 Compare June 2, 2026 15:26
@nick-hollon-lc Nick Hollon (nick-hollon-lc) merged commit fb26188 into main Jun 2, 2026
70 checks passed
@nick-hollon-lc Nick Hollon (nick-hollon-lc) deleted the nh/transformers-on-started-cause-backcompat branch June 2, 2026 15:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants