letta-nightly 0.7.0.dev20250423003112__py3-none-any.whl → 0.7.2.dev20250423222439__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.
- letta/__init__.py +1 -1
- letta/agent.py +113 -81
- letta/agents/letta_agent.py +2 -2
- letta/agents/letta_agent_batch.py +38 -34
- letta/client/client.py +10 -2
- letta/constants.py +4 -3
- letta/functions/function_sets/multi_agent.py +1 -3
- letta/functions/helpers.py +3 -3
- letta/groups/dynamic_multi_agent.py +58 -59
- letta/groups/round_robin_multi_agent.py +43 -49
- letta/groups/sleeptime_multi_agent.py +28 -18
- letta/groups/supervisor_multi_agent.py +21 -20
- letta/helpers/composio_helpers.py +1 -1
- letta/helpers/converters.py +29 -0
- letta/helpers/datetime_helpers.py +9 -0
- letta/helpers/message_helper.py +1 -0
- letta/helpers/tool_execution_helper.py +3 -3
- letta/jobs/llm_batch_job_polling.py +2 -1
- letta/llm_api/anthropic.py +10 -6
- letta/llm_api/anthropic_client.py +2 -2
- letta/llm_api/cohere.py +2 -2
- letta/llm_api/google_ai_client.py +2 -2
- letta/llm_api/google_vertex_client.py +2 -2
- letta/llm_api/openai.py +11 -4
- letta/llm_api/openai_client.py +34 -2
- letta/local_llm/chat_completion_proxy.py +2 -2
- letta/orm/agent.py +8 -1
- letta/orm/custom_columns.py +15 -0
- letta/schemas/agent.py +6 -0
- letta/schemas/letta_message_content.py +2 -1
- letta/schemas/llm_config.py +12 -2
- letta/schemas/message.py +18 -0
- letta/schemas/openai/chat_completion_response.py +52 -3
- letta/schemas/response_format.py +78 -0
- letta/schemas/tool_execution_result.py +14 -0
- letta/server/rest_api/chat_completions_interface.py +2 -2
- letta/server/rest_api/interface.py +3 -2
- letta/server/rest_api/routers/openai/chat_completions/chat_completions.py +1 -1
- letta/server/rest_api/routers/v1/agents.py +4 -4
- letta/server/rest_api/routers/v1/groups.py +2 -2
- letta/server/rest_api/routers/v1/messages.py +41 -19
- letta/server/server.py +24 -57
- letta/services/agent_manager.py +6 -1
- letta/services/llm_batch_manager.py +28 -26
- letta/services/tool_executor/tool_execution_manager.py +37 -28
- letta/services/tool_executor/tool_execution_sandbox.py +35 -16
- letta/services/tool_executor/tool_executor.py +299 -68
- letta/services/tool_sandbox/base.py +3 -2
- letta/services/tool_sandbox/e2b_sandbox.py +5 -4
- letta/services/tool_sandbox/local_sandbox.py +11 -6
- {letta_nightly-0.7.0.dev20250423003112.dist-info → letta_nightly-0.7.2.dev20250423222439.dist-info}/METADATA +1 -1
- {letta_nightly-0.7.0.dev20250423003112.dist-info → letta_nightly-0.7.2.dev20250423222439.dist-info}/RECORD +55 -53
- {letta_nightly-0.7.0.dev20250423003112.dist-info → letta_nightly-0.7.2.dev20250423222439.dist-info}/LICENSE +0 -0
- {letta_nightly-0.7.0.dev20250423003112.dist-info → letta_nightly-0.7.2.dev20250423222439.dist-info}/WHEEL +0 -0
- {letta_nightly-0.7.0.dev20250423003112.dist-info → letta_nightly-0.7.2.dev20250423222439.dist-info}/entry_points.txt +0 -0
@@ -291,9 +291,7 @@ class LLMBatchManager:
|
|
291
291
|
return [item.to_pydantic() for item in results]
|
292
292
|
|
293
293
|
def bulk_update_llm_batch_items(
|
294
|
-
self,
|
295
|
-
llm_batch_id_agent_id_pairs: List[Tuple[str, str]],
|
296
|
-
field_updates: List[Dict[str, Any]],
|
294
|
+
self, llm_batch_id_agent_id_pairs: List[Tuple[str, str]], field_updates: List[Dict[str, Any]], strict: bool = True
|
297
295
|
) -> None:
|
298
296
|
"""
|
299
297
|
Efficiently update multiple LLMBatchItem rows by (llm_batch_id, agent_id) pairs.
|
@@ -301,30 +299,43 @@ class LLMBatchManager:
|
|
301
299
|
Args:
|
302
300
|
llm_batch_id_agent_id_pairs: List of (llm_batch_id, agent_id) tuples identifying items to update
|
303
301
|
field_updates: List of dictionaries containing the fields to update for each item
|
302
|
+
strict: Whether to error if any of the requested keys don't exist (default True).
|
303
|
+
If False, missing pairs are skipped.
|
304
304
|
"""
|
305
305
|
if not llm_batch_id_agent_id_pairs or not field_updates:
|
306
306
|
return
|
307
307
|
|
308
308
|
if len(llm_batch_id_agent_id_pairs) != len(field_updates):
|
309
|
-
raise ValueError("
|
309
|
+
raise ValueError("llm_batch_id_agent_id_pairs and field_updates must have the same length")
|
310
310
|
|
311
311
|
with self.session_maker() as session:
|
312
|
-
# Lookup primary keys
|
312
|
+
# Lookup primary keys for all requested (batch_id, agent_id) pairs
|
313
313
|
items = (
|
314
314
|
session.query(LLMBatchItem.id, LLMBatchItem.llm_batch_id, LLMBatchItem.agent_id)
|
315
315
|
.filter(tuple_(LLMBatchItem.llm_batch_id, LLMBatchItem.agent_id).in_(llm_batch_id_agent_id_pairs))
|
316
316
|
.all()
|
317
317
|
)
|
318
|
-
pair_to_pk = {(
|
319
|
-
|
318
|
+
pair_to_pk = {(batch_id, agent_id): pk for pk, batch_id, agent_id in items}
|
319
|
+
|
320
|
+
if strict:
|
321
|
+
requested = set(llm_batch_id_agent_id_pairs)
|
322
|
+
found = set(pair_to_pk.keys())
|
323
|
+
missing = requested - found
|
324
|
+
if missing:
|
325
|
+
raise ValueError(
|
326
|
+
f"Cannot bulk-update batch items: no records for the following " f"(llm_batch_id, agent_id) pairs: {missing}"
|
327
|
+
)
|
328
|
+
|
329
|
+
# Build mappings, skipping any missing when strict=False
|
320
330
|
mappings = []
|
321
|
-
for (
|
322
|
-
|
323
|
-
if
|
331
|
+
for (batch_id, agent_id), fields in zip(llm_batch_id_agent_id_pairs, field_updates):
|
332
|
+
pk = pair_to_pk.get((batch_id, agent_id))
|
333
|
+
if pk is None:
|
334
|
+
# skip missing in non-strict mode
|
324
335
|
continue
|
325
336
|
|
326
337
|
update_fields = fields.copy()
|
327
|
-
update_fields["id"] =
|
338
|
+
update_fields["id"] = pk
|
328
339
|
mappings.append(update_fields)
|
329
340
|
|
330
341
|
if mappings:
|
@@ -332,10 +343,7 @@ class LLMBatchManager:
|
|
332
343
|
session.commit()
|
333
344
|
|
334
345
|
@enforce_types
|
335
|
-
def bulk_update_batch_llm_items_results_by_agent(
|
336
|
-
self,
|
337
|
-
updates: List[ItemUpdateInfo],
|
338
|
-
) -> None:
|
346
|
+
def bulk_update_batch_llm_items_results_by_agent(self, updates: List[ItemUpdateInfo], strict: bool = True) -> None:
|
339
347
|
"""Update request status and batch results for multiple batch items."""
|
340
348
|
batch_id_agent_id_pairs = [(update.llm_batch_id, update.agent_id) for update in updates]
|
341
349
|
field_updates = [
|
@@ -346,29 +354,23 @@ class LLMBatchManager:
|
|
346
354
|
for update in updates
|
347
355
|
]
|
348
356
|
|
349
|
-
self.bulk_update_llm_batch_items(batch_id_agent_id_pairs, field_updates)
|
357
|
+
self.bulk_update_llm_batch_items(batch_id_agent_id_pairs, field_updates, strict=strict)
|
350
358
|
|
351
359
|
@enforce_types
|
352
|
-
def bulk_update_llm_batch_items_step_status_by_agent(
|
353
|
-
self,
|
354
|
-
updates: List[StepStatusUpdateInfo],
|
355
|
-
) -> None:
|
360
|
+
def bulk_update_llm_batch_items_step_status_by_agent(self, updates: List[StepStatusUpdateInfo], strict: bool = True) -> None:
|
356
361
|
"""Update step status for multiple batch items."""
|
357
362
|
batch_id_agent_id_pairs = [(update.llm_batch_id, update.agent_id) for update in updates]
|
358
363
|
field_updates = [{"step_status": update.step_status} for update in updates]
|
359
364
|
|
360
|
-
self.bulk_update_llm_batch_items(batch_id_agent_id_pairs, field_updates)
|
365
|
+
self.bulk_update_llm_batch_items(batch_id_agent_id_pairs, field_updates, strict=strict)
|
361
366
|
|
362
367
|
@enforce_types
|
363
|
-
def bulk_update_llm_batch_items_request_status_by_agent(
|
364
|
-
self,
|
365
|
-
updates: List[RequestStatusUpdateInfo],
|
366
|
-
) -> None:
|
368
|
+
def bulk_update_llm_batch_items_request_status_by_agent(self, updates: List[RequestStatusUpdateInfo], strict: bool = True) -> None:
|
367
369
|
"""Update request status for multiple batch items."""
|
368
370
|
batch_id_agent_id_pairs = [(update.llm_batch_id, update.agent_id) for update in updates]
|
369
371
|
field_updates = [{"request_status": update.request_status} for update in updates]
|
370
372
|
|
371
|
-
self.bulk_update_llm_batch_items(batch_id_agent_id_pairs, field_updates)
|
373
|
+
self.bulk_update_llm_batch_items(batch_id_agent_id_pairs, field_updates, strict=strict)
|
372
374
|
|
373
375
|
@enforce_types
|
374
376
|
def delete_llm_batch_item(self, item_id: str, actor: PydanticUser) -> None:
|
@@ -1,16 +1,17 @@
|
|
1
|
-
|
1
|
+
import traceback
|
2
|
+
from typing import Any, Dict, Optional, Type
|
2
3
|
|
3
4
|
from letta.log import get_logger
|
4
5
|
from letta.orm.enums import ToolType
|
5
6
|
from letta.schemas.agent import AgentState
|
6
|
-
from letta.schemas.sandbox_config import SandboxConfig
|
7
|
+
from letta.schemas.sandbox_config import SandboxConfig
|
7
8
|
from letta.schemas.tool import Tool
|
9
|
+
from letta.schemas.tool_execution_result import ToolExecutionResult
|
8
10
|
from letta.schemas.user import User
|
9
11
|
from letta.services.tool_executor.tool_executor import (
|
10
12
|
ExternalComposioToolExecutor,
|
11
13
|
ExternalMCPToolExecutor,
|
12
14
|
LettaCoreToolExecutor,
|
13
|
-
LettaMemoryToolExecutor,
|
14
15
|
LettaMultiAgentToolExecutor,
|
15
16
|
SandboxToolExecutor,
|
16
17
|
ToolExecutor,
|
@@ -24,8 +25,9 @@ class ToolExecutorFactory:
|
|
24
25
|
|
25
26
|
_executor_map: Dict[ToolType, Type[ToolExecutor]] = {
|
26
27
|
ToolType.LETTA_CORE: LettaCoreToolExecutor,
|
28
|
+
ToolType.LETTA_MEMORY_CORE: LettaCoreToolExecutor,
|
29
|
+
ToolType.LETTA_SLEEPTIME_CORE: LettaCoreToolExecutor,
|
27
30
|
ToolType.LETTA_MULTI_AGENT_CORE: LettaMultiAgentToolExecutor,
|
28
|
-
ToolType.LETTA_MEMORY_CORE: LettaMemoryToolExecutor,
|
29
31
|
ToolType.EXTERNAL_COMPOSIO: ExternalComposioToolExecutor,
|
30
32
|
ToolType.EXTERNAL_MCP: ExternalMCPToolExecutor,
|
31
33
|
}
|
@@ -33,13 +35,8 @@ class ToolExecutorFactory:
|
|
33
35
|
@classmethod
|
34
36
|
def get_executor(cls, tool_type: ToolType) -> ToolExecutor:
|
35
37
|
"""Get the appropriate executor for the given tool type."""
|
36
|
-
executor_class = cls._executor_map.get(tool_type)
|
37
|
-
|
38
|
-
if executor_class:
|
39
|
-
return executor_class()
|
40
|
-
|
41
|
-
# Default to sandbox executor for unknown types
|
42
|
-
return SandboxToolExecutor()
|
38
|
+
executor_class = cls._executor_map.get(tool_type, SandboxToolExecutor)
|
39
|
+
return executor_class()
|
43
40
|
|
44
41
|
|
45
42
|
class ToolExecutionManager:
|
@@ -58,7 +55,7 @@ class ToolExecutionManager:
|
|
58
55
|
self.sandbox_config = sandbox_config
|
59
56
|
self.sandbox_env_vars = sandbox_env_vars
|
60
57
|
|
61
|
-
def execute_tool(self, function_name: str, function_args: dict, tool: Tool) ->
|
58
|
+
def execute_tool(self, function_name: str, function_args: dict, tool: Tool) -> ToolExecutionResult:
|
62
59
|
"""
|
63
60
|
Execute a tool and persist any state changes.
|
64
61
|
|
@@ -71,35 +68,43 @@ class ToolExecutionManager:
|
|
71
68
|
Tuple containing the function response and sandbox run result (if applicable)
|
72
69
|
"""
|
73
70
|
try:
|
74
|
-
# Get the appropriate executor for this tool type
|
75
71
|
executor = ToolExecutorFactory.get_executor(tool.tool_type)
|
76
|
-
|
77
|
-
# Execute the tool
|
78
72
|
return executor.execute(
|
79
|
-
function_name,
|
73
|
+
function_name,
|
74
|
+
function_args,
|
75
|
+
self.agent_state,
|
76
|
+
tool,
|
77
|
+
self.actor,
|
78
|
+
self.sandbox_config,
|
79
|
+
self.sandbox_env_vars,
|
80
80
|
)
|
81
81
|
|
82
82
|
except Exception as e:
|
83
83
|
self.logger.error(f"Error executing tool {function_name}: {str(e)}")
|
84
|
-
error_message = get_friendly_error_msg(
|
85
|
-
|
84
|
+
error_message = get_friendly_error_msg(
|
85
|
+
function_name=function_name,
|
86
|
+
exception_name=type(e).__name__,
|
87
|
+
exception_message=str(e),
|
88
|
+
)
|
89
|
+
return ToolExecutionResult(
|
90
|
+
status="error",
|
91
|
+
func_return=error_message,
|
92
|
+
stderr=[traceback.format_exc()],
|
93
|
+
)
|
86
94
|
|
87
95
|
@trace_method
|
88
|
-
async def execute_tool_async(self, function_name: str, function_args: dict, tool: Tool) ->
|
96
|
+
async def execute_tool_async(self, function_name: str, function_args: dict, tool: Tool) -> ToolExecutionResult:
|
89
97
|
"""
|
90
98
|
Execute a tool asynchronously and persist any state changes.
|
91
99
|
"""
|
92
100
|
try:
|
93
|
-
|
101
|
+
executor = ToolExecutorFactory.get_executor(tool.tool_type)
|
94
102
|
# TODO: Extend this async model to composio
|
95
|
-
|
96
|
-
|
97
|
-
executor = SandboxToolExecutor()
|
98
|
-
result_tuple = await executor.execute(function_name, function_args, self.agent_state, tool, self.actor)
|
103
|
+
if isinstance(executor, SandboxToolExecutor):
|
104
|
+
result = await executor.execute(function_name, function_args, self.agent_state, tool, self.actor)
|
99
105
|
else:
|
100
|
-
|
101
|
-
|
102
|
-
return result_tuple
|
106
|
+
result = executor.execute(function_name, function_args, self.agent_state, tool, self.actor)
|
107
|
+
return result
|
103
108
|
|
104
109
|
except Exception as e:
|
105
110
|
self.logger.error(f"Error executing tool {function_name}: {str(e)}")
|
@@ -108,4 +113,8 @@ class ToolExecutionManager:
|
|
108
113
|
exception_name=type(e).__name__,
|
109
114
|
exception_message=str(e),
|
110
115
|
)
|
111
|
-
return
|
116
|
+
return ToolExecutionResult(
|
117
|
+
status="error",
|
118
|
+
func_return=error_message,
|
119
|
+
stderr=[traceback.format_exc()],
|
120
|
+
)
|
@@ -13,8 +13,9 @@ from typing import Any, Dict, Optional
|
|
13
13
|
from letta.functions.helpers import generate_model_from_args_json_schema
|
14
14
|
from letta.log import get_logger
|
15
15
|
from letta.schemas.agent import AgentState
|
16
|
-
from letta.schemas.sandbox_config import SandboxConfig,
|
16
|
+
from letta.schemas.sandbox_config import SandboxConfig, SandboxType
|
17
17
|
from letta.schemas.tool import Tool
|
18
|
+
from letta.schemas.tool_execution_result import ToolExecutionResult
|
18
19
|
from letta.schemas.user import User
|
19
20
|
from letta.services.helpers.tool_execution_helper import (
|
20
21
|
add_imports_and_pydantic_schemas_for_args,
|
@@ -72,7 +73,11 @@ class ToolExecutionSandbox:
|
|
72
73
|
self.force_recreate = force_recreate
|
73
74
|
self.force_recreate_venv = force_recreate_venv
|
74
75
|
|
75
|
-
def run(
|
76
|
+
def run(
|
77
|
+
self,
|
78
|
+
agent_state: Optional[AgentState] = None,
|
79
|
+
additional_env_vars: Optional[Dict] = None,
|
80
|
+
) -> ToolExecutionResult:
|
76
81
|
"""
|
77
82
|
Run the tool in a sandbox environment.
|
78
83
|
|
@@ -81,7 +86,7 @@ class ToolExecutionSandbox:
|
|
81
86
|
additional_env_vars (Optional[Dict]): Environment variables to inject into the sandbox
|
82
87
|
|
83
88
|
Returns:
|
84
|
-
|
89
|
+
ToolExecutionResult: Object containing tool execution outcome (e.g. status, response)
|
85
90
|
"""
|
86
91
|
if tool_settings.e2b_api_key and not self.privileged_tools:
|
87
92
|
logger.debug(f"Using e2b sandbox to execute {self.tool_name}")
|
@@ -115,7 +120,7 @@ class ToolExecutionSandbox:
|
|
115
120
|
@trace_method
|
116
121
|
def run_local_dir_sandbox(
|
117
122
|
self, agent_state: Optional[AgentState] = None, additional_env_vars: Optional[Dict] = None
|
118
|
-
) ->
|
123
|
+
) -> ToolExecutionResult:
|
119
124
|
sbx_config = self.sandbox_config_manager.get_or_create_default_sandbox_config(sandbox_type=SandboxType.LOCAL, actor=self.user)
|
120
125
|
local_configs = sbx_config.get_local_config()
|
121
126
|
|
@@ -162,7 +167,12 @@ class ToolExecutionSandbox:
|
|
162
167
|
os.remove(temp_file_path)
|
163
168
|
|
164
169
|
@trace_method
|
165
|
-
def run_local_dir_sandbox_venv(
|
170
|
+
def run_local_dir_sandbox_venv(
|
171
|
+
self,
|
172
|
+
sbx_config: SandboxConfig,
|
173
|
+
env: Dict[str, str],
|
174
|
+
temp_file_path: str,
|
175
|
+
) -> ToolExecutionResult:
|
166
176
|
local_configs = sbx_config.get_local_config()
|
167
177
|
sandbox_dir = os.path.expanduser(local_configs.sandbox_dir) # Expand tilde
|
168
178
|
venv_path = os.path.join(sandbox_dir, local_configs.venv_name)
|
@@ -205,12 +215,12 @@ class ToolExecutionSandbox:
|
|
205
215
|
func_result, stdout = self.parse_out_function_results_markers(result.stdout)
|
206
216
|
func_return, agent_state = self.parse_best_effort(func_result)
|
207
217
|
|
208
|
-
return
|
218
|
+
return ToolExecutionResult(
|
219
|
+
status="success",
|
209
220
|
func_return=func_return,
|
210
221
|
agent_state=agent_state,
|
211
222
|
stdout=[stdout] if stdout else [],
|
212
223
|
stderr=[result.stderr] if result.stderr else [],
|
213
|
-
status="success",
|
214
224
|
sandbox_config_fingerprint=sbx_config.fingerprint(),
|
215
225
|
)
|
216
226
|
|
@@ -221,12 +231,12 @@ class ToolExecutionSandbox:
|
|
221
231
|
exception_name=type(e).__name__,
|
222
232
|
exception_message=str(e),
|
223
233
|
)
|
224
|
-
return
|
234
|
+
return ToolExecutionResult(
|
235
|
+
status="error",
|
225
236
|
func_return=func_return,
|
226
237
|
agent_state=None,
|
227
238
|
stdout=[e.stdout] if e.stdout else [],
|
228
239
|
stderr=[e.stderr] if e.stderr else [],
|
229
|
-
status="error",
|
230
240
|
sandbox_config_fingerprint=sbx_config.fingerprint(),
|
231
241
|
)
|
232
242
|
|
@@ -238,7 +248,12 @@ class ToolExecutionSandbox:
|
|
238
248
|
raise e
|
239
249
|
|
240
250
|
@trace_method
|
241
|
-
def run_local_dir_sandbox_directly(
|
251
|
+
def run_local_dir_sandbox_directly(
|
252
|
+
self,
|
253
|
+
sbx_config: SandboxConfig,
|
254
|
+
env: Dict[str, str],
|
255
|
+
temp_file_path: str,
|
256
|
+
) -> ToolExecutionResult:
|
242
257
|
status = "success"
|
243
258
|
func_return, agent_state, stderr = None, None, None
|
244
259
|
|
@@ -288,12 +303,12 @@ class ToolExecutionSandbox:
|
|
288
303
|
stdout_output = [captured_stdout.getvalue()] if captured_stdout.getvalue() else []
|
289
304
|
stderr_output = [captured_stderr.getvalue()] if captured_stderr.getvalue() else []
|
290
305
|
|
291
|
-
return
|
306
|
+
return ToolExecutionResult(
|
307
|
+
status=status,
|
292
308
|
func_return=func_return,
|
293
309
|
agent_state=agent_state,
|
294
310
|
stdout=stdout_output,
|
295
311
|
stderr=stderr_output,
|
296
|
-
status=status,
|
297
312
|
sandbox_config_fingerprint=sbx_config.fingerprint(),
|
298
313
|
)
|
299
314
|
|
@@ -307,7 +322,11 @@ class ToolExecutionSandbox:
|
|
307
322
|
|
308
323
|
# e2b sandbox specific functions
|
309
324
|
|
310
|
-
def run_e2b_sandbox(
|
325
|
+
def run_e2b_sandbox(
|
326
|
+
self,
|
327
|
+
agent_state: Optional[AgentState] = None,
|
328
|
+
additional_env_vars: Optional[Dict] = None,
|
329
|
+
) -> ToolExecutionResult:
|
311
330
|
sbx_config = self.sandbox_config_manager.get_or_create_default_sandbox_config(sandbox_type=SandboxType.E2B, actor=self.user)
|
312
331
|
sbx = self.get_running_e2b_sandbox_with_same_state(sbx_config)
|
313
332
|
if not sbx or self.force_recreate:
|
@@ -348,12 +367,12 @@ class ToolExecutionSandbox:
|
|
348
367
|
else:
|
349
368
|
raise ValueError(f"Tool {self.tool_name} returned execution with None")
|
350
369
|
|
351
|
-
return
|
370
|
+
return ToolExecutionResult(
|
371
|
+
status="error" if execution.error else "success",
|
352
372
|
func_return=func_return,
|
353
373
|
agent_state=agent_state,
|
354
374
|
stdout=execution.logs.stdout,
|
355
375
|
stderr=execution.logs.stderr,
|
356
|
-
status="error" if execution.error else "success",
|
357
376
|
sandbox_config_fingerprint=sbx_config.fingerprint(),
|
358
377
|
)
|
359
378
|
|
@@ -535,7 +554,7 @@ class ToolExecutionSandbox:
|
|
535
554
|
Generate the code string to call the function.
|
536
555
|
|
537
556
|
Args:
|
538
|
-
inject_agent_state (bool): Whether to inject the
|
557
|
+
inject_agent_state (bool): Whether to inject the agent's state as an input into the tool
|
539
558
|
|
540
559
|
Returns:
|
541
560
|
str: Generated code string for calling the tool
|