Skip to content

Commit 018c7cf

Browse files
feat: implement agent llm messages limit handling
1 parent 240a252 commit 018c7cf

7 files changed

Lines changed: 43 additions & 22 deletions

File tree

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "uipath-langchain"
3-
version = "0.4.4"
3+
version = "0.4.5"
44
description = "Python SDK that enables developers to build and deploy LangGraph agents to the UiPath Cloud Platform"
55
readme = { file = "README.md", content-type = "text/markdown" }
66
requires-python = ">=3.11"

src/uipath_langchain/agent/exceptions/exceptions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
"""Exceptions for the basic agent loop."""
1+
"""Exceptions for the agent graph."""
22

33
from uipath.runtime.errors import UiPathRuntimeError
44

src/uipath_langchain/agent/react/agent.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import os
21
from typing import Callable, Sequence, Type, TypeVar, cast
32

43
from langchain_core.language_models import BaseChatModel
@@ -72,8 +71,6 @@ def create_agent(
7271
if config is None:
7372
config = AgentGraphConfig()
7473

75-
os.environ["LANGCHAIN_RECURSION_LIMIT"] = str(config.recursion_limit)
76-
7774
agent_tools = list(tools)
7875
flow_control_tools: list[BaseTool] = (
7976
[] if config.is_conversational else create_flow_control_tools(output_schema)
@@ -113,7 +110,11 @@ def create_agent(
113110
builder.add_edge(START, AgentGraphNode.INIT)
114111

115112
llm_node = create_llm_node(
116-
model, llm_tools, config.thinking_messages_limit, config.is_conversational
113+
model,
114+
llm_tools,
115+
config.is_conversational,
116+
config.llm_messages_limit,
117+
config.thinking_messages_limit,
117118
)
118119
llm_with_guardrails_subgraph = create_llm_guardrails_subgraph(
119120
(AgentGraphNode.LLM, llm_node), guardrails
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
MAX_CONSECUTIVE_THINKING_MESSAGES = 0
1+
DEFAULT_MAX_CONSECUTIVE_THINKING_MESSAGES = 0
2+
DEFAULT_MAX_LLM_MESSAGES = 25

src/uipath_langchain/agent/react/llm_node.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,13 @@
55
from langchain_core.language_models import BaseChatModel
66
from langchain_core.messages import AIMessage, AnyMessage
77
from langchain_core.tools import BaseTool
8+
from uipath.runtime.errors import UiPathErrorCategory, UiPathErrorCode
89

9-
from .constants import MAX_CONSECUTIVE_THINKING_MESSAGES
10+
from ..exceptions import AgentTerminationException
11+
from .constants import (
12+
DEFAULT_MAX_CONSECUTIVE_THINKING_MESSAGES,
13+
DEFAULT_MAX_LLM_MESSAGES,
14+
)
1015
from .types import AgentGraphState
1116
from .utils import count_consecutive_thinking_messages
1217

@@ -36,8 +41,9 @@ def _get_required_tool_choice_by_model(
3641
def create_llm_node(
3742
model: BaseChatModel,
3843
tools: Sequence[BaseTool] | None = None,
39-
thinking_messages_limit: int = MAX_CONSECUTIVE_THINKING_MESSAGES,
4044
is_conversational: bool = False,
45+
llm_messages_limit: int = DEFAULT_MAX_LLM_MESSAGES,
46+
thinking_messages_limit: int = DEFAULT_MAX_CONSECUTIVE_THINKING_MESSAGES,
4147
):
4248
"""Create LLM node with dynamic tool_choice enforcement.
4349
@@ -47,6 +53,8 @@ def create_llm_node(
4753
Args:
4854
model: The chat model to use
4955
tools: Available tools to bind
56+
is_conversational: Whether this is a conversational agent
57+
llm_messages_limit: Maximum number of LLM calls allowed per execution
5058
thinking_messages_limit: Max consecutive LLM responses without tool calls
5159
before enforcing tool usage. 0 = force tools every time.
5260
"""
@@ -57,6 +65,15 @@ def create_llm_node(
5765
async def llm_node(state: AgentGraphState):
5866
messages: list[AnyMessage] = state.messages
5967

68+
agent_ai_messages = sum(1 for msg in messages if isinstance(msg, AIMessage))
69+
if agent_ai_messages >= llm_messages_limit:
70+
raise AgentTerminationException(
71+
code=UiPathErrorCode.EXECUTION_ERROR,
72+
title=f"Maximum iterations of '{llm_messages_limit}' reached.",
73+
detail="Verify the agent's trajectory or consider increasing the max iterations in the agent's settings.",
74+
category=UiPathErrorCategory.USER,
75+
)
76+
6077
consecutive_thinking_messages = count_consecutive_thinking_messages(messages)
6178

6279
if (

src/uipath_langchain/agent/react/types.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,15 @@ class AgentGraphNode(StrEnum):
5353

5454

5555
class AgentGraphConfig(BaseModel):
56-
recursion_limit: int = Field(
57-
default=50, ge=1, description="Maximum recursion limit for the agent graph"
56+
llm_messages_limit: int = Field(
57+
default=25,
58+
ge=1,
59+
description="Maximum number of LLM calls allowed per agent execution",
5860
)
5961
thinking_messages_limit: int = Field(
6062
default=0,
6163
ge=0,
62-
description="Max consecutive thinking messages before enforcing tool usage. 0 = force tools every time.",
64+
description="Max consecutive thinking messages before enforcing tool calling. 0 = force tool calling every time.",
6365
)
6466
is_conversational: bool = Field(
6567
default=False, description="If set, creates a graph for conversational agents"

uv.lock

Lines changed: 10 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)