diff --git a/library-standard/src/mas/library/standard/plugins/design_patterns/base.py b/library-standard/src/mas/library/standard/plugins/design_patterns/base.py index 640d06cd..1176a451 100644 --- a/library-standard/src/mas/library/standard/plugins/design_patterns/base.py +++ b/library-standard/src/mas/library/standard/plugins/design_patterns/base.py @@ -120,13 +120,17 @@ def evaluate_next(self, q: QProduct, run: RunLedger, *, config: KernelConfig) -> def _participants_from_spec(self, config: KernelConfig) -> list[str]: spec = getattr(config, "agent_spec", None) or {} wf = (spec.get("workflow") or {}) if isinstance(spec, dict) else {} + # The coordinator/entry node isn't always literally named "moderator" + # (e.g. sre-triage's entry node is "sre") — use workflow.entry when + # present so the coordinator never ends up delegating to itself. + coordinator_id = str(wf.get("entry") or "moderator").strip() or "moderator" - # 1) moderator.delegates_to (dynamic topology) + # 1) coordinator.delegates_to (dynamic topology) nodes = wf.get("nodes") or [] for node in nodes: if not isinstance(node, dict): continue - if str(node.get("id") or "").strip() != "moderator": + if str(node.get("id") or "").strip() != coordinator_id: continue delegates = node.get("delegates_to") or [] if isinstance(delegates, list): @@ -141,19 +145,19 @@ def _participants_from_spec(self, config: KernelConfig) -> list[str]: if out: return out - # 3) fallback: workflow.nodes excluding moderator + # 3) fallback: workflow.nodes excluding the coordinator out: list[str] = [] for node in nodes: if not isinstance(node, dict): continue node_id = str(node.get("id") or node.get("agent") or "").strip() - if not node_id or node_id == "moderator": + if not node_id or node_id == coordinator_id: continue out.append(node_id) if out: return out - # 4) fallback: agency agents list from MAS spec (exclude moderator/self) + # 4) fallback: agency agents list from MAS spec (exclude coordinator/self) agency = (spec.get("agency") or {}) if isinstance(spec, dict) else {} rows = agency.get("agents") or [] out = [] @@ -161,7 +165,7 @@ def _participants_from_spec(self, config: KernelConfig) -> list[str]: if not isinstance(row, dict): continue aid = str(row.get("id") or row.get("name") or "").strip() - if not aid or aid == "moderator": + if not aid or aid == coordinator_id: continue out.append(aid) return out diff --git a/library-standard/src/mas/library/standard/plugins/design_patterns/linear.py b/library-standard/src/mas/library/standard/plugins/design_patterns/linear.py index 6f43087f..2aaa8381 100644 --- a/library-standard/src/mas/library/standard/plugins/design_patterns/linear.py +++ b/library-standard/src/mas/library/standard/plugins/design_patterns/linear.py @@ -18,7 +18,7 @@ class DeterministicLinearPlugin(_DeterministicBase): plugin_id = "deterministic_linear@v1" mode = "linear" - def evaluate_next(self, q: QProduct, run: RunLedger, *, config: KernelConfig) -> list[EgressSymbol]: + def evaluate_next(self, q: QProduct, run: RunLedger, config: KernelConfig) -> list[EgressSymbol]: st = self._state() if not st.participants: return self._no_participants(q) diff --git a/runtime/src/mas/runtime/kernel/ingress_step.py b/runtime/src/mas/runtime/kernel/ingress_step.py index 52398451..266e9c56 100644 --- a/runtime/src/mas/runtime/kernel/ingress_step.py +++ b/runtime/src/mas/runtime/kernel/ingress_step.py @@ -94,7 +94,7 @@ def commit_engine_io_return( q.dp = DpState.EVALUATING apply_control_valid(q) coord_after_ingress(q) - return evaluate(q, run, config) + return evaluate(q, run, config=config) def apply_engine_io_return( @@ -203,6 +203,6 @@ def apply_engine_io_return( ) q.inflight_kind = "NONE" q.dp = DpState.EVALUATING - return evaluate(q, run, config) + return evaluate(q, run, config=config) return commit_engine_io_return(q, run, event, config=config, evaluate=evaluate) diff --git a/runtime/tests/test_parallel_tools.py b/runtime/tests/test_parallel_tools.py index 7bbeab41..80d9933c 100644 --- a/runtime/tests/test_parallel_tools.py +++ b/runtime/tests/test_parallel_tools.py @@ -102,7 +102,7 @@ def test_schedule_parallel_tools_egress_siblings_share_one_parent() -> None: text="ok", ) with runtime_binding(None, op): - apply_engine_io_return(q, run, event, config=config, evaluate=lambda *_: []) + apply_engine_io_return(q, run, event, config=config, evaluate=lambda *_, **__: []) ends = [ e