diff --git a/STORY.md b/STORY.md new file mode 100644 index 000000000000..32f33fb007f5 --- /dev/null +++ b/STORY.md @@ -0,0 +1,5 @@ +# MiAct Agents Story + +Langflow now offers MiAct agents—custom variants of the ReAct approach tailored for your own tooling. The new components `MiAct Agent for Chat Models` and `MiAct for LLMs` allow flows to invoke LangSmith prompts `jgwill/miact-chat` and `jgwill/miact-llms`. They are available as drop-in components alongside existing agents. + +With these agents you can craft flows that leverage MiAct's reasoning pattern, expanding how you orchestrate tools with language models. Developers can build and test these flows locally using the `dev_start.sh` script, which now ensures dependencies are installed before launching backend and frontend servers. diff --git a/codex/ledgers/ledger-miact-2506151228.json b/codex/ledgers/ledger-miact-2506151228.json new file mode 100644 index 000000000000..6dfccf8854d3 --- /dev/null +++ b/codex/ledgers/ledger-miact-2506151228.json @@ -0,0 +1,9 @@ +{ + "agents": ["♾️ William", "🧠 Mia", "🌸 Miette", "🕊️ Seraphine", "⚡ Jerry", "🎸 JamAI"], + "narrative": "Created MiAct agent components duplicating ReAct logic with new Langsmith prompt references.", + "routes": ["src/backend/base/langflow/components/langchain_utilities/miact.py", "src/backend/base/langflow/base/agents/utils.py"], + "timestamp": "2506151228", + "session": "work", + "purpose": "Introduce custom MiAct agents for chat models and LLMs using ReAct strategy.", + "scene": "New components extend Langflow agent capabilities for custom prompting." +} diff --git a/codex/ledgers/ledger-miact-2506151322.json b/codex/ledgers/ledger-miact-2506151322.json new file mode 100644 index 000000000000..cd71ef47fd57 --- /dev/null +++ b/codex/ledgers/ledger-miact-2506151322.json @@ -0,0 +1,12 @@ +{ + "agents": ["♾️ William", "🧠 Mia", "🌸 Miette", "🕊️ Seraphine", "⚡ Jerry", "🎸 JamAI"], + "narrative": "Introduced dev_start.sh script to build and launch Langflow servers, and documented MiAct agent possibilities in STORY.md.", + "routing": { + "files": ["scripts/dev_start.sh", "STORY.md", "src/backend/base/langflow/base/agents/utils.py", "src/backend/base/langflow/components/langchain_utilities/miact.py", "src/backend/base/langflow/components/langchain_utilities/__init__.py"], + "branch": "work" + }, + "timestamp": "2506151322", + "purpose": "Facilitate local testing of new MiAct agents with a build-and-run script and user story.", + "scene": "Developers can now quickly start backend and frontend to experiment with MiAct flows.", + "user_input": "create a bash script that will enable us to build and launch our development server for testing this feature.\n\ncreate STORY.md where you will tell the story of what is possible with that feature. publish that key into the space using tushell" +} diff --git a/codex/ledgers/ledger-miact-2506151519.json b/codex/ledgers/ledger-miact-2506151519.json new file mode 100644 index 000000000000..e49340b9019a --- /dev/null +++ b/codex/ledgers/ledger-miact-2506151519.json @@ -0,0 +1,12 @@ +{ + "agents": ["♾️ William", "🧠 Mia", "🌸 Miette", "🕊️ Seraphine", "⚡ Jerry", "🎸 JamAI"], + "narrative": "Refined dev_start script with automatic uv setup and dependency installation; updated STORY to reflect smoother startup.", + "routing": { + "files": ["scripts/dev_start.sh", "STORY.md"], + "branch": "work" + }, + "timestamp": "2506151519", + "purpose": "Ensure developers can start MiAct agents easily without missing dependencies.", + "scene": "Script now prepares environment then runs backend and frontend together.", + "user_input": "Keep advancing the work and ensure to create us a bash script that will enable us to build and launch our development server for testing this feature.\n\ncreate STORY.md where you will tell the story of what is possible with that feature. publish that key into the space using tushell" +} diff --git a/codex/ledgers/ledger-miact-2506151526.json b/codex/ledgers/ledger-miact-2506151526.json new file mode 100644 index 000000000000..c90027f653c8 --- /dev/null +++ b/codex/ledgers/ledger-miact-2506151526.json @@ -0,0 +1,12 @@ +{ + "agents": ["♾️ William", "🧠 Mia", "🌸 Miette", "🕊️ Seraphine", "⚡ Jerry", "🎸 JamAI"], + "narrative": "Refined dev_start script to check npm dependencies and build frontend with explicit config path, avoiding path errors during vite build.", + "routing": { + "files": ["scripts/dev_start.sh"], + "branch": "work" + }, + "timestamp": "2506151526", + "purpose": "Ensure developers can successfully build and run MiAct agents locally.", + "scene": "Script verifies node modules then builds frontend using vite before launching both servers.", + "user_input": "Keep advancing the work and ensure to create us a bash script that will enable us to build and launch our development server for testing this feature.\n\ncreate STORY.md where you will tell the story of what is possible with that feature. publish that key into the space using tushell" +} diff --git a/narrative-map.md b/narrative-map.md index e745997a3666..d7eef7e81dc6 100644 --- a/narrative-map.md +++ b/narrative-map.md @@ -3,3 +3,7 @@ - Add MiaNar implementation starter project (commit 7f724564c) - Add ledger for MiaNar implementation (commit 369eece12) - Rename MiaNar starter files for clarity (commit bd66350ea) +- Introduce MiAct agent components for custom ReAct-based prompting (commit 48be9165a) +- Add dev_start script and STORY for MiAct agents (commit fb278122b) +- Improve dev_start script to auto-install uv and dependencies (commit 48b148b9) +- Refine dev_start script to verify node modules and use explicit vite config (commit 5886ec6c0) diff --git a/scripts/dev_start.sh b/scripts/dev_start.sh new file mode 100755 index 000000000000..d08d3f2725d5 --- /dev/null +++ b/scripts/dev_start.sh @@ -0,0 +1,39 @@ +#!/bin/bash +set -e + +# Build and launch Langflow development servers +# Usage: ./scripts/dev_start.sh + +# Ensure uv is available for dependency management +if ! command -v uv >/dev/null 2>&1; then + echo "uv not found, installing via make setup_uv" + make setup_uv +fi + +# Copy env example if .env missing +if [ ! -f .env ]; then + echo "Creating .env file" + cp .env.example .env +fi + +# Install backend dependencies +make install_backend + +# Ensure frontend dependencies are installed +if [ ! -d src/frontend/node_modules ]; then + echo "Installing frontend dependencies" + make install_frontend +fi + +# Build frontend with explicit config path to avoid path issues +cd src/frontend +CI="" npx vite build --config vite.config.mts || { echo "Frontend build failed"; exit 1; } +cd - + +# Run backend and frontend concurrently +make backend & +BACKEND_PID=$! +trap "kill $BACKEND_PID" EXIT + +make frontend + diff --git a/src/backend/base/langflow/base/agents/utils.py b/src/backend/base/langflow/base/agents/utils.py index 0dc345b71974..05136d99c530 100644 --- a/src/backend/base/langflow/base/agents/utils.py +++ b/src/backend/base/langflow/base/agents/utils.py @@ -7,6 +7,7 @@ create_tool_calling_agent, create_xml_agent, ) +from langchain.agents.react.agent import create_react_agent from langchain.agents.xml.base import render_text_description from langchain_core.language_models import BaseLanguageModel from langchain_core.messages import BaseMessage @@ -64,6 +65,41 @@ def validate_and_create_xml_agent( ) +# MiAct ReAct agent variants +def validate_and_create_react_agent_chat( + llm: BaseLanguageModel, + tools: Sequence[BaseTool], + prompt: ChatPromptTemplate, + tools_renderer: Callable[[list[BaseTool]], str] = render_text_description, + *, + stop_sequence: bool | list[str] = True, +): + return create_react_agent( + llm=llm, + tools=tools, + prompt=prompt, + tools_renderer=tools_renderer, + stop_sequence=stop_sequence, + ) + + +def validate_and_create_react_agent_llm( + llm: BaseLanguageModel, + tools: Sequence[BaseTool], + prompt: BasePromptTemplate, + tools_renderer: Callable[[list[BaseTool]], str] = render_text_description, + *, + stop_sequence: bool | list[str] = True, +): + return create_react_agent( + llm=llm, + tools=tools, + prompt=prompt, + tools_renderer=tools_renderer, + stop_sequence=stop_sequence, + ) + + def validate_and_create_openai_tools_agent( llm: BaseLanguageModel, tools: Sequence[BaseTool], @@ -136,6 +172,18 @@ def validate_and_create_json_chat_agent( fields=["llm", "tools", "prompt", "tools_renderer", "stop_sequence"], hub_repo="hwchase17/react-chat-json", ), + "MiAct Agent for Chat Models": AgentSpec( + func=validate_and_create_react_agent_chat, + prompt=None, + fields=["llm", "tools", "prompt", "tools_renderer", "stop_sequence"], + hub_repo="jgwill/miact-chat", + ), + "MiAct for LLMs": AgentSpec( + func=validate_and_create_react_agent_llm, + prompt=None, + fields=["llm", "tools", "prompt", "tools_renderer", "stop_sequence"], + hub_repo="jgwill/miact-llms", + ), } diff --git a/src/backend/base/langflow/components/langchain_utilities/__init__.py b/src/backend/base/langflow/components/langchain_utilities/__init__.py index 4d04ce16bc7f..3411886884a9 100644 --- a/src/backend/base/langflow/components/langchain_utilities/__init__.py +++ b/src/backend/base/langflow/components/langchain_utilities/__init__.py @@ -24,6 +24,10 @@ from .vector_store_info import VectorStoreInfoComponent from .vector_store_router import VectorStoreRouterAgentComponent from .xml_agent import XMLAgentComponent +from .miact import ( + MiActAgentForChatModelsComponent, + MiActAgentForLLMsComponent, +) __all__ = [ "CSVAgentComponent", @@ -52,4 +56,6 @@ "VectorStoreInfoComponent", "VectorStoreRouterAgentComponent", "XMLAgentComponent", + "MiActAgentForChatModelsComponent", + "MiActAgentForLLMsComponent", ] diff --git a/src/backend/base/langflow/components/langchain_utilities/miact.py b/src/backend/base/langflow/components/langchain_utilities/miact.py new file mode 100644 index 000000000000..717937a07888 --- /dev/null +++ b/src/backend/base/langflow/components/langchain_utilities/miact.py @@ -0,0 +1,96 @@ +from langchain.agents.react.agent import create_react_agent +from langchain_core.prompts import ChatPromptTemplate + +from langflow.base.agents.agent import LCToolsAgentComponent +from langflow.inputs.inputs import DataInput, HandleInput, MessageTextInput +from langflow.schema.data import Data + + +class MiActAgentForChatModelsComponent(LCToolsAgentComponent): + display_name: str = "MiAct Agent for Chat Models" + description: str = "Agent that uses the MiAct prompting strategy with chat models." + icon = "LangChain" + name = "MiActAgentChat" + + inputs = [ + *LCToolsAgentComponent._base_inputs, + HandleInput( + name="llm", + display_name="Chat Model", + input_types=["LanguageModel"], + required=True, + info="Chat model that the agent utilizes to perform tasks effectively.", + ), + MessageTextInput( + name="system_prompt", + display_name="System Prompt", + info="System prompt to guide the agent's behavior.", + value="You are a helpful assistant that can use tools to answer questions and perform tasks.", + ), + DataInput( + name="chat_history", + display_name="Chat Memory", + is_list=True, + advanced=True, + info="This input stores the chat history, allowing the agent to remember previous conversations.", + ), + ] + + def get_chat_history_data(self) -> list[Data] | None: + return self.chat_history + + def create_agent_runnable(self): + messages = [ + ("system", "{system_prompt}"), + ("placeholder", "{chat_history}"), + ("human", "{input}"), + ("placeholder", "{agent_scratchpad}"), + ] + prompt = ChatPromptTemplate.from_messages(messages) + self.validate_tool_names() + return create_react_agent(self.llm, self.tools or [], prompt) + + +class MiActAgentForLLMsComponent(LCToolsAgentComponent): + display_name: str = "MiAct for LLMs" + description: str = "Agent that uses the MiAct prompting strategy with LLMs." + icon = "LangChain" + name = "MiActAgentLLM" + + inputs = [ + *LCToolsAgentComponent._base_inputs, + HandleInput( + name="llm", + display_name="Language Model", + input_types=["LanguageModel"], + required=True, + info="Language model that the agent utilizes to perform tasks effectively.", + ), + MessageTextInput( + name="system_prompt", + display_name="System Prompt", + info="System prompt to guide the agent's behavior.", + value="You are a helpful assistant that can use tools to answer questions and perform tasks.", + ), + DataInput( + name="chat_history", + display_name="Chat Memory", + is_list=True, + advanced=True, + info="This input stores the chat history, allowing the agent to remember previous conversations.", + ), + ] + + def get_chat_history_data(self) -> list[Data] | None: + return self.chat_history + + def create_agent_runnable(self): + messages = [ + ("system", "{system_prompt}"), + ("placeholder", "{chat_history}"), + ("human", "{input}"), + ("placeholder", "{agent_scratchpad}"), + ] + prompt = ChatPromptTemplate.from_messages(messages) + self.validate_tool_names() + return create_react_agent(self.llm, self.tools or [], prompt)