Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions backend/packages/harness/deerflow/agents/lead_agent/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -314,13 +314,18 @@ def _build_middlewares(
return middlewares


def make_lead_agent(config: RunnableConfig, app_config: AppConfig | None = None):
def make_lead_agent(config: RunnableConfig):
"""LangGraph graph factory; keep the signature compatible with LangGraph Server."""
return _make_lead_agent(config, app_config=get_app_config())


def _make_lead_agent(config: RunnableConfig, *, app_config: AppConfig):
# Lazy import to avoid circular dependency
from deerflow.tools import get_available_tools
from deerflow.tools.builtins import setup_agent

cfg = _get_runtime_config(config)
resolved_app_config = app_config or get_app_config()
resolved_app_config = app_config

thinking_enabled = cfg.get("thinking_enabled", True)
reasoning_effort = cfg.get("reasoning_effort", None)
Expand Down
39 changes: 39 additions & 0 deletions backend/tests/test_lead_agent_model_resolution.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from __future__ import annotations

import inspect
from unittest.mock import MagicMock

import pytest
Expand Down Expand Up @@ -33,6 +34,44 @@ def _make_model(name: str, *, supports_thinking: bool) -> ModelConfig:
)


def test_make_lead_agent_signature_matches_langgraph_server_factory_abi():
assert list(inspect.signature(lead_agent_module.make_lead_agent).parameters) == ["config"]


def test_internal_make_lead_agent_uses_explicit_app_config(monkeypatch):
app_config = _make_app_config([_make_model("explicit-model", supports_thinking=False)])

import deerflow.tools as tools_module

def _raise_get_app_config():
raise AssertionError("ambient get_app_config() must not be used when app_config is explicit")

monkeypatch.setattr(lead_agent_module, "get_app_config", _raise_get_app_config)
monkeypatch.setattr(tools_module, "get_available_tools", lambda **kwargs: [])
monkeypatch.setattr(lead_agent_module, "_build_middlewares", lambda config, model_name, agent_name=None, **kwargs: [])

captured: dict[str, object] = {}

def _fake_create_chat_model(*, name, thinking_enabled, reasoning_effort=None, app_config=None):
captured["name"] = name
captured["app_config"] = app_config
return object()

monkeypatch.setattr(lead_agent_module, "create_chat_model", _fake_create_chat_model)
monkeypatch.setattr(lead_agent_module, "create_agent", lambda **kwargs: kwargs)

result = lead_agent_module._make_lead_agent(
{"configurable": {"model_name": "explicit-model"}},
app_config=app_config,
)

assert captured == {
"name": "explicit-model",
"app_config": app_config,
}
assert result["model"] is not None


def test_resolve_model_name_falls_back_to_default(monkeypatch, caplog):
app_config = _make_app_config(
[
Expand Down
Loading