letta-nightly 0.7.21.dev20250522104246__py3-none-any.whl → 0.7.22.dev20250523081403__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 +2 -2
- letta/agents/base_agent.py +4 -2
- letta/agents/letta_agent.py +3 -10
- letta/agents/letta_agent_batch.py +6 -6
- letta/cli/cli.py +0 -316
- letta/cli/cli_load.py +0 -52
- letta/client/client.py +2 -1554
- letta/data_sources/connectors.py +4 -2
- letta/functions/ast_parsers.py +33 -43
- letta/groups/sleeptime_multi_agent_v2.py +49 -13
- letta/jobs/llm_batch_job_polling.py +3 -3
- letta/jobs/scheduler.py +20 -19
- letta/llm_api/anthropic_client.py +3 -0
- letta/llm_api/google_vertex_client.py +5 -0
- letta/llm_api/openai_client.py +5 -0
- letta/main.py +2 -362
- letta/server/db.py +5 -0
- letta/server/rest_api/routers/v1/agents.py +72 -43
- letta/server/rest_api/routers/v1/llms.py +2 -2
- letta/server/rest_api/routers/v1/messages.py +5 -3
- letta/server/rest_api/routers/v1/sandbox_configs.py +18 -18
- letta/server/rest_api/routers/v1/sources.py +49 -36
- letta/server/server.py +53 -22
- letta/services/agent_manager.py +797 -124
- letta/services/block_manager.py +14 -62
- letta/services/group_manager.py +37 -0
- letta/services/identity_manager.py +9 -0
- letta/services/job_manager.py +17 -0
- letta/services/llm_batch_manager.py +88 -64
- letta/services/message_manager.py +19 -0
- letta/services/organization_manager.py +10 -0
- letta/services/passage_manager.py +13 -0
- letta/services/per_agent_lock_manager.py +4 -0
- letta/services/provider_manager.py +34 -0
- letta/services/sandbox_config_manager.py +130 -0
- letta/services/source_manager.py +59 -44
- letta/services/step_manager.py +8 -1
- letta/services/tool_manager.py +21 -0
- letta/services/tool_sandbox/e2b_sandbox.py +4 -2
- letta/services/tool_sandbox/local_sandbox.py +7 -3
- letta/services/user_manager.py +16 -0
- {letta_nightly-0.7.21.dev20250522104246.dist-info → letta_nightly-0.7.22.dev20250523081403.dist-info}/METADATA +1 -1
- {letta_nightly-0.7.21.dev20250522104246.dist-info → letta_nightly-0.7.22.dev20250523081403.dist-info}/RECORD +46 -50
- letta/__main__.py +0 -3
- letta/benchmark/benchmark.py +0 -98
- letta/benchmark/constants.py +0 -14
- letta/cli/cli_config.py +0 -227
- {letta_nightly-0.7.21.dev20250522104246.dist-info → letta_nightly-0.7.22.dev20250523081403.dist-info}/LICENSE +0 -0
- {letta_nightly-0.7.21.dev20250522104246.dist-info → letta_nightly-0.7.22.dev20250523081403.dist-info}/WHEEL +0 -0
- {letta_nightly-0.7.21.dev20250522104246.dist-info → letta_nightly-0.7.22.dev20250523081403.dist-info}/entry_points.txt +0 -0
letta/client/client.py
CHANGED
@@ -1,27 +1,19 @@
|
|
1
|
-
import asyncio
|
2
|
-
import logging
|
3
1
|
import sys
|
4
2
|
import time
|
5
3
|
from typing import Callable, Dict, Generator, List, Optional, Union
|
6
4
|
|
7
5
|
import requests
|
8
6
|
|
9
|
-
import letta.utils
|
10
7
|
from letta.constants import ADMIN_PREFIX, BASE_MEMORY_TOOLS, BASE_TOOLS, DEFAULT_HUMAN, DEFAULT_PERSONA, FUNCTION_RETURN_CHAR_LIMIT
|
11
8
|
from letta.data_sources.connectors import DataConnector
|
12
9
|
from letta.functions.functions import parse_source_code
|
13
|
-
from letta.orm.errors import NoResultFound
|
14
10
|
from letta.schemas.agent import AgentState, AgentType, CreateAgent, UpdateAgent
|
15
11
|
from letta.schemas.block import Block, BlockUpdate, CreateBlock, Human, Persona
|
16
12
|
from letta.schemas.embedding_config import EmbeddingConfig
|
17
13
|
|
18
14
|
# new schemas
|
19
15
|
from letta.schemas.enums import JobStatus, MessageRole
|
20
|
-
from letta.schemas.environment_variables import
|
21
|
-
SandboxEnvironmentVariable,
|
22
|
-
SandboxEnvironmentVariableCreate,
|
23
|
-
SandboxEnvironmentVariableUpdate,
|
24
|
-
)
|
16
|
+
from letta.schemas.environment_variables import SandboxEnvironmentVariable
|
25
17
|
from letta.schemas.file import FileMetadata
|
26
18
|
from letta.schemas.job import Job
|
27
19
|
from letta.schemas.letta_message import LettaMessage, LettaMessageUnion
|
@@ -35,11 +27,10 @@ from letta.schemas.organization import Organization
|
|
35
27
|
from letta.schemas.passage import Passage
|
36
28
|
from letta.schemas.response_format import ResponseFormatUnion
|
37
29
|
from letta.schemas.run import Run
|
38
|
-
from letta.schemas.sandbox_config import E2BSandboxConfig, LocalSandboxConfig, SandboxConfig
|
30
|
+
from letta.schemas.sandbox_config import E2BSandboxConfig, LocalSandboxConfig, SandboxConfig
|
39
31
|
from letta.schemas.source import Source, SourceCreate, SourceUpdate
|
40
32
|
from letta.schemas.tool import Tool, ToolCreate, ToolUpdate
|
41
33
|
from letta.schemas.tool_rule import BaseToolRule
|
42
|
-
from letta.server.rest_api.interface import QueuingInterface
|
43
34
|
from letta.utils import get_human_text, get_persona_text
|
44
35
|
|
45
36
|
# Print deprecation notice in yellow when module is imported
|
@@ -53,13 +44,6 @@ print(
|
|
53
44
|
)
|
54
45
|
|
55
46
|
|
56
|
-
def create_client(base_url: Optional[str] = None, token: Optional[str] = None):
|
57
|
-
if base_url is None:
|
58
|
-
return LocalClient()
|
59
|
-
else:
|
60
|
-
return RESTClient(base_url, token)
|
61
|
-
|
62
|
-
|
63
47
|
class AbstractClient(object):
|
64
48
|
def __init__(
|
65
49
|
self,
|
@@ -2229,1539 +2213,3 @@ class RESTClient(AbstractClient):
|
|
2229
2213
|
if response.status_code != 200:
|
2230
2214
|
raise ValueError(f"Failed to get tags: {response.text}")
|
2231
2215
|
return response.json()
|
2232
|
-
|
2233
|
-
|
2234
|
-
class LocalClient(AbstractClient):
|
2235
|
-
"""
|
2236
|
-
A local client for Letta, which corresponds to a single user.
|
2237
|
-
|
2238
|
-
Attributes:
|
2239
|
-
user_id (str): The user ID.
|
2240
|
-
debug (bool): Whether to print debug information.
|
2241
|
-
interface (QueuingInterface): The interface for the client.
|
2242
|
-
server (SyncServer): The server for the client.
|
2243
|
-
"""
|
2244
|
-
|
2245
|
-
def __init__(
|
2246
|
-
self,
|
2247
|
-
user_id: Optional[str] = None,
|
2248
|
-
org_id: Optional[str] = None,
|
2249
|
-
debug: bool = False,
|
2250
|
-
default_llm_config: Optional[LLMConfig] = None,
|
2251
|
-
default_embedding_config: Optional[EmbeddingConfig] = None,
|
2252
|
-
):
|
2253
|
-
"""
|
2254
|
-
Initializes a new instance of Client class.
|
2255
|
-
|
2256
|
-
Args:
|
2257
|
-
user_id (str): The user ID.
|
2258
|
-
debug (bool): Whether to print debug information.
|
2259
|
-
"""
|
2260
|
-
|
2261
|
-
from letta.server.server import SyncServer
|
2262
|
-
|
2263
|
-
# set logging levels
|
2264
|
-
letta.utils.DEBUG = debug
|
2265
|
-
logging.getLogger().setLevel(logging.CRITICAL)
|
2266
|
-
|
2267
|
-
# save default model config
|
2268
|
-
self._default_llm_config = default_llm_config
|
2269
|
-
self._default_embedding_config = default_embedding_config
|
2270
|
-
|
2271
|
-
# create server
|
2272
|
-
self.interface = QueuingInterface(debug=debug)
|
2273
|
-
self.server = SyncServer(default_interface_factory=lambda: self.interface)
|
2274
|
-
|
2275
|
-
# save org_id that `LocalClient` is associated with
|
2276
|
-
if org_id:
|
2277
|
-
self.org_id = org_id
|
2278
|
-
else:
|
2279
|
-
self.org_id = self.server.organization_manager.DEFAULT_ORG_ID
|
2280
|
-
# save user_id that `LocalClient` is associated with
|
2281
|
-
if user_id:
|
2282
|
-
self.user_id = user_id
|
2283
|
-
else:
|
2284
|
-
# get default user
|
2285
|
-
self.user_id = self.server.user_manager.DEFAULT_USER_ID
|
2286
|
-
|
2287
|
-
self.user = self.server.user_manager.get_user_or_default(self.user_id)
|
2288
|
-
self.organization = self.server.get_organization_or_default(self.org_id)
|
2289
|
-
|
2290
|
-
# agents
|
2291
|
-
def list_agents(
|
2292
|
-
self,
|
2293
|
-
query_text: Optional[str] = None,
|
2294
|
-
tags: Optional[List[str]] = None,
|
2295
|
-
limit: int = 100,
|
2296
|
-
before: Optional[str] = None,
|
2297
|
-
after: Optional[str] = None,
|
2298
|
-
) -> List[AgentState]:
|
2299
|
-
self.interface.clear()
|
2300
|
-
|
2301
|
-
return self.server.agent_manager.list_agents(
|
2302
|
-
actor=self.user, tags=tags, query_text=query_text, limit=limit, before=before, after=after
|
2303
|
-
)
|
2304
|
-
|
2305
|
-
def agent_exists(self, agent_id: Optional[str] = None, agent_name: Optional[str] = None) -> bool:
|
2306
|
-
"""
|
2307
|
-
Check if an agent exists
|
2308
|
-
|
2309
|
-
Args:
|
2310
|
-
agent_id (str): ID of the agent
|
2311
|
-
agent_name (str): Name of the agent
|
2312
|
-
|
2313
|
-
Returns:
|
2314
|
-
exists (bool): `True` if the agent exists, `False` otherwise
|
2315
|
-
"""
|
2316
|
-
|
2317
|
-
if not (agent_id or agent_name):
|
2318
|
-
raise ValueError(f"Either agent_id or agent_name must be provided")
|
2319
|
-
if agent_id and agent_name:
|
2320
|
-
raise ValueError(f"Only one of agent_id or agent_name can be provided")
|
2321
|
-
existing = self.list_agents()
|
2322
|
-
if agent_id:
|
2323
|
-
return str(agent_id) in [str(agent.id) for agent in existing]
|
2324
|
-
else:
|
2325
|
-
return agent_name in [str(agent.name) for agent in existing]
|
2326
|
-
|
2327
|
-
def create_agent(
|
2328
|
-
self,
|
2329
|
-
name: Optional[str] = None,
|
2330
|
-
# agent config
|
2331
|
-
agent_type: Optional[AgentType] = AgentType.memgpt_agent,
|
2332
|
-
# model configs
|
2333
|
-
embedding_config: EmbeddingConfig = None,
|
2334
|
-
llm_config: LLMConfig = None,
|
2335
|
-
# memory
|
2336
|
-
memory: Memory = ChatMemory(human=get_human_text(DEFAULT_HUMAN), persona=get_persona_text(DEFAULT_PERSONA)),
|
2337
|
-
block_ids: Optional[List[str]] = None,
|
2338
|
-
# TODO: change to this when we are ready to migrate all the tests/examples (matches the REST API)
|
2339
|
-
# memory_blocks=[
|
2340
|
-
# {"label": "human", "value": get_human_text(DEFAULT_HUMAN), "limit": 5000},
|
2341
|
-
# {"label": "persona", "value": get_persona_text(DEFAULT_PERSONA), "limit": 5000},
|
2342
|
-
# ],
|
2343
|
-
# system
|
2344
|
-
system: Optional[str] = None,
|
2345
|
-
# tools
|
2346
|
-
tool_ids: Optional[List[str]] = None,
|
2347
|
-
tool_rules: Optional[List[BaseToolRule]] = None,
|
2348
|
-
include_base_tools: Optional[bool] = True,
|
2349
|
-
include_multi_agent_tools: bool = False,
|
2350
|
-
include_base_tool_rules: bool = True,
|
2351
|
-
# metadata
|
2352
|
-
metadata: Optional[Dict] = {"human:": DEFAULT_HUMAN, "persona": DEFAULT_PERSONA},
|
2353
|
-
description: Optional[str] = None,
|
2354
|
-
initial_message_sequence: Optional[List[Message]] = None,
|
2355
|
-
tags: Optional[List[str]] = None,
|
2356
|
-
message_buffer_autoclear: bool = False,
|
2357
|
-
response_format: Optional[ResponseFormatUnion] = None,
|
2358
|
-
) -> AgentState:
|
2359
|
-
"""Create an agent
|
2360
|
-
|
2361
|
-
Args:
|
2362
|
-
name (str): Name of the agent
|
2363
|
-
embedding_config (EmbeddingConfig): Embedding configuration
|
2364
|
-
llm_config (LLMConfig): LLM configuration
|
2365
|
-
memory_blocks (List[Dict]): List of configurations for the memory blocks (placed in core-memory)
|
2366
|
-
system (str): System configuration
|
2367
|
-
tools (List[str]): List of tools
|
2368
|
-
tool_rules (Optional[List[BaseToolRule]]): List of tool rules
|
2369
|
-
include_base_tools (bool): Include base tools
|
2370
|
-
include_multi_agent_tools (bool): Include multi agent tools
|
2371
|
-
metadata (Dict): Metadata
|
2372
|
-
description (str): Description
|
2373
|
-
tags (List[str]): Tags for filtering agents
|
2374
|
-
|
2375
|
-
Returns:
|
2376
|
-
agent_state (AgentState): State of the created agent
|
2377
|
-
"""
|
2378
|
-
# construct list of tools
|
2379
|
-
tool_ids = tool_ids or []
|
2380
|
-
|
2381
|
-
# check if default configs are provided
|
2382
|
-
assert embedding_config or self._default_embedding_config, f"Embedding config must be provided"
|
2383
|
-
assert llm_config or self._default_llm_config, f"LLM config must be provided"
|
2384
|
-
|
2385
|
-
# TODO: This should not happen here, we need to have clear separation between create/add blocks
|
2386
|
-
for block in memory.get_blocks():
|
2387
|
-
self.server.block_manager.create_or_update_block(block, actor=self.user)
|
2388
|
-
|
2389
|
-
# Also get any existing block_ids passed in
|
2390
|
-
block_ids = block_ids or []
|
2391
|
-
|
2392
|
-
# create agent
|
2393
|
-
# Create the base parameters
|
2394
|
-
create_params = {
|
2395
|
-
"description": description,
|
2396
|
-
"metadata": metadata,
|
2397
|
-
"memory_blocks": [],
|
2398
|
-
"block_ids": [b.id for b in memory.get_blocks()] + block_ids,
|
2399
|
-
"tool_ids": tool_ids,
|
2400
|
-
"tool_rules": tool_rules,
|
2401
|
-
"include_base_tools": include_base_tools,
|
2402
|
-
"include_multi_agent_tools": include_multi_agent_tools,
|
2403
|
-
"include_base_tool_rules": include_base_tool_rules,
|
2404
|
-
"system": system,
|
2405
|
-
"agent_type": agent_type,
|
2406
|
-
"llm_config": llm_config if llm_config else self._default_llm_config,
|
2407
|
-
"embedding_config": embedding_config if embedding_config else self._default_embedding_config,
|
2408
|
-
"initial_message_sequence": initial_message_sequence,
|
2409
|
-
"tags": tags,
|
2410
|
-
"message_buffer_autoclear": message_buffer_autoclear,
|
2411
|
-
"response_format": response_format,
|
2412
|
-
}
|
2413
|
-
|
2414
|
-
# Only add name if it's not None
|
2415
|
-
if name is not None:
|
2416
|
-
create_params["name"] = name
|
2417
|
-
|
2418
|
-
agent_state = self.server.create_agent(
|
2419
|
-
CreateAgent(**create_params),
|
2420
|
-
actor=self.user,
|
2421
|
-
)
|
2422
|
-
|
2423
|
-
# TODO: get full agent state
|
2424
|
-
return self.server.agent_manager.get_agent_by_id(agent_state.id, actor=self.user)
|
2425
|
-
|
2426
|
-
def update_agent(
|
2427
|
-
self,
|
2428
|
-
agent_id: str,
|
2429
|
-
name: Optional[str] = None,
|
2430
|
-
description: Optional[str] = None,
|
2431
|
-
system: Optional[str] = None,
|
2432
|
-
tool_ids: Optional[List[str]] = None,
|
2433
|
-
tags: Optional[List[str]] = None,
|
2434
|
-
metadata: Optional[Dict] = None,
|
2435
|
-
llm_config: Optional[LLMConfig] = None,
|
2436
|
-
embedding_config: Optional[EmbeddingConfig] = None,
|
2437
|
-
message_ids: Optional[List[str]] = None,
|
2438
|
-
response_format: Optional[ResponseFormatUnion] = None,
|
2439
|
-
):
|
2440
|
-
"""
|
2441
|
-
Update an existing agent
|
2442
|
-
|
2443
|
-
Args:
|
2444
|
-
agent_id (str): ID of the agent
|
2445
|
-
name (str): Name of the agent
|
2446
|
-
description (str): Description of the agent
|
2447
|
-
system (str): System configuration
|
2448
|
-
tools (List[str]): List of tools
|
2449
|
-
metadata (Dict): Metadata
|
2450
|
-
llm_config (LLMConfig): LLM configuration
|
2451
|
-
embedding_config (EmbeddingConfig): Embedding configuration
|
2452
|
-
message_ids (List[str]): List of message IDs
|
2453
|
-
tags (List[str]): Tags for filtering agents
|
2454
|
-
|
2455
|
-
Returns:
|
2456
|
-
agent_state (AgentState): State of the updated agent
|
2457
|
-
"""
|
2458
|
-
# TODO: add the ability to reset linked block_ids
|
2459
|
-
self.interface.clear()
|
2460
|
-
agent_state = self.server.agent_manager.update_agent(
|
2461
|
-
agent_id,
|
2462
|
-
UpdateAgent(
|
2463
|
-
name=name,
|
2464
|
-
system=system,
|
2465
|
-
tool_ids=tool_ids,
|
2466
|
-
tags=tags,
|
2467
|
-
description=description,
|
2468
|
-
metadata=metadata,
|
2469
|
-
llm_config=llm_config,
|
2470
|
-
embedding_config=embedding_config,
|
2471
|
-
message_ids=message_ids,
|
2472
|
-
response_format=response_format,
|
2473
|
-
),
|
2474
|
-
actor=self.user,
|
2475
|
-
)
|
2476
|
-
return agent_state
|
2477
|
-
|
2478
|
-
def get_tools_from_agent(self, agent_id: str) -> List[Tool]:
|
2479
|
-
"""
|
2480
|
-
Get tools from an existing agent.
|
2481
|
-
|
2482
|
-
Args:
|
2483
|
-
agent_id (str): ID of the agent
|
2484
|
-
|
2485
|
-
Returns:
|
2486
|
-
List[Tool]: A list of Tool objs
|
2487
|
-
"""
|
2488
|
-
self.interface.clear()
|
2489
|
-
return self.server.agent_manager.get_agent_by_id(agent_id=agent_id, actor=self.user).tools
|
2490
|
-
|
2491
|
-
def attach_tool(self, agent_id: str, tool_id: str) -> AgentState:
|
2492
|
-
"""
|
2493
|
-
Add tool to an existing agent
|
2494
|
-
|
2495
|
-
Args:
|
2496
|
-
agent_id (str): ID of the agent
|
2497
|
-
tool_id (str): A tool id
|
2498
|
-
|
2499
|
-
Returns:
|
2500
|
-
agent_state (AgentState): State of the updated agent
|
2501
|
-
"""
|
2502
|
-
self.interface.clear()
|
2503
|
-
agent_state = self.server.agent_manager.attach_tool(agent_id=agent_id, tool_id=tool_id, actor=self.user)
|
2504
|
-
return agent_state
|
2505
|
-
|
2506
|
-
def detach_tool(self, agent_id: str, tool_id: str) -> AgentState:
|
2507
|
-
"""
|
2508
|
-
Removes tools from an existing agent
|
2509
|
-
|
2510
|
-
Args:
|
2511
|
-
agent_id (str): ID of the agent
|
2512
|
-
tool_id (str): The tool id
|
2513
|
-
|
2514
|
-
Returns:
|
2515
|
-
agent_state (AgentState): State of the updated agent
|
2516
|
-
"""
|
2517
|
-
self.interface.clear()
|
2518
|
-
agent_state = self.server.agent_manager.detach_tool(agent_id=agent_id, tool_id=tool_id, actor=self.user)
|
2519
|
-
return agent_state
|
2520
|
-
|
2521
|
-
def rename_agent(self, agent_id: str, new_name: str) -> AgentState:
|
2522
|
-
"""
|
2523
|
-
Rename an agent
|
2524
|
-
|
2525
|
-
Args:
|
2526
|
-
agent_id (str): ID of the agent
|
2527
|
-
new_name (str): New name for the agent
|
2528
|
-
|
2529
|
-
Returns:
|
2530
|
-
agent_state (AgentState): State of the updated agent
|
2531
|
-
"""
|
2532
|
-
return self.update_agent(agent_id, name=new_name)
|
2533
|
-
|
2534
|
-
def delete_agent(self, agent_id: str) -> None:
|
2535
|
-
"""
|
2536
|
-
Delete an agent
|
2537
|
-
|
2538
|
-
Args:
|
2539
|
-
agent_id (str): ID of the agent to delete
|
2540
|
-
"""
|
2541
|
-
self.server.agent_manager.delete_agent(agent_id=agent_id, actor=self.user)
|
2542
|
-
|
2543
|
-
def get_agent_by_name(self, agent_name: str) -> AgentState:
|
2544
|
-
"""
|
2545
|
-
Get an agent by its name
|
2546
|
-
|
2547
|
-
Args:
|
2548
|
-
agent_name (str): Name of the agent
|
2549
|
-
|
2550
|
-
Returns:
|
2551
|
-
agent_state (AgentState): State of the agent
|
2552
|
-
"""
|
2553
|
-
self.interface.clear()
|
2554
|
-
return self.server.agent_manager.get_agent_by_name(agent_name=agent_name, actor=self.user)
|
2555
|
-
|
2556
|
-
def get_agent(self, agent_id: str) -> AgentState:
|
2557
|
-
"""
|
2558
|
-
Get an agent's state by its ID.
|
2559
|
-
|
2560
|
-
Args:
|
2561
|
-
agent_id (str): ID of the agent
|
2562
|
-
|
2563
|
-
Returns:
|
2564
|
-
agent_state (AgentState): State representation of the agent
|
2565
|
-
"""
|
2566
|
-
self.interface.clear()
|
2567
|
-
return self.server.agent_manager.get_agent_by_id(agent_id=agent_id, actor=self.user)
|
2568
|
-
|
2569
|
-
def get_agent_id(self, agent_name: str) -> Optional[str]:
|
2570
|
-
"""
|
2571
|
-
Get the ID of an agent by name (names are unique per user)
|
2572
|
-
|
2573
|
-
Args:
|
2574
|
-
agent_name (str): Name of the agent
|
2575
|
-
|
2576
|
-
Returns:
|
2577
|
-
agent_id (str): ID of the agent
|
2578
|
-
"""
|
2579
|
-
|
2580
|
-
self.interface.clear()
|
2581
|
-
assert agent_name, f"Agent name must be provided"
|
2582
|
-
|
2583
|
-
# TODO: Refactor this futher to not have downstream users expect Optionals - this should just error
|
2584
|
-
try:
|
2585
|
-
return self.server.agent_manager.get_agent_by_name(agent_name=agent_name, actor=self.user).id
|
2586
|
-
except NoResultFound:
|
2587
|
-
return None
|
2588
|
-
|
2589
|
-
# memory
|
2590
|
-
def get_in_context_memory(self, agent_id: str) -> Memory:
|
2591
|
-
"""
|
2592
|
-
Get the in-context (i.e. core) memory of an agent
|
2593
|
-
|
2594
|
-
Args:
|
2595
|
-
agent_id (str): ID of the agent
|
2596
|
-
|
2597
|
-
Returns:
|
2598
|
-
memory (Memory): In-context memory of the agent
|
2599
|
-
"""
|
2600
|
-
memory = self.server.get_agent_memory(agent_id=agent_id, actor=self.user)
|
2601
|
-
return memory
|
2602
|
-
|
2603
|
-
def get_core_memory(self, agent_id: str) -> Memory:
|
2604
|
-
return self.get_in_context_memory(agent_id)
|
2605
|
-
|
2606
|
-
def update_in_context_memory(self, agent_id: str, section: str, value: Union[List[str], str]) -> Memory:
|
2607
|
-
"""
|
2608
|
-
Update the in-context memory of an agent
|
2609
|
-
|
2610
|
-
Args:
|
2611
|
-
agent_id (str): ID of the agent
|
2612
|
-
|
2613
|
-
Returns:
|
2614
|
-
memory (Memory): The updated in-context memory of the agent
|
2615
|
-
|
2616
|
-
"""
|
2617
|
-
# TODO: implement this (not sure what it should look like)
|
2618
|
-
memory = self.server.update_agent_core_memory(agent_id=agent_id, label=section, value=value, actor=self.user)
|
2619
|
-
return memory
|
2620
|
-
|
2621
|
-
def get_archival_memory_summary(self, agent_id: str) -> ArchivalMemorySummary:
|
2622
|
-
"""
|
2623
|
-
Get a summary of the archival memory of an agent
|
2624
|
-
|
2625
|
-
Args:
|
2626
|
-
agent_id (str): ID of the agent
|
2627
|
-
|
2628
|
-
Returns:
|
2629
|
-
summary (ArchivalMemorySummary): Summary of the archival memory
|
2630
|
-
|
2631
|
-
"""
|
2632
|
-
return self.server.get_archival_memory_summary(agent_id=agent_id, actor=self.user)
|
2633
|
-
|
2634
|
-
def get_recall_memory_summary(self, agent_id: str) -> RecallMemorySummary:
|
2635
|
-
"""
|
2636
|
-
Get a summary of the recall memory of an agent
|
2637
|
-
|
2638
|
-
Args:
|
2639
|
-
agent_id (str): ID of the agent
|
2640
|
-
|
2641
|
-
Returns:
|
2642
|
-
summary (RecallMemorySummary): Summary of the recall memory
|
2643
|
-
"""
|
2644
|
-
return self.server.get_recall_memory_summary(agent_id=agent_id, actor=self.user)
|
2645
|
-
|
2646
|
-
def get_in_context_messages(self, agent_id: str) -> List[Message]:
|
2647
|
-
"""
|
2648
|
-
Get in-context messages of an agent
|
2649
|
-
|
2650
|
-
Args:
|
2651
|
-
agent_id (str): ID of the agent
|
2652
|
-
|
2653
|
-
Returns:
|
2654
|
-
messages (List[Message]): List of in-context messages
|
2655
|
-
"""
|
2656
|
-
return self.server.agent_manager.get_in_context_messages(agent_id=agent_id, actor=self.user)
|
2657
|
-
|
2658
|
-
# agent interactions
|
2659
|
-
|
2660
|
-
def send_messages(
|
2661
|
-
self,
|
2662
|
-
agent_id: str,
|
2663
|
-
messages: List[Union[Message | MessageCreate]],
|
2664
|
-
):
|
2665
|
-
"""
|
2666
|
-
Send pre-packed messages to an agent.
|
2667
|
-
|
2668
|
-
Args:
|
2669
|
-
agent_id (str): ID of the agent
|
2670
|
-
messages (List[Union[Message | MessageCreate]]): List of messages to send
|
2671
|
-
|
2672
|
-
Returns:
|
2673
|
-
response (LettaResponse): Response from the agent
|
2674
|
-
"""
|
2675
|
-
self.interface.clear()
|
2676
|
-
usage = self.server.send_messages(actor=self.user, agent_id=agent_id, input_messages=messages)
|
2677
|
-
|
2678
|
-
# format messages
|
2679
|
-
return LettaResponse(messages=messages, usage=usage)
|
2680
|
-
|
2681
|
-
def send_message(
|
2682
|
-
self,
|
2683
|
-
message: str,
|
2684
|
-
role: str,
|
2685
|
-
name: Optional[str] = None,
|
2686
|
-
agent_id: Optional[str] = None,
|
2687
|
-
agent_name: Optional[str] = None,
|
2688
|
-
stream_steps: bool = False,
|
2689
|
-
stream_tokens: bool = False,
|
2690
|
-
) -> LettaResponse:
|
2691
|
-
"""
|
2692
|
-
Send a message to an agent
|
2693
|
-
|
2694
|
-
Args:
|
2695
|
-
message (str): Message to send
|
2696
|
-
role (str): Role of the message
|
2697
|
-
agent_id (str): ID of the agent
|
2698
|
-
name(str): Name of the sender
|
2699
|
-
stream (bool): Stream the response (default: `False`)
|
2700
|
-
|
2701
|
-
Returns:
|
2702
|
-
response (LettaResponse): Response from the agent
|
2703
|
-
"""
|
2704
|
-
if not agent_id:
|
2705
|
-
# lookup agent by name
|
2706
|
-
assert agent_name, f"Either agent_id or agent_name must be provided"
|
2707
|
-
agent_id = self.get_agent_id(agent_name=agent_name)
|
2708
|
-
assert agent_id, f"Agent with name {agent_name} not found"
|
2709
|
-
|
2710
|
-
if stream_steps or stream_tokens:
|
2711
|
-
# TODO: implement streaming with stream=True/False
|
2712
|
-
raise NotImplementedError
|
2713
|
-
self.interface.clear()
|
2714
|
-
|
2715
|
-
usage = self.server.send_messages(
|
2716
|
-
actor=self.user,
|
2717
|
-
agent_id=agent_id,
|
2718
|
-
input_messages=[MessageCreate(role=MessageRole(role), content=message, name=name)],
|
2719
|
-
)
|
2720
|
-
|
2721
|
-
## TODO: need to make sure date/timestamp is propely passed
|
2722
|
-
## TODO: update self.interface.to_list() to return actual Message objects
|
2723
|
-
## here, the message objects will have faulty created_by timestamps
|
2724
|
-
# messages = self.interface.to_list()
|
2725
|
-
# for m in messages:
|
2726
|
-
# assert isinstance(m, Message), f"Expected Message object, got {type(m)}"
|
2727
|
-
# letta_messages = []
|
2728
|
-
# for m in messages:
|
2729
|
-
# letta_messages += m.to_letta_messages()
|
2730
|
-
# return LettaResponse(messages=letta_messages, usage=usage)
|
2731
|
-
|
2732
|
-
# format messages
|
2733
|
-
messages = self.interface.to_list()
|
2734
|
-
letta_messages = []
|
2735
|
-
for m in messages:
|
2736
|
-
letta_messages += m.to_letta_messages()
|
2737
|
-
|
2738
|
-
return LettaResponse(messages=letta_messages, usage=usage)
|
2739
|
-
|
2740
|
-
def user_message(self, agent_id: str, message: str) -> LettaResponse:
|
2741
|
-
"""
|
2742
|
-
Send a message to an agent as a user
|
2743
|
-
|
2744
|
-
Args:
|
2745
|
-
agent_id (str): ID of the agent
|
2746
|
-
message (str): Message to send
|
2747
|
-
|
2748
|
-
Returns:
|
2749
|
-
response (LettaResponse): Response from the agent
|
2750
|
-
"""
|
2751
|
-
self.interface.clear()
|
2752
|
-
return self.send_message(role="user", agent_id=agent_id, message=message)
|
2753
|
-
|
2754
|
-
def run_command(self, agent_id: str, command: str) -> LettaResponse:
|
2755
|
-
"""
|
2756
|
-
Run a command on the agent
|
2757
|
-
|
2758
|
-
Args:
|
2759
|
-
agent_id (str): The agent ID
|
2760
|
-
command (str): The command to run
|
2761
|
-
|
2762
|
-
Returns:
|
2763
|
-
LettaResponse: The response from the agent
|
2764
|
-
|
2765
|
-
"""
|
2766
|
-
self.interface.clear()
|
2767
|
-
usage = self.server.run_command(user_id=self.user_id, agent_id=agent_id, command=command)
|
2768
|
-
|
2769
|
-
# NOTE: messages/usage may be empty, depending on the command
|
2770
|
-
return LettaResponse(messages=self.interface.to_list(), usage=usage)
|
2771
|
-
|
2772
|
-
# archival memory
|
2773
|
-
|
2774
|
-
# humans / personas
|
2775
|
-
|
2776
|
-
def get_block_id(self, name: str, label: str) -> str | None:
|
2777
|
-
return None
|
2778
|
-
|
2779
|
-
def create_human(self, name: str, text: str):
|
2780
|
-
"""
|
2781
|
-
Create a human block template (saved human string to pre-fill `ChatMemory`)
|
2782
|
-
|
2783
|
-
Args:
|
2784
|
-
name (str): Name of the human block
|
2785
|
-
text (str): Text of the human block
|
2786
|
-
|
2787
|
-
Returns:
|
2788
|
-
human (Human): Human block
|
2789
|
-
"""
|
2790
|
-
return self.server.block_manager.create_or_update_block(Human(template_name=name, value=text), actor=self.user)
|
2791
|
-
|
2792
|
-
def create_persona(self, name: str, text: str):
|
2793
|
-
"""
|
2794
|
-
Create a persona block template (saved persona string to pre-fill `ChatMemory`)
|
2795
|
-
|
2796
|
-
Args:
|
2797
|
-
name (str): Name of the persona block
|
2798
|
-
text (str): Text of the persona block
|
2799
|
-
|
2800
|
-
Returns:
|
2801
|
-
persona (Persona): Persona block
|
2802
|
-
"""
|
2803
|
-
return self.server.block_manager.create_or_update_block(Persona(template_name=name, value=text), actor=self.user)
|
2804
|
-
|
2805
|
-
def list_humans(self):
|
2806
|
-
"""
|
2807
|
-
List available human block templates
|
2808
|
-
|
2809
|
-
Returns:
|
2810
|
-
humans (List[Human]): List of human blocks
|
2811
|
-
"""
|
2812
|
-
return []
|
2813
|
-
|
2814
|
-
def list_personas(self) -> List[Persona]:
|
2815
|
-
"""
|
2816
|
-
List available persona block templates
|
2817
|
-
|
2818
|
-
Returns:
|
2819
|
-
personas (List[Persona]): List of persona blocks
|
2820
|
-
"""
|
2821
|
-
return []
|
2822
|
-
|
2823
|
-
def update_human(self, human_id: str, text: str):
|
2824
|
-
"""
|
2825
|
-
Update a human block template
|
2826
|
-
|
2827
|
-
Args:
|
2828
|
-
human_id (str): ID of the human block
|
2829
|
-
text (str): Text of the human block
|
2830
|
-
|
2831
|
-
Returns:
|
2832
|
-
human (Human): Updated human block
|
2833
|
-
"""
|
2834
|
-
return self.server.block_manager.update_block(
|
2835
|
-
block_id=human_id, block_update=UpdateHuman(value=text, is_template=True), actor=self.user
|
2836
|
-
)
|
2837
|
-
|
2838
|
-
def update_persona(self, persona_id: str, text: str):
|
2839
|
-
"""
|
2840
|
-
Update a persona block template
|
2841
|
-
|
2842
|
-
Args:
|
2843
|
-
persona_id (str): ID of the persona block
|
2844
|
-
text (str): Text of the persona block
|
2845
|
-
|
2846
|
-
Returns:
|
2847
|
-
persona (Persona): Updated persona block
|
2848
|
-
"""
|
2849
|
-
return self.server.block_manager.update_block(
|
2850
|
-
block_id=persona_id, block_update=UpdatePersona(value=text, is_template=True), actor=self.user
|
2851
|
-
)
|
2852
|
-
|
2853
|
-
def get_persona(self, id: str) -> Persona:
|
2854
|
-
"""
|
2855
|
-
Get a persona block template
|
2856
|
-
|
2857
|
-
Args:
|
2858
|
-
id (str): ID of the persona block
|
2859
|
-
|
2860
|
-
Returns:
|
2861
|
-
persona (Persona): Persona block
|
2862
|
-
"""
|
2863
|
-
assert id, f"Persona ID must be provided"
|
2864
|
-
return Persona(**self.server.block_manager.get_block_by_id(id, actor=self.user).model_dump())
|
2865
|
-
|
2866
|
-
def get_human(self, id: str) -> Human:
|
2867
|
-
"""
|
2868
|
-
Get a human block template
|
2869
|
-
|
2870
|
-
Args:
|
2871
|
-
id (str): ID of the human block
|
2872
|
-
|
2873
|
-
Returns:
|
2874
|
-
human (Human): Human block
|
2875
|
-
"""
|
2876
|
-
assert id, f"Human ID must be provided"
|
2877
|
-
return Human(**self.server.block_manager.get_block_by_id(id, actor=self.user).model_dump())
|
2878
|
-
|
2879
|
-
def get_persona_id(self, name: str) -> str | None:
|
2880
|
-
"""
|
2881
|
-
Get the ID of a persona block template
|
2882
|
-
|
2883
|
-
Args:
|
2884
|
-
name (str): Name of the persona block
|
2885
|
-
|
2886
|
-
Returns:
|
2887
|
-
id (str): ID of the persona block
|
2888
|
-
"""
|
2889
|
-
return None
|
2890
|
-
|
2891
|
-
def get_human_id(self, name: str) -> str | None:
|
2892
|
-
"""
|
2893
|
-
Get the ID of a human block template
|
2894
|
-
|
2895
|
-
Args:
|
2896
|
-
name (str): Name of the human block
|
2897
|
-
|
2898
|
-
Returns:
|
2899
|
-
id (str): ID of the human block
|
2900
|
-
"""
|
2901
|
-
return None
|
2902
|
-
|
2903
|
-
def delete_persona(self, id: str):
|
2904
|
-
"""
|
2905
|
-
Delete a persona block template
|
2906
|
-
|
2907
|
-
Args:
|
2908
|
-
id (str): ID of the persona block
|
2909
|
-
"""
|
2910
|
-
self.delete_block(id)
|
2911
|
-
|
2912
|
-
def delete_human(self, id: str):
|
2913
|
-
"""
|
2914
|
-
Delete a human block template
|
2915
|
-
|
2916
|
-
Args:
|
2917
|
-
id (str): ID of the human block
|
2918
|
-
"""
|
2919
|
-
self.delete_block(id)
|
2920
|
-
|
2921
|
-
# tools
|
2922
|
-
def load_langchain_tool(self, langchain_tool: "LangChainBaseTool", additional_imports_module_attr_map: dict[str, str] = None) -> Tool:
|
2923
|
-
tool_create = ToolCreate.from_langchain(
|
2924
|
-
langchain_tool=langchain_tool,
|
2925
|
-
additional_imports_module_attr_map=additional_imports_module_attr_map,
|
2926
|
-
)
|
2927
|
-
return self.server.tool_manager.create_or_update_langchain_tool(tool_create=tool_create, actor=self.user)
|
2928
|
-
|
2929
|
-
def load_composio_tool(self, action: "ActionType") -> Tool:
|
2930
|
-
tool_create = ToolCreate.from_composio(action_name=action.name)
|
2931
|
-
return self.server.tool_manager.create_or_update_composio_tool(tool_create=tool_create, actor=self.user)
|
2932
|
-
|
2933
|
-
def create_tool(
|
2934
|
-
self,
|
2935
|
-
func,
|
2936
|
-
tags: Optional[List[str]] = None,
|
2937
|
-
description: Optional[str] = None,
|
2938
|
-
return_char_limit: int = FUNCTION_RETURN_CHAR_LIMIT,
|
2939
|
-
) -> Tool:
|
2940
|
-
"""
|
2941
|
-
Create a tool. This stores the source code of function on the server, so that the server can execute the function and generate an OpenAI JSON schemas for it when using with an agent.
|
2942
|
-
|
2943
|
-
Args:
|
2944
|
-
func (callable): The function to create a tool for.
|
2945
|
-
tags (Optional[List[str]], optional): Tags for the tool. Defaults to None.
|
2946
|
-
description (str, optional): The description.
|
2947
|
-
return_char_limit (int): The character limit for the tool's return value. Defaults to FUNCTION_RETURN_CHAR_LIMIT.
|
2948
|
-
|
2949
|
-
Returns:
|
2950
|
-
tool (Tool): The created tool.
|
2951
|
-
"""
|
2952
|
-
# TODO: check if tool already exists
|
2953
|
-
# TODO: how to load modules?
|
2954
|
-
# parse source code/schema
|
2955
|
-
source_code = parse_source_code(func)
|
2956
|
-
source_type = "python"
|
2957
|
-
name = func.__name__ # Initialize name using function's __name__
|
2958
|
-
if not tags:
|
2959
|
-
tags = []
|
2960
|
-
|
2961
|
-
# call server function
|
2962
|
-
return self.server.tool_manager.create_tool(
|
2963
|
-
Tool(
|
2964
|
-
source_type=source_type,
|
2965
|
-
source_code=source_code,
|
2966
|
-
name=name,
|
2967
|
-
tags=tags,
|
2968
|
-
description=description,
|
2969
|
-
return_char_limit=return_char_limit,
|
2970
|
-
),
|
2971
|
-
actor=self.user,
|
2972
|
-
)
|
2973
|
-
|
2974
|
-
def create_or_update_tool(
|
2975
|
-
self,
|
2976
|
-
func,
|
2977
|
-
tags: Optional[List[str]] = None,
|
2978
|
-
description: Optional[str] = None,
|
2979
|
-
return_char_limit: int = FUNCTION_RETURN_CHAR_LIMIT,
|
2980
|
-
) -> Tool:
|
2981
|
-
"""
|
2982
|
-
Creates or updates a tool. This stores the source code of function on the server, so that the server can execute the function and generate an OpenAI JSON schemas for it when using with an agent.
|
2983
|
-
|
2984
|
-
Args:
|
2985
|
-
func (callable): The function to create a tool for.
|
2986
|
-
tags (Optional[List[str]], optional): Tags for the tool. Defaults to None.
|
2987
|
-
description (str, optional): The description.
|
2988
|
-
return_char_limit (int): The character limit for the tool's return value. Defaults to FUNCTION_RETURN_CHAR_LIMIT.
|
2989
|
-
|
2990
|
-
Returns:
|
2991
|
-
tool (Tool): The created tool.
|
2992
|
-
"""
|
2993
|
-
source_code = parse_source_code(func)
|
2994
|
-
source_type = "python"
|
2995
|
-
if not tags:
|
2996
|
-
tags = []
|
2997
|
-
|
2998
|
-
# call server function
|
2999
|
-
return self.server.tool_manager.create_or_update_tool(
|
3000
|
-
Tool(
|
3001
|
-
source_type=source_type,
|
3002
|
-
source_code=source_code,
|
3003
|
-
tags=tags,
|
3004
|
-
description=description,
|
3005
|
-
return_char_limit=return_char_limit,
|
3006
|
-
),
|
3007
|
-
actor=self.user,
|
3008
|
-
)
|
3009
|
-
|
3010
|
-
def update_tool(
|
3011
|
-
self,
|
3012
|
-
id: str,
|
3013
|
-
description: Optional[str] = None,
|
3014
|
-
func: Optional[Callable] = None,
|
3015
|
-
tags: Optional[List[str]] = None,
|
3016
|
-
return_char_limit: int = FUNCTION_RETURN_CHAR_LIMIT,
|
3017
|
-
) -> Tool:
|
3018
|
-
"""
|
3019
|
-
Update a tool with provided parameters (name, func, tags)
|
3020
|
-
|
3021
|
-
Args:
|
3022
|
-
id (str): ID of the tool
|
3023
|
-
func (callable): Function to wrap in a tool
|
3024
|
-
tags (List[str]): Tags for the tool
|
3025
|
-
return_char_limit (int): The character limit for the tool's return value. Defaults to FUNCTION_RETURN_CHAR_LIMIT.
|
3026
|
-
|
3027
|
-
Returns:
|
3028
|
-
tool (Tool): Updated tool
|
3029
|
-
"""
|
3030
|
-
update_data = {
|
3031
|
-
"source_type": "python", # Always include source_type
|
3032
|
-
"source_code": parse_source_code(func) if func else None,
|
3033
|
-
"tags": tags,
|
3034
|
-
"description": description,
|
3035
|
-
"return_char_limit": return_char_limit,
|
3036
|
-
}
|
3037
|
-
|
3038
|
-
# Filter out any None values from the dictionary
|
3039
|
-
update_data = {key: value for key, value in update_data.items() if value is not None}
|
3040
|
-
|
3041
|
-
return self.server.tool_manager.update_tool_by_id(tool_id=id, tool_update=ToolUpdate(**update_data), actor=self.user)
|
3042
|
-
|
3043
|
-
def list_tools(self, after: Optional[str] = None, limit: Optional[int] = 50) -> List[Tool]:
|
3044
|
-
"""
|
3045
|
-
List available tools for the user.
|
3046
|
-
|
3047
|
-
Returns:
|
3048
|
-
tools (List[Tool]): List of tools
|
3049
|
-
"""
|
3050
|
-
# Get the current event loop or create a new one if there isn't one
|
3051
|
-
try:
|
3052
|
-
loop = asyncio.get_event_loop()
|
3053
|
-
if loop.is_running():
|
3054
|
-
# We're in an async context but can't await - use a new loop via run_coroutine_threadsafe
|
3055
|
-
concurrent_future = asyncio.run_coroutine_threadsafe(
|
3056
|
-
self.server.tool_manager.list_tools_async(actor=self.user, after=after, limit=limit), loop
|
3057
|
-
)
|
3058
|
-
return concurrent_future.result()
|
3059
|
-
else:
|
3060
|
-
# We have a loop but it's not running - we can just run the coroutine
|
3061
|
-
return loop.run_until_complete(self.server.tool_manager.list_tools_async(actor=self.user, after=after, limit=limit))
|
3062
|
-
except RuntimeError:
|
3063
|
-
# No running event loop - create a new one with asyncio.run
|
3064
|
-
return asyncio.run(self.server.tool_manager.list_tools_async(actor=self.user, after=after, limit=limit))
|
3065
|
-
|
3066
|
-
def get_tool(self, id: str) -> Optional[Tool]:
|
3067
|
-
"""
|
3068
|
-
Get a tool given its ID.
|
3069
|
-
|
3070
|
-
Args:
|
3071
|
-
id (str): ID of the tool
|
3072
|
-
|
3073
|
-
Returns:
|
3074
|
-
tool (Tool): Tool
|
3075
|
-
"""
|
3076
|
-
return self.server.tool_manager.get_tool_by_id(id, actor=self.user)
|
3077
|
-
|
3078
|
-
def delete_tool(self, id: str):
|
3079
|
-
"""
|
3080
|
-
Delete a tool given the ID.
|
3081
|
-
|
3082
|
-
Args:
|
3083
|
-
id (str): ID of the tool
|
3084
|
-
"""
|
3085
|
-
return self.server.tool_manager.delete_tool_by_id(id, actor=self.user)
|
3086
|
-
|
3087
|
-
def get_tool_id(self, name: str) -> Optional[str]:
|
3088
|
-
"""
|
3089
|
-
Get the ID of a tool from its name. The client will use the org_id it is configured with.
|
3090
|
-
|
3091
|
-
Args:
|
3092
|
-
name (str): Name of the tool
|
3093
|
-
|
3094
|
-
Returns:
|
3095
|
-
id (str): ID of the tool (`None` if not found)
|
3096
|
-
"""
|
3097
|
-
tool = self.server.tool_manager.get_tool_by_name(tool_name=name, actor=self.user)
|
3098
|
-
return tool.id if tool else None
|
3099
|
-
|
3100
|
-
def list_attached_tools(self, agent_id: str) -> List[Tool]:
|
3101
|
-
"""
|
3102
|
-
List all tools attached to an agent.
|
3103
|
-
|
3104
|
-
Args:
|
3105
|
-
agent_id (str): ID of the agent
|
3106
|
-
|
3107
|
-
Returns:
|
3108
|
-
List[Tool]: List of tools attached to the agent
|
3109
|
-
"""
|
3110
|
-
return self.server.agent_manager.list_attached_tools(agent_id=agent_id, actor=self.user)
|
3111
|
-
|
3112
|
-
def load_data(self, connector: DataConnector, source_name: str):
|
3113
|
-
"""
|
3114
|
-
Load data into a source
|
3115
|
-
|
3116
|
-
Args:
|
3117
|
-
connector (DataConnector): Data connector
|
3118
|
-
source_name (str): Name of the source
|
3119
|
-
"""
|
3120
|
-
self.server.load_data(user_id=self.user_id, connector=connector, source_name=source_name)
|
3121
|
-
|
3122
|
-
def load_file_to_source(self, filename: str, source_id: str, blocking=True):
|
3123
|
-
"""
|
3124
|
-
Load a file into a source
|
3125
|
-
|
3126
|
-
Args:
|
3127
|
-
filename (str): Name of the file
|
3128
|
-
source_id (str): ID of the source
|
3129
|
-
blocking (bool): Block until the job is complete
|
3130
|
-
|
3131
|
-
Returns:
|
3132
|
-
job (Job): Data loading job including job status and metadata
|
3133
|
-
"""
|
3134
|
-
job = Job(
|
3135
|
-
user_id=self.user_id,
|
3136
|
-
status=JobStatus.created,
|
3137
|
-
metadata={"type": "embedding", "filename": filename, "source_id": source_id},
|
3138
|
-
)
|
3139
|
-
job = self.server.job_manager.create_job(pydantic_job=job, actor=self.user)
|
3140
|
-
|
3141
|
-
# TODO: implement blocking vs. non-blocking
|
3142
|
-
self.server.load_file_to_source(source_id=source_id, file_path=filename, job_id=job.id, actor=self.user)
|
3143
|
-
return job
|
3144
|
-
|
3145
|
-
def delete_file_from_source(self, source_id: str, file_id: str) -> None:
|
3146
|
-
self.server.source_manager.delete_file(file_id, actor=self.user)
|
3147
|
-
|
3148
|
-
def get_job(self, job_id: str):
|
3149
|
-
return self.server.job_manager.get_job_by_id(job_id=job_id, actor=self.user)
|
3150
|
-
|
3151
|
-
def delete_job(self, job_id: str):
|
3152
|
-
return self.server.job_manager.delete_job_by_id(job_id=job_id, actor=self.user)
|
3153
|
-
|
3154
|
-
def list_jobs(self):
|
3155
|
-
return self.server.job_manager.list_jobs(actor=self.user)
|
3156
|
-
|
3157
|
-
def list_active_jobs(self):
|
3158
|
-
return self.server.job_manager.list_jobs(actor=self.user, statuses=[JobStatus.created, JobStatus.running])
|
3159
|
-
|
3160
|
-
def create_source(self, name: str, embedding_config: Optional[EmbeddingConfig] = None) -> Source:
|
3161
|
-
"""
|
3162
|
-
Create a source
|
3163
|
-
|
3164
|
-
Args:
|
3165
|
-
name (str): Name of the source
|
3166
|
-
|
3167
|
-
Returns:
|
3168
|
-
source (Source): Created source
|
3169
|
-
"""
|
3170
|
-
assert embedding_config or self._default_embedding_config, f"Must specify embedding_config for source"
|
3171
|
-
source = Source(
|
3172
|
-
name=name, embedding_config=embedding_config or self._default_embedding_config, organization_id=self.user.organization_id
|
3173
|
-
)
|
3174
|
-
return self.server.source_manager.create_source(source=source, actor=self.user)
|
3175
|
-
|
3176
|
-
def delete_source(self, source_id: str):
|
3177
|
-
"""
|
3178
|
-
Delete a source
|
3179
|
-
|
3180
|
-
Args:
|
3181
|
-
source_id (str): ID of the source
|
3182
|
-
"""
|
3183
|
-
|
3184
|
-
# TODO: delete source data
|
3185
|
-
self.server.delete_source(source_id=source_id, actor=self.user)
|
3186
|
-
|
3187
|
-
def get_source(self, source_id: str) -> Source:
|
3188
|
-
"""
|
3189
|
-
Get a source given the ID.
|
3190
|
-
|
3191
|
-
Args:
|
3192
|
-
source_id (str): ID of the source
|
3193
|
-
|
3194
|
-
Returns:
|
3195
|
-
source (Source): Source
|
3196
|
-
"""
|
3197
|
-
return self.server.source_manager.get_source_by_id(source_id=source_id, actor=self.user)
|
3198
|
-
|
3199
|
-
def get_source_id(self, source_name: str) -> str:
|
3200
|
-
"""
|
3201
|
-
Get the ID of a source
|
3202
|
-
|
3203
|
-
Args:
|
3204
|
-
source_name (str): Name of the source
|
3205
|
-
|
3206
|
-
Returns:
|
3207
|
-
source_id (str): ID of the source
|
3208
|
-
"""
|
3209
|
-
return self.server.source_manager.get_source_by_name(source_name=source_name, actor=self.user).id
|
3210
|
-
|
3211
|
-
def attach_source(self, agent_id: str, source_id: Optional[str] = None, source_name: Optional[str] = None) -> AgentState:
|
3212
|
-
"""
|
3213
|
-
Attach a source to an agent
|
3214
|
-
|
3215
|
-
Args:
|
3216
|
-
agent_id (str): ID of the agent
|
3217
|
-
source_id (str): ID of the source
|
3218
|
-
source_name (str): Name of the source
|
3219
|
-
"""
|
3220
|
-
if source_name:
|
3221
|
-
source = self.server.source_manager.get_source_by_id(source_id=source_id, actor=self.user)
|
3222
|
-
source_id = source.id
|
3223
|
-
|
3224
|
-
return self.server.agent_manager.attach_source(source_id=source_id, agent_id=agent_id, actor=self.user)
|
3225
|
-
|
3226
|
-
def detach_source(self, agent_id: str, source_id: Optional[str] = None, source_name: Optional[str] = None) -> AgentState:
|
3227
|
-
"""
|
3228
|
-
Detach a source from an agent by removing all `Passage` objects that were loaded from the source from archival memory.
|
3229
|
-
Args:
|
3230
|
-
agent_id (str): ID of the agent
|
3231
|
-
source_id (str): ID of the source
|
3232
|
-
source_name (str): Name of the source
|
3233
|
-
Returns:
|
3234
|
-
source (Source): Detached source
|
3235
|
-
"""
|
3236
|
-
if source_name:
|
3237
|
-
source = self.server.source_manager.get_source_by_id(source_id=source_id, actor=self.user)
|
3238
|
-
source_id = source.id
|
3239
|
-
return self.server.agent_manager.detach_source(agent_id=agent_id, source_id=source_id, actor=self.user)
|
3240
|
-
|
3241
|
-
def list_sources(self) -> List[Source]:
|
3242
|
-
"""
|
3243
|
-
List available sources
|
3244
|
-
|
3245
|
-
Returns:
|
3246
|
-
sources (List[Source]): List of sources
|
3247
|
-
"""
|
3248
|
-
|
3249
|
-
return self.server.list_all_sources(actor=self.user)
|
3250
|
-
|
3251
|
-
def list_attached_sources(self, agent_id: str) -> List[Source]:
|
3252
|
-
"""
|
3253
|
-
List sources attached to an agent
|
3254
|
-
|
3255
|
-
Args:
|
3256
|
-
agent_id (str): ID of the agent
|
3257
|
-
|
3258
|
-
Returns:
|
3259
|
-
sources (List[Source]): List of sources
|
3260
|
-
"""
|
3261
|
-
return self.server.agent_manager.list_attached_sources(agent_id=agent_id, actor=self.user)
|
3262
|
-
|
3263
|
-
def list_files_from_source(self, source_id: str, limit: int = 1000, after: Optional[str] = None) -> List[FileMetadata]:
|
3264
|
-
"""
|
3265
|
-
List files from source.
|
3266
|
-
|
3267
|
-
Args:
|
3268
|
-
source_id (str): ID of the source
|
3269
|
-
limit (int): The # of items to return
|
3270
|
-
after (str): The cursor for fetching the next page
|
3271
|
-
|
3272
|
-
Returns:
|
3273
|
-
files (List[FileMetadata]): List of files
|
3274
|
-
"""
|
3275
|
-
return self.server.source_manager.list_files(source_id=source_id, limit=limit, after=after, actor=self.user)
|
3276
|
-
|
3277
|
-
def update_source(self, source_id: str, name: Optional[str] = None) -> Source:
|
3278
|
-
"""
|
3279
|
-
Update a source
|
3280
|
-
|
3281
|
-
Args:
|
3282
|
-
source_id (str): ID of the source
|
3283
|
-
name (str): Name of the source
|
3284
|
-
|
3285
|
-
Returns:
|
3286
|
-
source (Source): Updated source
|
3287
|
-
"""
|
3288
|
-
# TODO should the arg here just be "source_update: Source"?
|
3289
|
-
request = SourceUpdate(name=name)
|
3290
|
-
return self.server.source_manager.update_source(source_id=source_id, source_update=request, actor=self.user)
|
3291
|
-
|
3292
|
-
# archival memory
|
3293
|
-
|
3294
|
-
def insert_archival_memory(self, agent_id: str, memory: str) -> List[Passage]:
|
3295
|
-
"""
|
3296
|
-
Insert archival memory into an agent
|
3297
|
-
|
3298
|
-
Args:
|
3299
|
-
agent_id (str): ID of the agent
|
3300
|
-
memory (str): Memory string to insert
|
3301
|
-
|
3302
|
-
Returns:
|
3303
|
-
passages (List[Passage]): List of inserted passages
|
3304
|
-
"""
|
3305
|
-
return self.server.insert_archival_memory(agent_id=agent_id, memory_contents=memory, actor=self.user)
|
3306
|
-
|
3307
|
-
def delete_archival_memory(self, agent_id: str, memory_id: str):
|
3308
|
-
"""
|
3309
|
-
Delete archival memory from an agent
|
3310
|
-
|
3311
|
-
Args:
|
3312
|
-
agent_id (str): ID of the agent
|
3313
|
-
memory_id (str): ID of the memory
|
3314
|
-
"""
|
3315
|
-
self.server.delete_archival_memory(memory_id=memory_id, actor=self.user)
|
3316
|
-
|
3317
|
-
def get_archival_memory(
|
3318
|
-
self, agent_id: str, before: Optional[str] = None, after: Optional[str] = None, limit: Optional[int] = 1000
|
3319
|
-
) -> List[Passage]:
|
3320
|
-
"""
|
3321
|
-
Get archival memory from an agent with pagination.
|
3322
|
-
|
3323
|
-
Args:
|
3324
|
-
agent_id (str): ID of the agent
|
3325
|
-
before (str): Get memories before a certain time
|
3326
|
-
after (str): Get memories after a certain time
|
3327
|
-
limit (int): Limit number of memories
|
3328
|
-
|
3329
|
-
Returns:
|
3330
|
-
passages (List[Passage]): List of passages
|
3331
|
-
"""
|
3332
|
-
|
3333
|
-
return self.server.get_agent_archival(user_id=self.user_id, agent_id=agent_id, limit=limit)
|
3334
|
-
|
3335
|
-
# recall memory
|
3336
|
-
|
3337
|
-
def get_messages(
|
3338
|
-
self, agent_id: str, before: Optional[str] = None, after: Optional[str] = None, limit: Optional[int] = 1000
|
3339
|
-
) -> List[LettaMessage]:
|
3340
|
-
"""
|
3341
|
-
Get messages from an agent with pagination.
|
3342
|
-
|
3343
|
-
Args:
|
3344
|
-
agent_id (str): ID of the agent
|
3345
|
-
before (str): Get messages before a certain time
|
3346
|
-
after (str): Get messages after a certain time
|
3347
|
-
limit (int): Limit number of messages
|
3348
|
-
|
3349
|
-
Returns:
|
3350
|
-
messages (List[Message]): List of messages
|
3351
|
-
"""
|
3352
|
-
|
3353
|
-
self.interface.clear()
|
3354
|
-
return self.server.get_agent_recall(
|
3355
|
-
user_id=self.user_id,
|
3356
|
-
agent_id=agent_id,
|
3357
|
-
before=before,
|
3358
|
-
after=after,
|
3359
|
-
limit=limit,
|
3360
|
-
reverse=True,
|
3361
|
-
return_message_object=False,
|
3362
|
-
)
|
3363
|
-
|
3364
|
-
def list_blocks(self, label: Optional[str] = None, templates_only: Optional[bool] = True) -> List[Block]:
|
3365
|
-
"""
|
3366
|
-
List available blocks
|
3367
|
-
|
3368
|
-
Args:
|
3369
|
-
label (str): Label of the block
|
3370
|
-
templates_only (bool): List only templates
|
3371
|
-
|
3372
|
-
Returns:
|
3373
|
-
blocks (List[Block]): List of blocks
|
3374
|
-
"""
|
3375
|
-
return []
|
3376
|
-
|
3377
|
-
def create_block(
|
3378
|
-
self, label: str, value: str, limit: Optional[int] = None, template_name: Optional[str] = None, is_template: bool = False
|
3379
|
-
) -> Block: #
|
3380
|
-
"""
|
3381
|
-
Create a block
|
3382
|
-
|
3383
|
-
Args:
|
3384
|
-
label (str): Label of the block
|
3385
|
-
name (str): Name of the block
|
3386
|
-
text (str): Text of the block
|
3387
|
-
limit (int): Character of the block
|
3388
|
-
|
3389
|
-
Returns:
|
3390
|
-
block (Block): Created block
|
3391
|
-
"""
|
3392
|
-
block = Block(label=label, template_name=template_name, value=value, is_template=is_template)
|
3393
|
-
if limit:
|
3394
|
-
block.limit = limit
|
3395
|
-
return self.server.block_manager.create_or_update_block(block, actor=self.user)
|
3396
|
-
|
3397
|
-
def update_block(self, block_id: str, name: Optional[str] = None, text: Optional[str] = None, limit: Optional[int] = None) -> Block:
|
3398
|
-
"""
|
3399
|
-
Update a block
|
3400
|
-
|
3401
|
-
Args:
|
3402
|
-
block_id (str): ID of the block
|
3403
|
-
name (str): Name of the block
|
3404
|
-
text (str): Text of the block
|
3405
|
-
|
3406
|
-
Returns:
|
3407
|
-
block (Block): Updated block
|
3408
|
-
"""
|
3409
|
-
return self.server.block_manager.update_block(
|
3410
|
-
block_id=block_id,
|
3411
|
-
block_update=BlockUpdate(template_name=name, value=text, limit=limit if limit else self.get_block(block_id).limit),
|
3412
|
-
actor=self.user,
|
3413
|
-
)
|
3414
|
-
|
3415
|
-
def get_block(self, block_id: str) -> Block:
|
3416
|
-
"""
|
3417
|
-
Get a block
|
3418
|
-
|
3419
|
-
Args:
|
3420
|
-
block_id (str): ID of the block
|
3421
|
-
|
3422
|
-
Returns:
|
3423
|
-
block (Block): Block
|
3424
|
-
"""
|
3425
|
-
return self.server.block_manager.get_block_by_id(block_id, actor=self.user)
|
3426
|
-
|
3427
|
-
def delete_block(self, id: str) -> Block:
|
3428
|
-
"""
|
3429
|
-
Delete a block
|
3430
|
-
|
3431
|
-
Args:
|
3432
|
-
id (str): ID of the block
|
3433
|
-
|
3434
|
-
Returns:
|
3435
|
-
block (Block): Deleted block
|
3436
|
-
"""
|
3437
|
-
return self.server.block_manager.delete_block(id, actor=self.user)
|
3438
|
-
|
3439
|
-
def set_default_llm_config(self, llm_config: LLMConfig):
|
3440
|
-
"""
|
3441
|
-
Set the default LLM configuration for agents.
|
3442
|
-
|
3443
|
-
Args:
|
3444
|
-
llm_config (LLMConfig): LLM configuration
|
3445
|
-
"""
|
3446
|
-
self._default_llm_config = llm_config
|
3447
|
-
|
3448
|
-
def set_default_embedding_config(self, embedding_config: EmbeddingConfig):
|
3449
|
-
"""
|
3450
|
-
Set the default embedding configuration for agents.
|
3451
|
-
|
3452
|
-
Args:
|
3453
|
-
embedding_config (EmbeddingConfig): Embedding configuration
|
3454
|
-
"""
|
3455
|
-
self._default_embedding_config = embedding_config
|
3456
|
-
|
3457
|
-
def list_llm_configs(self) -> List[LLMConfig]:
|
3458
|
-
"""
|
3459
|
-
List available LLM configurations
|
3460
|
-
|
3461
|
-
Returns:
|
3462
|
-
configs (List[LLMConfig]): List of LLM configurations
|
3463
|
-
"""
|
3464
|
-
return self.server.list_llm_models(actor=self.user)
|
3465
|
-
|
3466
|
-
def list_embedding_configs(self) -> List[EmbeddingConfig]:
|
3467
|
-
"""
|
3468
|
-
List available embedding configurations
|
3469
|
-
|
3470
|
-
Returns:
|
3471
|
-
configs (List[EmbeddingConfig]): List of embedding configurations
|
3472
|
-
"""
|
3473
|
-
return self.server.list_embedding_models(actor=self.user)
|
3474
|
-
|
3475
|
-
def create_org(self, name: Optional[str] = None) -> Organization:
|
3476
|
-
return self.server.organization_manager.create_organization(pydantic_org=Organization(name=name))
|
3477
|
-
|
3478
|
-
def list_orgs(self, after: Optional[str] = None, limit: Optional[int] = 50) -> List[Organization]:
|
3479
|
-
return self.server.organization_manager.list_organizations(limit=limit, after=after)
|
3480
|
-
|
3481
|
-
def delete_org(self, org_id: str) -> Organization:
|
3482
|
-
return self.server.organization_manager.delete_organization_by_id(org_id=org_id)
|
3483
|
-
|
3484
|
-
def create_sandbox_config(self, config: Union[LocalSandboxConfig, E2BSandboxConfig]) -> SandboxConfig:
|
3485
|
-
"""
|
3486
|
-
Create a new sandbox configuration.
|
3487
|
-
"""
|
3488
|
-
config_create = SandboxConfigCreate(config=config)
|
3489
|
-
return self.server.sandbox_config_manager.create_or_update_sandbox_config(sandbox_config_create=config_create, actor=self.user)
|
3490
|
-
|
3491
|
-
def update_sandbox_config(self, sandbox_config_id: str, config: Union[LocalSandboxConfig, E2BSandboxConfig]) -> SandboxConfig:
|
3492
|
-
"""
|
3493
|
-
Update an existing sandbox configuration.
|
3494
|
-
"""
|
3495
|
-
sandbox_update = SandboxConfigUpdate(config=config)
|
3496
|
-
return self.server.sandbox_config_manager.update_sandbox_config(
|
3497
|
-
sandbox_config_id=sandbox_config_id, sandbox_update=sandbox_update, actor=self.user
|
3498
|
-
)
|
3499
|
-
|
3500
|
-
def delete_sandbox_config(self, sandbox_config_id: str) -> None:
|
3501
|
-
"""
|
3502
|
-
Delete a sandbox configuration.
|
3503
|
-
"""
|
3504
|
-
return self.server.sandbox_config_manager.delete_sandbox_config(sandbox_config_id=sandbox_config_id, actor=self.user)
|
3505
|
-
|
3506
|
-
def list_sandbox_configs(self, limit: int = 50, after: Optional[str] = None) -> List[SandboxConfig]:
|
3507
|
-
"""
|
3508
|
-
List all sandbox configurations.
|
3509
|
-
"""
|
3510
|
-
return self.server.sandbox_config_manager.list_sandbox_configs(actor=self.user, limit=limit, after=after)
|
3511
|
-
|
3512
|
-
def create_sandbox_env_var(
|
3513
|
-
self, sandbox_config_id: str, key: str, value: str, description: Optional[str] = None
|
3514
|
-
) -> SandboxEnvironmentVariable:
|
3515
|
-
"""
|
3516
|
-
Create a new environment variable for a sandbox configuration.
|
3517
|
-
"""
|
3518
|
-
env_var_create = SandboxEnvironmentVariableCreate(key=key, value=value, description=description)
|
3519
|
-
return self.server.sandbox_config_manager.create_sandbox_env_var(
|
3520
|
-
env_var_create=env_var_create, sandbox_config_id=sandbox_config_id, actor=self.user
|
3521
|
-
)
|
3522
|
-
|
3523
|
-
def update_sandbox_env_var(
|
3524
|
-
self, env_var_id: str, key: Optional[str] = None, value: Optional[str] = None, description: Optional[str] = None
|
3525
|
-
) -> SandboxEnvironmentVariable:
|
3526
|
-
"""
|
3527
|
-
Update an existing environment variable.
|
3528
|
-
"""
|
3529
|
-
env_var_update = SandboxEnvironmentVariableUpdate(key=key, value=value, description=description)
|
3530
|
-
return self.server.sandbox_config_manager.update_sandbox_env_var(
|
3531
|
-
env_var_id=env_var_id, env_var_update=env_var_update, actor=self.user
|
3532
|
-
)
|
3533
|
-
|
3534
|
-
def delete_sandbox_env_var(self, env_var_id: str) -> None:
|
3535
|
-
"""
|
3536
|
-
Delete an environment variable by its ID.
|
3537
|
-
"""
|
3538
|
-
return self.server.sandbox_config_manager.delete_sandbox_env_var(env_var_id=env_var_id, actor=self.user)
|
3539
|
-
|
3540
|
-
def list_sandbox_env_vars(
|
3541
|
-
self, sandbox_config_id: str, limit: int = 50, after: Optional[str] = None
|
3542
|
-
) -> List[SandboxEnvironmentVariable]:
|
3543
|
-
"""
|
3544
|
-
List all environment variables associated with a sandbox configuration.
|
3545
|
-
"""
|
3546
|
-
return self.server.sandbox_config_manager.list_sandbox_env_vars(
|
3547
|
-
sandbox_config_id=sandbox_config_id, actor=self.user, limit=limit, after=after
|
3548
|
-
)
|
3549
|
-
|
3550
|
-
def update_agent_memory_block_label(self, agent_id: str, current_label: str, new_label: str) -> Memory:
|
3551
|
-
"""Rename a block in the agent's core memory
|
3552
|
-
|
3553
|
-
Args:
|
3554
|
-
agent_id (str): The agent ID
|
3555
|
-
current_label (str): The current label of the block
|
3556
|
-
new_label (str): The new label of the block
|
3557
|
-
|
3558
|
-
Returns:
|
3559
|
-
memory (Memory): The updated memory
|
3560
|
-
"""
|
3561
|
-
block = self.get_agent_memory_block(agent_id, current_label)
|
3562
|
-
return self.update_block(block.id, label=new_label)
|
3563
|
-
|
3564
|
-
def get_agent_memory_blocks(self, agent_id: str) -> List[Block]:
|
3565
|
-
"""
|
3566
|
-
Get all the blocks in the agent's core memory
|
3567
|
-
|
3568
|
-
Args:
|
3569
|
-
agent_id (str): The agent ID
|
3570
|
-
|
3571
|
-
Returns:
|
3572
|
-
blocks (List[Block]): The blocks in the agent's core memory
|
3573
|
-
"""
|
3574
|
-
agent = self.server.agent_manager.get_agent_by_id(agent_id=agent_id, actor=self.user)
|
3575
|
-
return agent.memory.blocks
|
3576
|
-
|
3577
|
-
def get_agent_memory_block(self, agent_id: str, label: str) -> Block:
|
3578
|
-
"""
|
3579
|
-
Get a block in the agent's core memory by its label
|
3580
|
-
|
3581
|
-
Args:
|
3582
|
-
agent_id (str): The agent ID
|
3583
|
-
label (str): The label in the agent's core memory
|
3584
|
-
|
3585
|
-
Returns:
|
3586
|
-
block (Block): The block corresponding to the label
|
3587
|
-
"""
|
3588
|
-
return self.server.agent_manager.get_block_with_label(agent_id=agent_id, block_label=label, actor=self.user)
|
3589
|
-
|
3590
|
-
def update_agent_memory_block(
|
3591
|
-
self,
|
3592
|
-
agent_id: str,
|
3593
|
-
label: str,
|
3594
|
-
value: Optional[str] = None,
|
3595
|
-
limit: Optional[int] = None,
|
3596
|
-
):
|
3597
|
-
"""
|
3598
|
-
Update a block in the agent's core memory by specifying its label
|
3599
|
-
|
3600
|
-
Args:
|
3601
|
-
agent_id (str): The agent ID
|
3602
|
-
label (str): The label of the block
|
3603
|
-
value (str): The new value of the block
|
3604
|
-
limit (int): The new limit of the block
|
3605
|
-
|
3606
|
-
Returns:
|
3607
|
-
block (Block): The updated block
|
3608
|
-
"""
|
3609
|
-
block = self.get_agent_memory_block(agent_id, label)
|
3610
|
-
data = {}
|
3611
|
-
if value:
|
3612
|
-
data["value"] = value
|
3613
|
-
if limit:
|
3614
|
-
data["limit"] = limit
|
3615
|
-
return self.server.block_manager.update_block(block.id, actor=self.user, block_update=BlockUpdate(**data))
|
3616
|
-
|
3617
|
-
def update_block(
|
3618
|
-
self,
|
3619
|
-
block_id: str,
|
3620
|
-
label: Optional[str] = None,
|
3621
|
-
value: Optional[str] = None,
|
3622
|
-
limit: Optional[int] = None,
|
3623
|
-
):
|
3624
|
-
"""
|
3625
|
-
Update a block given the ID with the provided fields
|
3626
|
-
|
3627
|
-
Args:
|
3628
|
-
block_id (str): ID of the block
|
3629
|
-
label (str): Label to assign to the block
|
3630
|
-
value (str): Value to assign to the block
|
3631
|
-
limit (int): Token limit to assign to the block
|
3632
|
-
|
3633
|
-
Returns:
|
3634
|
-
block (Block): Updated block
|
3635
|
-
"""
|
3636
|
-
data = {}
|
3637
|
-
if value:
|
3638
|
-
data["value"] = value
|
3639
|
-
if limit:
|
3640
|
-
data["limit"] = limit
|
3641
|
-
if label:
|
3642
|
-
data["label"] = label
|
3643
|
-
return self.server.block_manager.update_block(block_id, actor=self.user, block_update=BlockUpdate(**data))
|
3644
|
-
|
3645
|
-
def attach_block(self, agent_id: str, block_id: str) -> AgentState:
|
3646
|
-
"""
|
3647
|
-
Attach a block to an agent.
|
3648
|
-
|
3649
|
-
Args:
|
3650
|
-
agent_id (str): ID of the agent
|
3651
|
-
block_id (str): ID of the block to attach
|
3652
|
-
"""
|
3653
|
-
return self.server.agent_manager.attach_block(agent_id=agent_id, block_id=block_id, actor=self.user)
|
3654
|
-
|
3655
|
-
def detach_block(self, agent_id: str, block_id: str) -> AgentState:
|
3656
|
-
"""
|
3657
|
-
Detach a block from an agent.
|
3658
|
-
|
3659
|
-
Args:
|
3660
|
-
agent_id (str): ID of the agent
|
3661
|
-
block_id (str): ID of the block to detach
|
3662
|
-
"""
|
3663
|
-
return self.server.agent_manager.detach_block(agent_id=agent_id, block_id=block_id, actor=self.user)
|
3664
|
-
|
3665
|
-
def get_run_messages(
|
3666
|
-
self,
|
3667
|
-
run_id: str,
|
3668
|
-
before: Optional[str] = None,
|
3669
|
-
after: Optional[str] = None,
|
3670
|
-
limit: Optional[int] = 100,
|
3671
|
-
ascending: bool = True,
|
3672
|
-
role: Optional[MessageRole] = None,
|
3673
|
-
) -> List[LettaMessageUnion]:
|
3674
|
-
"""
|
3675
|
-
Get messages associated with a job with filtering options.
|
3676
|
-
|
3677
|
-
Args:
|
3678
|
-
run_id: ID of the run
|
3679
|
-
before: Cursor for pagination
|
3680
|
-
after: Cursor for pagination
|
3681
|
-
limit: Maximum number of messages to return
|
3682
|
-
ascending: Sort order by creation time
|
3683
|
-
role: Filter by message role (user/assistant/system/tool)
|
3684
|
-
Returns:
|
3685
|
-
List of messages matching the filter criteria
|
3686
|
-
"""
|
3687
|
-
params = {
|
3688
|
-
"before": before,
|
3689
|
-
"after": after,
|
3690
|
-
"limit": limit,
|
3691
|
-
"ascending": ascending,
|
3692
|
-
"role": role,
|
3693
|
-
}
|
3694
|
-
|
3695
|
-
return self.server.job_manager.get_run_messages(run_id=run_id, actor=self.user, **params)
|
3696
|
-
|
3697
|
-
def get_run_usage(
|
3698
|
-
self,
|
3699
|
-
run_id: str,
|
3700
|
-
) -> List[UsageStatistics]:
|
3701
|
-
"""
|
3702
|
-
Get usage statistics associated with a job.
|
3703
|
-
|
3704
|
-
Args:
|
3705
|
-
run_id (str): ID of the run
|
3706
|
-
|
3707
|
-
Returns:
|
3708
|
-
List[UsageStatistics]: List of usage statistics associated with the run
|
3709
|
-
"""
|
3710
|
-
usage = self.server.job_manager.get_job_usage(job_id=run_id, actor=self.user)
|
3711
|
-
return [
|
3712
|
-
UsageStatistics(completion_tokens=stat.completion_tokens, prompt_tokens=stat.prompt_tokens, total_tokens=stat.total_tokens)
|
3713
|
-
for stat in usage
|
3714
|
-
]
|
3715
|
-
|
3716
|
-
def get_run(self, run_id: str) -> Run:
|
3717
|
-
"""
|
3718
|
-
Get a run by ID.
|
3719
|
-
|
3720
|
-
Args:
|
3721
|
-
run_id (str): ID of the run
|
3722
|
-
|
3723
|
-
Returns:
|
3724
|
-
run (Run): Run
|
3725
|
-
"""
|
3726
|
-
return self.server.job_manager.get_job_by_id(job_id=run_id, actor=self.user)
|
3727
|
-
|
3728
|
-
def delete_run(self, run_id: str) -> None:
|
3729
|
-
"""
|
3730
|
-
Delete a run by ID.
|
3731
|
-
|
3732
|
-
Args:
|
3733
|
-
run_id (str): ID of the run
|
3734
|
-
"""
|
3735
|
-
return self.server.job_manager.delete_job_by_id(job_id=run_id, actor=self.user)
|
3736
|
-
|
3737
|
-
def list_runs(self) -> List[Run]:
|
3738
|
-
"""
|
3739
|
-
List all runs.
|
3740
|
-
|
3741
|
-
Returns:
|
3742
|
-
runs (List[Run]): List of runs
|
3743
|
-
"""
|
3744
|
-
return self.server.job_manager.list_jobs(actor=self.user, job_type=JobType.RUN)
|
3745
|
-
|
3746
|
-
def list_active_runs(self) -> List[Run]:
|
3747
|
-
"""
|
3748
|
-
List all active runs.
|
3749
|
-
|
3750
|
-
Returns:
|
3751
|
-
runs (List[Run]): List of active runs
|
3752
|
-
"""
|
3753
|
-
return self.server.job_manager.list_jobs(actor=self.user, job_type=JobType.RUN, statuses=[JobStatus.created, JobStatus.running])
|
3754
|
-
|
3755
|
-
def get_tags(
|
3756
|
-
self,
|
3757
|
-
after: Optional[str] = None,
|
3758
|
-
limit: Optional[int] = None,
|
3759
|
-
query_text: Optional[str] = None,
|
3760
|
-
) -> List[str]:
|
3761
|
-
"""
|
3762
|
-
Get all tags.
|
3763
|
-
|
3764
|
-
Returns:
|
3765
|
-
tags (List[str]): List of tags
|
3766
|
-
"""
|
3767
|
-
return self.server.agent_manager.list_tags(actor=self.user, after=after, limit=limit, query_text=query_text)
|