jl-ecms-client 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- jl_ecms_client-0.2.0.dist-info/METADATA +295 -0
- jl_ecms_client-0.2.0.dist-info/RECORD +51 -0
- jl_ecms_client-0.2.0.dist-info/WHEEL +5 -0
- jl_ecms_client-0.2.0.dist-info/licenses/LICENSE +190 -0
- jl_ecms_client-0.2.0.dist-info/top_level.txt +1 -0
- mirix/client/__init__.py +72 -0
- mirix/client/client.py +2594 -0
- mirix/client/remote_client.py +1136 -0
- mirix/helpers/__init__.py +1 -0
- mirix/helpers/converters.py +429 -0
- mirix/helpers/datetime_helpers.py +90 -0
- mirix/helpers/json_helpers.py +47 -0
- mirix/helpers/message_helpers.py +74 -0
- mirix/helpers/tool_rule_solver.py +166 -0
- mirix/schemas/__init__.py +1 -0
- mirix/schemas/agent.py +400 -0
- mirix/schemas/block.py +188 -0
- mirix/schemas/cloud_file_mapping.py +29 -0
- mirix/schemas/embedding_config.py +114 -0
- mirix/schemas/enums.py +69 -0
- mirix/schemas/environment_variables.py +82 -0
- mirix/schemas/episodic_memory.py +170 -0
- mirix/schemas/file.py +57 -0
- mirix/schemas/health.py +10 -0
- mirix/schemas/knowledge_vault.py +181 -0
- mirix/schemas/llm_config.py +187 -0
- mirix/schemas/memory.py +318 -0
- mirix/schemas/message.py +1315 -0
- mirix/schemas/mirix_base.py +107 -0
- mirix/schemas/mirix_message.py +411 -0
- mirix/schemas/mirix_message_content.py +230 -0
- mirix/schemas/mirix_request.py +39 -0
- mirix/schemas/mirix_response.py +183 -0
- mirix/schemas/openai/__init__.py +1 -0
- mirix/schemas/openai/chat_completion_request.py +122 -0
- mirix/schemas/openai/chat_completion_response.py +144 -0
- mirix/schemas/openai/chat_completions.py +127 -0
- mirix/schemas/openai/embedding_response.py +11 -0
- mirix/schemas/openai/openai.py +229 -0
- mirix/schemas/organization.py +38 -0
- mirix/schemas/procedural_memory.py +151 -0
- mirix/schemas/providers.py +816 -0
- mirix/schemas/resource_memory.py +134 -0
- mirix/schemas/sandbox_config.py +132 -0
- mirix/schemas/semantic_memory.py +162 -0
- mirix/schemas/source.py +96 -0
- mirix/schemas/step.py +53 -0
- mirix/schemas/tool.py +241 -0
- mirix/schemas/tool_rule.py +209 -0
- mirix/schemas/usage.py +31 -0
- mirix/schemas/user.py +67 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from typing import List, Optional, Union
|
|
3
|
+
|
|
4
|
+
from pydantic import BaseModel, Field
|
|
5
|
+
|
|
6
|
+
from mirix.schemas.enums import ToolRuleType
|
|
7
|
+
from mirix.schemas.tool_rule import (
|
|
8
|
+
BaseToolRule,
|
|
9
|
+
ChildToolRule,
|
|
10
|
+
ConditionalToolRule,
|
|
11
|
+
InitToolRule,
|
|
12
|
+
TerminalToolRule,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ToolRuleValidationError(Exception):
|
|
17
|
+
"""Custom exception for tool rule validation errors in ToolRulesSolver."""
|
|
18
|
+
|
|
19
|
+
def __init__(self, message: str):
|
|
20
|
+
super().__init__(f"ToolRuleValidationError: {message}")
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class ToolRulesSolver(BaseModel):
|
|
24
|
+
init_tool_rules: List[InitToolRule] = Field(
|
|
25
|
+
default_factory=list,
|
|
26
|
+
description="Initial tool rules to be used at the start of tool execution.",
|
|
27
|
+
)
|
|
28
|
+
tool_rules: List[Union[ChildToolRule, ConditionalToolRule]] = Field(
|
|
29
|
+
default_factory=list,
|
|
30
|
+
description="Standard tool rules for controlling execution sequence and allowed transitions.",
|
|
31
|
+
)
|
|
32
|
+
terminal_tool_rules: List[TerminalToolRule] = Field(
|
|
33
|
+
default_factory=list,
|
|
34
|
+
description="Terminal tool rules that end the agent loop if called.",
|
|
35
|
+
)
|
|
36
|
+
last_tool_name: Optional[str] = Field(
|
|
37
|
+
None, description="The most recent tool used, updated with each tool call."
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
def __init__(self, tool_rules: List[BaseToolRule], **kwargs):
|
|
41
|
+
super().__init__(**kwargs)
|
|
42
|
+
# Separate the provided tool rules into init, standard, and terminal categories
|
|
43
|
+
for rule in tool_rules:
|
|
44
|
+
if rule.type == ToolRuleType.run_first:
|
|
45
|
+
assert isinstance(rule, InitToolRule)
|
|
46
|
+
self.init_tool_rules.append(rule)
|
|
47
|
+
elif rule.type == ToolRuleType.constrain_child_tools:
|
|
48
|
+
assert isinstance(rule, ChildToolRule)
|
|
49
|
+
self.tool_rules.append(rule)
|
|
50
|
+
elif rule.type == ToolRuleType.conditional:
|
|
51
|
+
assert isinstance(rule, ConditionalToolRule)
|
|
52
|
+
self.validate_conditional_tool(rule)
|
|
53
|
+
self.tool_rules.append(rule)
|
|
54
|
+
elif rule.type == ToolRuleType.exit_loop:
|
|
55
|
+
assert isinstance(rule, TerminalToolRule)
|
|
56
|
+
self.terminal_tool_rules.append(rule)
|
|
57
|
+
|
|
58
|
+
def update_tool_usage(self, tool_name: str):
|
|
59
|
+
"""Update the internal state to track the last tool called."""
|
|
60
|
+
self.last_tool_name = tool_name
|
|
61
|
+
|
|
62
|
+
def get_allowed_tool_names(
|
|
63
|
+
self, error_on_empty: bool = False, last_function_response: Optional[str] = None
|
|
64
|
+
) -> List[str]:
|
|
65
|
+
"""Get a list of tool names allowed based on the last tool called."""
|
|
66
|
+
if self.last_tool_name is None:
|
|
67
|
+
# Use initial tool rules if no tool has been called yet
|
|
68
|
+
return [rule.tool_name for rule in self.init_tool_rules]
|
|
69
|
+
else:
|
|
70
|
+
# Find a matching ToolRule for the last tool used
|
|
71
|
+
current_rule = next(
|
|
72
|
+
(
|
|
73
|
+
rule
|
|
74
|
+
for rule in self.tool_rules
|
|
75
|
+
if rule.tool_name == self.last_tool_name
|
|
76
|
+
),
|
|
77
|
+
None,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
if current_rule is None:
|
|
81
|
+
if error_on_empty:
|
|
82
|
+
raise ValueError(f"No tool rule found for {self.last_tool_name}")
|
|
83
|
+
return []
|
|
84
|
+
|
|
85
|
+
# If the current rule is a conditional tool rule, use the LLM response to
|
|
86
|
+
# determine which child tool to use
|
|
87
|
+
if isinstance(current_rule, ConditionalToolRule):
|
|
88
|
+
if not last_function_response:
|
|
89
|
+
raise ValueError(
|
|
90
|
+
"Conditional tool rule requires an LLM response to determine which child tool to use"
|
|
91
|
+
)
|
|
92
|
+
next_tool = self.evaluate_conditional_tool(
|
|
93
|
+
current_rule, last_function_response
|
|
94
|
+
)
|
|
95
|
+
return [next_tool] if next_tool else []
|
|
96
|
+
|
|
97
|
+
return current_rule.children if current_rule.children else []
|
|
98
|
+
|
|
99
|
+
def is_terminal_tool(self, tool_name: str) -> bool:
|
|
100
|
+
"""Check if the tool is defined as a terminal tool in the terminal tool rules."""
|
|
101
|
+
return any(rule.tool_name == tool_name for rule in self.terminal_tool_rules)
|
|
102
|
+
|
|
103
|
+
def has_children_tools(self, tool_name):
|
|
104
|
+
"""Check if the tool has children tools"""
|
|
105
|
+
return any(rule.tool_name == tool_name for rule in self.tool_rules)
|
|
106
|
+
|
|
107
|
+
def validate_conditional_tool(self, rule: ConditionalToolRule):
|
|
108
|
+
"""
|
|
109
|
+
Validate a conditional tool rule
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
rule (ConditionalToolRule): The conditional tool rule to validate
|
|
113
|
+
|
|
114
|
+
Raises:
|
|
115
|
+
ToolRuleValidationError: If the rule is invalid
|
|
116
|
+
"""
|
|
117
|
+
if len(rule.child_output_mapping) == 0:
|
|
118
|
+
raise ToolRuleValidationError(
|
|
119
|
+
"Conditional tool rule must have at least one child tool."
|
|
120
|
+
)
|
|
121
|
+
return True
|
|
122
|
+
|
|
123
|
+
def evaluate_conditional_tool(
|
|
124
|
+
self, tool: ConditionalToolRule, last_function_response: str
|
|
125
|
+
) -> str:
|
|
126
|
+
"""
|
|
127
|
+
Parse function response to determine which child tool to use based on the mapping
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
tool (ConditionalToolRule): The conditional tool rule
|
|
131
|
+
last_function_response (str): The function response in JSON format
|
|
132
|
+
|
|
133
|
+
Returns:
|
|
134
|
+
str: The name of the child tool to use next
|
|
135
|
+
"""
|
|
136
|
+
json_response = json.loads(last_function_response)
|
|
137
|
+
function_output = json_response["message"]
|
|
138
|
+
|
|
139
|
+
# Try to match the function output with a mapping key
|
|
140
|
+
for key in tool.child_output_mapping:
|
|
141
|
+
# Convert function output to match key type for comparison
|
|
142
|
+
if isinstance(key, bool):
|
|
143
|
+
typed_output = function_output.lower() == "true"
|
|
144
|
+
elif isinstance(key, int):
|
|
145
|
+
try:
|
|
146
|
+
typed_output = int(function_output)
|
|
147
|
+
except (ValueError, TypeError):
|
|
148
|
+
continue
|
|
149
|
+
elif isinstance(key, float):
|
|
150
|
+
try:
|
|
151
|
+
typed_output = float(function_output)
|
|
152
|
+
except (ValueError, TypeError):
|
|
153
|
+
continue
|
|
154
|
+
else: # string
|
|
155
|
+
if function_output == "True" or function_output == "False":
|
|
156
|
+
typed_output = function_output.lower()
|
|
157
|
+
elif function_output == "None":
|
|
158
|
+
typed_output = None
|
|
159
|
+
else:
|
|
160
|
+
typed_output = function_output
|
|
161
|
+
|
|
162
|
+
if typed_output == key:
|
|
163
|
+
return tool.child_output_mapping[key]
|
|
164
|
+
|
|
165
|
+
# If no match found, use default
|
|
166
|
+
return tool.default_child
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Mirix schemas package
|
mirix/schemas/agent.py
ADDED
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
from typing import Any, Dict, List, Optional, Union
|
|
3
|
+
|
|
4
|
+
from pydantic import BaseModel, Field, field_validator
|
|
5
|
+
|
|
6
|
+
from mirix.constants import DEFAULT_EMBEDDING_CHUNK_SIZE
|
|
7
|
+
from mirix.helpers import ToolRulesSolver
|
|
8
|
+
from mirix.schemas.block import CreateBlock
|
|
9
|
+
from mirix.schemas.embedding_config import EmbeddingConfig
|
|
10
|
+
from mirix.schemas.llm_config import LLMConfig
|
|
11
|
+
from mirix.schemas.memory import Memory
|
|
12
|
+
from mirix.schemas.message import Message, MessageCreate
|
|
13
|
+
from mirix.schemas.mirix_base import OrmMetadataBase
|
|
14
|
+
from mirix.schemas.openai.chat_completion_response import UsageStatistics
|
|
15
|
+
from mirix.schemas.tool import Tool
|
|
16
|
+
from mirix.schemas.tool_rule import ToolRule
|
|
17
|
+
from mirix.utils import create_random_username
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class AgentType(str, Enum):
|
|
21
|
+
"""
|
|
22
|
+
Enum to represent the type of agent.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
coder_agent = "coder_agent"
|
|
26
|
+
chat_agent = "chat_agent"
|
|
27
|
+
reflexion_agent = "reflexion_agent"
|
|
28
|
+
background_agent = "background_agent"
|
|
29
|
+
episodic_memory_agent = "episodic_memory_agent"
|
|
30
|
+
procedural_memory_agent = "procedural_memory_agent"
|
|
31
|
+
resource_memory_agent = "resource_memory_agent"
|
|
32
|
+
knowledge_vault_memory_agent = "knowledge_vault_memory_agent"
|
|
33
|
+
meta_memory_agent = "meta_memory_agent"
|
|
34
|
+
semantic_memory_agent = "semantic_memory_agent"
|
|
35
|
+
core_memory_agent = "core_memory_agent"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class AgentState(OrmMetadataBase, validate_assignment=True):
|
|
39
|
+
"""
|
|
40
|
+
Representation of an agent's state. This is the state of the agent at a given time, and is persisted in the DB backend. The state has all the information needed to recreate a persisted agent.
|
|
41
|
+
|
|
42
|
+
Parameters:
|
|
43
|
+
id (str): The unique identifier of the agent.
|
|
44
|
+
name (str): The name of the agent (must be unique to the user).
|
|
45
|
+
created_at (datetime): The datetime the agent was created.
|
|
46
|
+
memory (Memory): The in-context memory of the agent.
|
|
47
|
+
tools (List[str]): The tools used by the agent. This includes any memory editing functions specified in `memory`.
|
|
48
|
+
system (str): The system prompt used by the agent.
|
|
49
|
+
llm_config (LLMConfig): The LLM configuration used by the agent.
|
|
50
|
+
embedding_config (EmbeddingConfig): The embedding configuration used by the agent.
|
|
51
|
+
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
__id_prefix__ = "agent"
|
|
55
|
+
|
|
56
|
+
# NOTE: this is what is returned to the client and also what is used to initialize `Agent`
|
|
57
|
+
id: str = Field(..., description="The id of the agent. Assigned by the database.")
|
|
58
|
+
name: str = Field(..., description="The name of the agent.")
|
|
59
|
+
# tool rules
|
|
60
|
+
tool_rules: Optional[List[ToolRule]] = Field(
|
|
61
|
+
default=None, description="The list of tool rules."
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
# in-context memory
|
|
65
|
+
message_ids: Optional[List[str]] = Field(
|
|
66
|
+
default=None,
|
|
67
|
+
description="The ids of the messages in the agent's in-context memory.",
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
# system prompt
|
|
71
|
+
system: str = Field(..., description="The system prompt used by the agent.")
|
|
72
|
+
|
|
73
|
+
# agent configuration
|
|
74
|
+
agent_type: AgentType = Field(..., description="The type of agent.")
|
|
75
|
+
|
|
76
|
+
# llm information
|
|
77
|
+
llm_config: LLMConfig = Field(
|
|
78
|
+
..., description="The LLM configuration used by the agent."
|
|
79
|
+
)
|
|
80
|
+
embedding_config: EmbeddingConfig = Field(
|
|
81
|
+
..., description="The embedding configuration used by the agent."
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
# This is an object representing the in-process state of a running `Agent`
|
|
85
|
+
# Field in this object can be theoretically edited by tools, and will be persisted by the ORM
|
|
86
|
+
organization_id: Optional[str] = Field(
|
|
87
|
+
None,
|
|
88
|
+
description="The unique identifier of the organization associated with the agent.",
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
description: Optional[str] = Field(
|
|
92
|
+
None, description="The description of the agent."
|
|
93
|
+
)
|
|
94
|
+
parent_id: Optional[str] = Field(
|
|
95
|
+
None, description="The parent agent ID (for sub-agents in a meta-agent)."
|
|
96
|
+
)
|
|
97
|
+
children: Optional[List["AgentState"]] = Field(
|
|
98
|
+
default=None, description="Child agents (sub-agents) if this is a parent agent."
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
memory: Memory = Field(..., description="The in-context memory of the agent.")
|
|
102
|
+
tools: List[Tool] = Field(..., description="The tools used by the agent.")
|
|
103
|
+
mcp_tools: Optional[List[str]] = Field(
|
|
104
|
+
default_factory=list,
|
|
105
|
+
description="List of connected MCP server names (e.g., ['gmail-native'])",
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
class CreateAgent(BaseModel, validate_assignment=True): #
|
|
110
|
+
# all optional as server can generate defaults
|
|
111
|
+
name: str = Field(
|
|
112
|
+
default_factory=lambda: create_random_username(),
|
|
113
|
+
description="The name of the agent.",
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
# memory creation
|
|
117
|
+
memory_blocks: Optional[List[CreateBlock]] = Field(
|
|
118
|
+
None,
|
|
119
|
+
description="The blocks to create in the agent's in-context memory.",
|
|
120
|
+
)
|
|
121
|
+
# TODO: This is a legacy field and should be removed ASAP to force `tool_ids` usage
|
|
122
|
+
tools: Optional[List[str]] = Field(None, description="The tools used by the agent.")
|
|
123
|
+
tool_ids: Optional[List[str]] = Field(
|
|
124
|
+
None, description="The ids of the tools used by the agent."
|
|
125
|
+
)
|
|
126
|
+
tool_rules: Optional[List[ToolRule]] = Field(
|
|
127
|
+
None, description="The tool rules governing the agent."
|
|
128
|
+
)
|
|
129
|
+
system: Optional[str] = Field(
|
|
130
|
+
None, description="The system prompt used by the agent."
|
|
131
|
+
)
|
|
132
|
+
agent_type: AgentType = Field(
|
|
133
|
+
default_factory=lambda: AgentType.chat_agent, description="The type of agent."
|
|
134
|
+
)
|
|
135
|
+
llm_config: Optional[LLMConfig] = Field(
|
|
136
|
+
None, description="The LLM configuration used by the agent."
|
|
137
|
+
)
|
|
138
|
+
embedding_config: Optional[EmbeddingConfig] = Field(
|
|
139
|
+
None, description="The embedding configuration used by the agent."
|
|
140
|
+
)
|
|
141
|
+
# Note: if this is None, then we'll populate with the standard "more human than human" initial message sequence
|
|
142
|
+
# If the client wants to make this empty, then the client can set the arg to an empty list
|
|
143
|
+
initial_message_sequence: Optional[List[MessageCreate]] = Field(
|
|
144
|
+
None,
|
|
145
|
+
description="The initial set of messages to put in the agent's in-context memory.",
|
|
146
|
+
)
|
|
147
|
+
include_base_tools: bool = Field(
|
|
148
|
+
True,
|
|
149
|
+
description="If true, attaches the Mirix core tools (e.g. archival_memory and core_memory related functions).",
|
|
150
|
+
)
|
|
151
|
+
include_multi_agent_tools: bool = Field(
|
|
152
|
+
False,
|
|
153
|
+
description="If true, attaches the Mirix multi-agent tools (e.g. sending a message to another agent).",
|
|
154
|
+
)
|
|
155
|
+
parent_id: Optional[str] = Field(
|
|
156
|
+
None, description="The parent agent ID (for sub-agents in a meta-agent)."
|
|
157
|
+
)
|
|
158
|
+
model: Optional[str] = Field(
|
|
159
|
+
None,
|
|
160
|
+
description="The LLM configuration handle used by the agent, specified in the format "
|
|
161
|
+
"provider/model-name, as an alternative to specifying llm_config.",
|
|
162
|
+
)
|
|
163
|
+
embedding: Optional[str] = Field(
|
|
164
|
+
None,
|
|
165
|
+
description="The embedding configuration handle used by the agent, specified in the format provider/model-name.",
|
|
166
|
+
)
|
|
167
|
+
context_window_limit: Optional[int] = Field(
|
|
168
|
+
None, description="The context window limit used by the agent."
|
|
169
|
+
)
|
|
170
|
+
embedding_chunk_size: Optional[int] = Field(
|
|
171
|
+
DEFAULT_EMBEDDING_CHUNK_SIZE,
|
|
172
|
+
description="The embedding chunk size used by the agent.",
|
|
173
|
+
)
|
|
174
|
+
from_template: Optional[str] = Field(
|
|
175
|
+
None, description="The template id used to configure the agent"
|
|
176
|
+
)
|
|
177
|
+
template: bool = Field(False, description="Whether the agent is a template")
|
|
178
|
+
project: Optional[str] = Field(
|
|
179
|
+
None, description="The project slug that the agent will be associated with."
|
|
180
|
+
)
|
|
181
|
+
tool_exec_environment_variables: Optional[Dict[str, str]] = Field(
|
|
182
|
+
None,
|
|
183
|
+
description="The environment variables for tool execution specific to this agent.",
|
|
184
|
+
)
|
|
185
|
+
memory_variables: Optional[Dict[str, str]] = Field(
|
|
186
|
+
None, description="The variables that should be set for the agent."
|
|
187
|
+
)
|
|
188
|
+
mcp_tools: Optional[List[str]] = Field(
|
|
189
|
+
None, description="List of MCP server names to connect to this agent."
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
@field_validator("name")
|
|
193
|
+
@classmethod
|
|
194
|
+
def validate_name(cls, name: str) -> str:
|
|
195
|
+
"""Validate the requested new agent name (prevent bad inputs)"""
|
|
196
|
+
|
|
197
|
+
import re
|
|
198
|
+
|
|
199
|
+
if not name:
|
|
200
|
+
# don't check if not provided
|
|
201
|
+
return name
|
|
202
|
+
|
|
203
|
+
# TODO: this check should also be added to other model (e.g. User.name)
|
|
204
|
+
# Length check
|
|
205
|
+
if not (1 <= len(name) <= 50):
|
|
206
|
+
raise ValueError("Name length must be between 1 and 50 characters.")
|
|
207
|
+
|
|
208
|
+
# Regex for allowed characters (alphanumeric, spaces, hyphens, underscores)
|
|
209
|
+
if not re.match("^[A-Za-z0-9 _-]+$", name):
|
|
210
|
+
raise ValueError("Name contains invalid characters.")
|
|
211
|
+
|
|
212
|
+
# Further checks can be added here...
|
|
213
|
+
# TODO
|
|
214
|
+
|
|
215
|
+
return name
|
|
216
|
+
|
|
217
|
+
@field_validator("model")
|
|
218
|
+
@classmethod
|
|
219
|
+
def validate_model(cls, model: Optional[str]) -> Optional[str]:
|
|
220
|
+
if not model:
|
|
221
|
+
return model
|
|
222
|
+
|
|
223
|
+
provider_name, model_name = model.split("/", 1)
|
|
224
|
+
if not provider_name or not model_name:
|
|
225
|
+
raise ValueError(
|
|
226
|
+
"The llm config handle should be in the format provider/model-name"
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
return model
|
|
230
|
+
|
|
231
|
+
@field_validator("embedding")
|
|
232
|
+
@classmethod
|
|
233
|
+
def validate_embedding(cls, embedding: Optional[str]) -> Optional[str]:
|
|
234
|
+
if not embedding:
|
|
235
|
+
return embedding
|
|
236
|
+
|
|
237
|
+
provider_name, embedding_name = embedding.split("/", 1)
|
|
238
|
+
if not provider_name or not embedding_name:
|
|
239
|
+
raise ValueError(
|
|
240
|
+
"The embedding config handle should be in the format provider/model-name"
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
return embedding
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
class UpdateAgent(BaseModel):
|
|
247
|
+
name: Optional[str] = Field(None, description="The name of the agent.")
|
|
248
|
+
tool_ids: Optional[List[str]] = Field(
|
|
249
|
+
None, description="The ids of the tools used by the agent."
|
|
250
|
+
)
|
|
251
|
+
block_ids: Optional[List[str]] = Field(
|
|
252
|
+
None, description="The ids of the blocks used by the agent."
|
|
253
|
+
)
|
|
254
|
+
system: Optional[str] = Field(
|
|
255
|
+
None, description="The system prompt used by the agent."
|
|
256
|
+
)
|
|
257
|
+
tool_rules: Optional[List[ToolRule]] = Field(
|
|
258
|
+
None, description="The tool rules governing the agent."
|
|
259
|
+
)
|
|
260
|
+
llm_config: Optional[LLMConfig] = Field(
|
|
261
|
+
None, description="The LLM configuration used by the agent."
|
|
262
|
+
)
|
|
263
|
+
embedding_config: Optional[EmbeddingConfig] = Field(
|
|
264
|
+
None, description="The embedding configuration used by the agent."
|
|
265
|
+
)
|
|
266
|
+
message_ids: Optional[List[str]] = Field(
|
|
267
|
+
None, description="The ids of the messages in the agent's in-context memory."
|
|
268
|
+
)
|
|
269
|
+
description: Optional[str] = Field(
|
|
270
|
+
None, description="The description of the agent."
|
|
271
|
+
)
|
|
272
|
+
parent_id: Optional[str] = Field(
|
|
273
|
+
None, description="The parent agent ID (for sub-agents in a meta-agent)."
|
|
274
|
+
)
|
|
275
|
+
mcp_tools: Optional[List[str]] = Field(
|
|
276
|
+
None, description="List of MCP server names to connect to this agent."
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
class Config:
|
|
280
|
+
extra = "ignore" # Ignores extra fields
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
class CreateMetaAgent(BaseModel):
|
|
284
|
+
"""Request schema for creating a MetaAgent."""
|
|
285
|
+
|
|
286
|
+
name: Optional[str] = Field(
|
|
287
|
+
None,
|
|
288
|
+
description="Optional name for the MetaAgent. If None, a random name will be generated.",
|
|
289
|
+
)
|
|
290
|
+
agents: List[Union[str, Dict[str, Any]]] = Field(
|
|
291
|
+
default_factory=lambda: [
|
|
292
|
+
"core_memory_agent",
|
|
293
|
+
"resource_memory_agent",
|
|
294
|
+
"semantic_memory_agent",
|
|
295
|
+
"episodic_memory_agent",
|
|
296
|
+
"procedural_memory_agent",
|
|
297
|
+
"knowledge_vault_memory_agent",
|
|
298
|
+
"meta_memory_agent",
|
|
299
|
+
"reflexion_agent",
|
|
300
|
+
"background_agent",
|
|
301
|
+
],
|
|
302
|
+
description="List of memory agent names or dicts with agent configs. Supports both 'agent_name' strings and {'agent_name': {'blocks': [...], ...}} dicts.",
|
|
303
|
+
)
|
|
304
|
+
system_prompts: Optional[Dict[str, str]] = Field(
|
|
305
|
+
None,
|
|
306
|
+
description="Dictionary mapping agent names to their system prompt text. Takes precedence over system_prompts_folder.",
|
|
307
|
+
)
|
|
308
|
+
llm_config: Optional[LLMConfig] = Field(
|
|
309
|
+
None,
|
|
310
|
+
description="LLM configuration for memory agents. Required if no default is set.",
|
|
311
|
+
)
|
|
312
|
+
embedding_config: Optional[EmbeddingConfig] = Field(
|
|
313
|
+
None,
|
|
314
|
+
description="Embedding configuration for memory agents. Required if no default is set.",
|
|
315
|
+
)
|
|
316
|
+
|
|
317
|
+
class UpdateMetaAgent(BaseModel):
|
|
318
|
+
"""Request schema for updating a MetaAgent."""
|
|
319
|
+
|
|
320
|
+
name: Optional[str] = Field(
|
|
321
|
+
None,
|
|
322
|
+
description="Optional new name for the MetaAgent.",
|
|
323
|
+
)
|
|
324
|
+
agents: Optional[List[Union[str, Dict[str, Any]]]] = Field(
|
|
325
|
+
None,
|
|
326
|
+
description="List of memory agent names or dicts with agent configs. Will be compared with existing agents to determine what to add/remove.",
|
|
327
|
+
)
|
|
328
|
+
system_prompts: Optional[Dict[str, str]] = Field(
|
|
329
|
+
None,
|
|
330
|
+
description="Dictionary mapping agent names to their system prompt text. Updates only the specified agents.",
|
|
331
|
+
)
|
|
332
|
+
llm_config: Optional[LLMConfig] = Field(
|
|
333
|
+
None,
|
|
334
|
+
description="LLM configuration for meta agent and its sub-agents.",
|
|
335
|
+
)
|
|
336
|
+
embedding_config: Optional[EmbeddingConfig] = Field(
|
|
337
|
+
None,
|
|
338
|
+
description="Embedding configuration for meta agent and its sub-agents.",
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
class Config:
|
|
342
|
+
extra = "ignore" # Ignores extra fields
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
class AgentStepResponse(BaseModel):
|
|
346
|
+
messages: List[Message] = Field(
|
|
347
|
+
..., description="The messages generated during the agent's step."
|
|
348
|
+
)
|
|
349
|
+
continue_chaining: bool = Field(
|
|
350
|
+
...,
|
|
351
|
+
description="Whether the agent requested a contine_chaining (i.e. follow-up execution).",
|
|
352
|
+
)
|
|
353
|
+
function_failed: bool = Field(
|
|
354
|
+
..., description="Whether the agent step ended because a function call failed."
|
|
355
|
+
)
|
|
356
|
+
in_context_memory_warning: bool = Field(
|
|
357
|
+
...,
|
|
358
|
+
description="Whether the agent step ended because the in-context memory is near its limit.",
|
|
359
|
+
)
|
|
360
|
+
usage: UsageStatistics = Field(
|
|
361
|
+
..., description="Usage statistics of the LLM call during the agent's step."
|
|
362
|
+
)
|
|
363
|
+
traj: Optional[dict] = Field(
|
|
364
|
+
None, description="Action, Observation, State at the current step"
|
|
365
|
+
)
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
class AgentStepState(BaseModel):
|
|
369
|
+
step_number: int = Field(
|
|
370
|
+
..., description="The current step number in the agent loop"
|
|
371
|
+
)
|
|
372
|
+
tool_rules_solver: ToolRulesSolver = Field(
|
|
373
|
+
..., description="The current state of the ToolRulesSolver"
|
|
374
|
+
)
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
def get_prompt_template_for_agent_type(agent_type: Optional[AgentType] = None):
|
|
378
|
+
if agent_type == AgentType.sleeptime_agent:
|
|
379
|
+
return (
|
|
380
|
+
"{% for block in blocks %}"
|
|
381
|
+
'<{{ block.label }} characters="{{ block.value|length }}/{{ block.limit }}">\n'
|
|
382
|
+
"{% for line in block.value.split('\\n') %}"
|
|
383
|
+
"Line {{ loop.index }}: {{ line }}\n"
|
|
384
|
+
"{% endfor %}"
|
|
385
|
+
"</{{ block.label }}>"
|
|
386
|
+
"{% if not loop.last %}\n{% endif %}"
|
|
387
|
+
"{% endfor %}"
|
|
388
|
+
)
|
|
389
|
+
return (
|
|
390
|
+
"{% for block in blocks %}"
|
|
391
|
+
'<{{ block.label }} characters="{{ block.value|length }}/{{ block.limit }}">\n'
|
|
392
|
+
"{{ block.value }}\n"
|
|
393
|
+
"</{{ block.label }}>"
|
|
394
|
+
"{% if not loop.last %}\n{% endif %}"
|
|
395
|
+
"{% endfor %}"
|
|
396
|
+
)
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
# Rebuild model to support forward references (children field)
|
|
400
|
+
AgentState.model_rebuild()
|