feat(adapters/langgraph): compile ManagerWorkers into a hierarchical graph - #30
Open
spichen wants to merge 17 commits into
Open
feat(adapters/langgraph): compile ManagerWorkers into a hierarchical graph#30spichen wants to merge 17 commits into
spichen wants to merge 17 commits into
Conversation
This was referenced Jul 25, 2026
spichen
force-pushed
the
feat/agent-single-string-output
branch
from
July 25, 2026 11:31
cdbe088 to
c368d95
Compare
spichen
force-pushed
the
feat/managerworkers-adapter
branch
from
July 25, 2026 11:31
3747193 to
dba45e2
Compare
spichen
force-pushed
the
feat/agent-single-string-output
branch
from
July 25, 2026 11:37
c368d95 to
711abb5
Compare
spichen
force-pushed
the
feat/managerworkers-adapter
branch
from
July 25, 2026 11:37
dba45e2 to
34ad0ab
Compare
spichen
force-pushed
the
feat/agent-single-string-output
branch
from
July 25, 2026 12:00
711abb5 to
bd33dfd
Compare
spichen
force-pushed
the
feat/managerworkers-adapter
branch
from
July 25, 2026 12:00
34ad0ab to
023ef14
Compare
spichen
force-pushed
the
feat/agent-single-string-output
branch
from
July 25, 2026 15:30
bd33dfd to
4460030
Compare
spichen
force-pushed
the
feat/managerworkers-adapter
branch
from
July 25, 2026 15:30
023ef14 to
fa78d18
Compare
spichen
force-pushed
the
feat/agent-single-string-output
branch
from
July 25, 2026 16:16
4460030 to
47a3d39
Compare
spichen
force-pushed
the
feat/managerworkers-adapter
branch
from
July 25, 2026 16:16
fa78d18 to
1aa5a54
Compare
spichen
force-pushed
the
feat/agent-single-string-output
branch
from
July 25, 2026 16:48
47a3d39 to
cd19935
Compare
spichen
force-pushed
the
feat/managerworkers-adapter
branch
from
July 25, 2026 16:48
1aa5a54 to
ebf57be
Compare
spichen
force-pushed
the
feat/agent-single-string-output
branch
from
July 25, 2026 16:55
cd19935 to
4373852
Compare
spichen
force-pushed
the
feat/managerworkers-adapter
branch
2 times, most recently
from
July 25, 2026 18:33
e1a293b to
c3ed319
Compare
spichen
force-pushed
the
feat/managerworkers-adapter
branch
from
July 25, 2026 20:52
9fa2184 to
08f689a
Compare
* Upgrading agent-framework adapter to work on latest release * Fix api key in langgraph adapter * Upgrade openai agents * Generalization * Remove negative test for api key in langgraph * Fix autogen * Fix documentation * Changelog, fix docs
* feat: add DBMS vector chain LLM config Signed-off-by: Tanmay Bagaria <tanmay.bagaria@oracle.com> * Add DBMS Vector Chain LLM configuration Signed-off-by: Tanmay Bagaria <tanmay.bagaria@oracle.com> * Address DBMS Vector Chain review feedback Signed-off-by: Tanmay Bagaria <tanmay.bagaria@oracle.com> * Clarify DBMS Vector Chain configuration semantics Signed-off-by: Tanmay Bagaria <tanmay.bagaria@oracle.com> --------- Signed-off-by: Tanmay Bagaria <tanmay.bagaria@oracle.com>
cesarebernardis
force-pushed
the
feat/managerworkers-adapter
branch
from
August 24, 2026 10:07
ec7909b to
6cdd9fc
Compare
* bump versions * bump version 26.3.0 * Remove CrewAI adapter * open new dev cycle * Revert "Remove CrewAI adapter" This reverts commit 5ca9197. --------- Co-authored-by: Son Le <tran.minh.son.le@oracle.com> Co-authored-by: Damien Hilloulin <damien.hilloulin@oracle.com>
…nagerWorkers Quality pass over the ManagerWorkers adapter. No behaviour change intended. Wrapping stream/astream in an execution span was already duplicated between the Agent and Flow paths, and ManagerWorkers added a third near-verbatim copy. Extract one `patch_with_execution_span` into `_execution_span.py`, parameterized by span and event factories, and route all three through it. The `except NotImplementedError` fallback ladder for the async span protocol was written 12 times; it is now one helper. Move the flow-step compile onto `AgentNodeExecutor` as `_create_manager_workers_with_given_input_values`, next to its react-agent twin. It was living in `_managerworkers.py` while importing the converter and taking the executor's private cache as a parameter. Replace the six per-worker closures in `_wrap_worker_for_subgraph` with module-level helpers and a `_WorkerSubgraphNode` holding only the graph, so a long-lived node no longer pins the whole factory frame. Memoize `_make_worker_delegation_tool`, which depends only on the node name yet re-ran the `@tool` decorator on every compile. In the converter, collapse the parallel worker list and dict into one list of pairs, hoist the repeated conversion kwargs, and use the module's existing lazy `langgraph_graph` instead of a local `MessagesState` import. Drop `is_delegation_event`: no callers, not exported, unreachable through any supported import path. `is_delegation_tool_name` stays. Tests: collapse six copies of the loader and double-patch stack into one `_load_with_fake_llms` helper, and drop assertions in the roster test that compared a locally computed string against itself. Add an `allow_llm_config_construction` fixture so tests that only build an LLM config and stub the conversion are not skipped by the blanket SKIP_LLM_TESTS guard. This un-skips the three flow-step tests that the guard was hiding.
…h codebase style Trim reviewer-directed comments to codebase density; drop the lru_cache on the delegation-tool factory, the _WorkerSubgraphNode class (now closures) and the dict-or-object tool-call shim. Rewrite the tests to repo conventions: module-level pyagentspec imports, a shared _agent() helper, pytestmark instead of an empty autouse fixture, no section dividers, and behavior-level coverage instead of micro-tests of private helpers. Also fix a real bug the flow-step test exposed: the ManagerWorkers parent graph runs over MessagesState, so a structured_response can never reach the node executor and any declared output raised ValueError. A ManagerWorkers flow step now answers its single string output with the manager's final message, and rejects other output shapes with NotImplementedError.
- Remove the SKIP_LLM_TESTS opt-out fixture from tests/adapters/conftest.py and its usages; the tests now skip like every other LLM-config test. - Rename the delegation tool prefix to __delegate_to__ so it cannot collide with a real tool name, and route a delegation only when its suffix is an actual worker node. - Move flows/test_managerworkers_node.py into the main test_managerworkers.py since ManagerWorkers is not a Node. - Enforce that the I/Os of a ManagerWorkers match the I/Os of its group manager (same name and type), per the language spec decision. - Reject unsupported ManagerWorkers flow-step output shapes when the flow is converted instead of when the step runs.
- Move the ManagerWorkers flow-step behavior out of AgentNodeExecutor into a dedicated ManagerWorkersNodeExecutor, selected once at conversion time in _agent_node_convert_to_langgraph. This removes the scattered isinstance branches and brings _node_execution.py back under 1000 lines. - Document why the executor calls the private converter entry point: the public convert() caches by component id, which would collapse differently-rendered prompt copies into one graph. - Re-export DELEGATE_TOOL_PREFIX and is_delegation_tool_name from pyagentspec.adapters.langgraph so the delegation protocol is actually public API. - Tidy: hoist the stdlib Annotated import, annotate _async_or_sync -> None, correct the _MANAGER_NODE_KEY collision-safety comment.
cesarebernardis
force-pushed
the
feat/managerworkers-adapter
branch
from
August 25, 2026 13:44
0a52773 to
bf30c66
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
ManagerWorkershad no LangGraph support: converting one fell through_convertand raised. This compiles it into a hierarchical graph.The manager becomes a react agent holding one synthetic
delegate_to_<worker>tool per worker. The parent graph intercepts that tool call in a conditional edge and fans out oneSendper delegation, so a single manager turn can delegate to several workers at once. Each worker runs in an isolated message context and replies with aToolMessagematched to itstool_call_id. Every call gets answered independently, since an unanswered one leaves a dangling call in the manager's next turn.Workers are converted recursively into their own
CompiledStateGraphand added as subgraph nodes, soastream_eventsstill shows the parent/child boundary (subgraph=True) for tracing and SSE streaming. NestedManagerWorkerscompose throughconvertwith no extra work.ManagerWorkersnow infers its inputs and outputs from the group manager, so it can sit inside a flow: anAgentNodewrapping one exposes input ports, and aDataFlowEdgeinto it resolves. The graph runs overMessagesState, which can't carry structured inputs inward, so node inputs are rendered into the group-manager prompt and the satisfied ports are dropped.AgentNodeExecutorcompiles and caches that graph by rendered prompt, the same key it already uses for plain react agents.The delegation protocol is deliberately visible:
delegate_to_<worker>calls and their lifecycle events stream like any other tool call, because "the manager handed task X to worker Y" is usually the most informative thing a run produces. Nothing wrapsastream_eventsto scrub it. A consumer that would rather not render the routing plumbing can recognize it withis_delegation_tool_name.Structure
Helpers live in a new
_managerworkers.pyrather than growing_langgraphconverter.py;_manager_workers_convert_to_langgraphstays on the converter next to its siblings, and the flow-step compile sits onAgentNodeExecutornext to its react-agent equivalent.Wrapping
stream/astreamin an execution span was already duplicated between the Agent and Flow paths, and ManagerWorkers needed a third copy. That wrapper is now a singlepatch_with_execution_spanin_execution_span.py, parameterized by span and event factories, and all three paths call it.Swarm is untouched.
Testing
tests/adapters/langgraph,tests/serializationandtests/validationwithSKIP_LLM_TESTS=1, in a venv pinned toconstraints/constraints.txt. The only failures are the pre-existing ones that need a live model endpoint.ruffis clean on the changed files.The 25
ManagerWorkerstests all run offline, including the five flow-step ones inflows/test_managerworkers_node.py. They opt out of the blanketSKIP_LLM_TESTSconstruction guard via a newallow_llm_config_constructionfixture — that guard skips a test the moment it builds an LLM config, which is right for tests that go on to call a model but hides tests that only need a config object and stub the conversion.🤖 Generated with Claude Code