from __future__ import annotations import logging from langchain.agents import create_agent from langchain_core.runnables import RunnableConfig from deerflow.agents.canvas_agent.prompt import build_canvas_system_prompt from deerflow.agents.canvas_agent.tools import update_artifact_tool from deerflow.agents.middlewares.clarification_middleware import ClarificationMiddleware from deerflow.agents.middlewares.dangling_tool_call_middleware import DanglingToolCallMiddleware from deerflow.agents.middlewares.loop_detection_middleware import LoopDetectionMiddleware from deerflow.agents.middlewares.title_middleware import TitleMiddleware from deerflow.agents.middlewares.tool_error_handling_middleware import ToolErrorHandlingMiddleware from deerflow.agents.thread_state import ThreadState from deerflow.config.app_config import get_app_config from deerflow.models import create_chat_model from deerflow.tools.builtins import ask_clarification_tool logger = logging.getLogger(__name__) def _get_runtime_config(config: RunnableConfig) -> dict: cfg = dict(config.get("configurable", {}) or {}) context = config.get("context", {}) or {} if isinstance(context, dict): cfg.update(context) return cfg def make_canvas_agent(config: RunnableConfig): """LangGraph graph factory for canvas mode; signature compatible with LangGraph Server.""" app_config = get_app_config() cfg = _get_runtime_config(config) requested_model = cfg.get("model_name") or cfg.get("model") if requested_model and app_config.get_model_config(requested_model): model_name = requested_model else: if requested_model: logger.warning("Canvas agent: model '%s' not found; falling back to default.", requested_model) model_name = app_config.models[0].name if app_config.models else None if model_name is None: raise ValueError("No chat models configured. Please add at least one model in config.yaml.") thinking_enabled = cfg.get("thinking_enabled", False) model_config = app_config.get_model_config(model_name) if thinking_enabled and model_config and not model_config.supports_thinking: thinking_enabled = False canvas_artifact_title = cfg.get("canvas_artifact_title") or None canvas_artifact_type = cfg.get("canvas_artifact_type") or None system_prompt = build_canvas_system_prompt( artifact_title=canvas_artifact_title, artifact_type=canvas_artifact_type, ) logger.info( "Create CanvasAgent -> model_name: %s, thinking_enabled: %s, artifact_title: %s", model_name, thinking_enabled, canvas_artifact_title, ) middlewares = [ DanglingToolCallMiddleware(), ToolErrorHandlingMiddleware(), TitleMiddleware(app_config=app_config), LoopDetectionMiddleware(), ClarificationMiddleware(), ] return create_agent( model=create_chat_model(name=model_name, thinking_enabled=thinking_enabled, app_config=app_config), tools=[update_artifact_tool, ask_clarification_tool], middleware=middlewares, system_prompt=system_prompt, state_schema=ThreadState, )