Files
letta-server/letta/schemas/group.py
Ari Webb 787740e3cb feat: deprecate shared_block_ids, and add groups, blocks [LET-4430] (#5746)
* deprecate field

* add detach/attach, verify user can do them

* just stage publish api

---------

Co-authored-by: Ari Webb <ari@letta.com>
2025-11-13 15:35:34 -08:00

198 lines
8.6 KiB
Python

from enum import Enum
from typing import Annotated, List, Literal, Optional, Union
from pydantic import BaseModel, Field
from letta.schemas.enums import PrimitiveType
from letta.schemas.letta_base import LettaBase
class ManagerType(str, Enum):
round_robin = "round_robin"
supervisor = "supervisor"
dynamic = "dynamic"
sleeptime = "sleeptime"
voice_sleeptime = "voice_sleeptime"
swarm = "swarm"
class ManagerConfig(BaseModel):
manager_type: ManagerType = Field(..., description="")
class GroupBase(LettaBase):
__id_prefix__ = PrimitiveType.GROUP.value
class Group(GroupBase):
id: str = Field(..., description="The id of the group. Assigned by the database.")
manager_type: ManagerType = Field(..., description="")
agent_ids: List[str] = Field(..., description="")
description: str = Field(..., description="")
project_id: Optional[str] = Field(None, description="The associated project id.")
# Template fields
template_id: Optional[str] = Field(None, description="The id of the template.")
base_template_id: Optional[str] = Field(None, description="The base template id.")
deployment_id: Optional[str] = Field(None, description="The id of the deployment.")
shared_block_ids: List[str] = Field([], description="", deprecated=True)
# Pattern fields
manager_agent_id: Optional[str] = Field(None, description="")
termination_token: Optional[str] = Field(None, description="")
max_turns: Optional[int] = Field(None, description="")
sleeptime_agent_frequency: Optional[int] = Field(None, description="")
turns_counter: Optional[int] = Field(None, description="")
last_processed_message_id: Optional[str] = Field(None, description="")
max_message_buffer_length: Optional[int] = Field(
None,
description="The desired maximum length of messages in the context window of the convo agent. This is a best effort, and may be off slightly due to user/assistant interleaving.",
)
min_message_buffer_length: Optional[int] = Field(
None,
description="The desired minimum length of messages in the context window of the convo agent. This is a best effort, and may be off-by-one due to user/assistant interleaving.",
)
hidden: Optional[bool] = Field(
None,
description="If set to True, the group will be hidden.",
)
@property
def manager_config(self) -> ManagerConfig:
match self.manager_type:
case ManagerType.round_robin:
return RoundRobinManager(max_turns=self.max_turns)
case ManagerType.supervisor:
return SupervisorManager(manager_agent_id=self.manager_agent_id)
case ManagerType.dynamic:
return DynamicManager(
manager_agent_id=self.manager_agent_id,
termination_token=self.termination_token,
max_turns=self.max_turns,
)
case ManagerType.sleeptime:
return SleeptimeManager(
manager_agent_id=self.manager_agent_id,
sleeptime_agent_frequency=self.sleeptime_agent_frequency,
)
case ManagerType.voice_sleeptime:
return VoiceSleeptimeManager(
manager_agent_id=self.manager_agent_id,
max_message_buffer_length=self.max_message_buffer_length,
min_message_buffer_length=self.min_message_buffer_length,
)
class RoundRobinManager(ManagerConfig):
manager_type: Literal[ManagerType.round_robin] = Field(ManagerType.round_robin, description="")
max_turns: Optional[int] = Field(None, description="")
class RoundRobinManagerUpdate(ManagerConfig):
manager_type: Literal[ManagerType.round_robin] = Field(ManagerType.round_robin, description="")
max_turns: Optional[int] = Field(None, description="")
class SupervisorManager(ManagerConfig):
manager_type: Literal[ManagerType.supervisor] = Field(ManagerType.supervisor, description="")
manager_agent_id: str = Field(..., description="")
class SupervisorManagerUpdate(ManagerConfig):
manager_type: Literal[ManagerType.supervisor] = Field(ManagerType.supervisor, description="")
manager_agent_id: Optional[str] = Field(..., description="")
class DynamicManager(ManagerConfig):
manager_type: Literal[ManagerType.dynamic] = Field(ManagerType.dynamic, description="")
manager_agent_id: str = Field(..., description="")
termination_token: Optional[str] = Field("DONE!", description="")
max_turns: Optional[int] = Field(None, description="")
class DynamicManagerUpdate(ManagerConfig):
manager_type: Literal[ManagerType.dynamic] = Field(ManagerType.dynamic, description="")
manager_agent_id: Optional[str] = Field(None, description="")
termination_token: Optional[str] = Field(None, description="")
max_turns: Optional[int] = Field(None, description="")
class SleeptimeManager(ManagerConfig):
manager_type: Literal[ManagerType.sleeptime] = Field(ManagerType.sleeptime, description="")
manager_agent_id: str = Field(..., description="")
sleeptime_agent_frequency: Optional[int] = Field(None, description="")
class SleeptimeManagerUpdate(ManagerConfig):
manager_type: Literal[ManagerType.sleeptime] = Field(ManagerType.sleeptime, description="")
manager_agent_id: Optional[str] = Field(None, description="")
sleeptime_agent_frequency: Optional[int] = Field(None, description="")
class VoiceSleeptimeManager(ManagerConfig):
manager_type: Literal[ManagerType.voice_sleeptime] = Field(ManagerType.voice_sleeptime, description="")
manager_agent_id: str = Field(..., description="")
max_message_buffer_length: Optional[int] = Field(
None,
description="The desired maximum length of messages in the context window of the convo agent. This is a best effort, and may be off slightly due to user/assistant interleaving.",
)
min_message_buffer_length: Optional[int] = Field(
None,
description="The desired minimum length of messages in the context window of the convo agent. This is a best effort, and may be off-by-one due to user/assistant interleaving.",
)
class VoiceSleeptimeManagerUpdate(ManagerConfig):
manager_type: Literal[ManagerType.voice_sleeptime] = Field(ManagerType.voice_sleeptime, description="")
manager_agent_id: Optional[str] = Field(None, description="")
max_message_buffer_length: Optional[int] = Field(
None,
description="The desired maximum length of messages in the context window of the convo agent. This is a best effort, and may be off slightly due to user/assistant interleaving.",
)
min_message_buffer_length: Optional[int] = Field(
None,
description="The desired minimum length of messages in the context window of the convo agent. This is a best effort, and may be off-by-one due to user/assistant interleaving.",
)
# class SwarmGroup(ManagerConfig):
# manager_type: Literal[ManagerType.swarm] = Field(ManagerType.swarm, description="")
ManagerConfigUnion = Annotated[
Union[RoundRobinManager, SupervisorManager, DynamicManager, SleeptimeManager, VoiceSleeptimeManager],
Field(discriminator="manager_type"),
]
ManagerConfigUpdateUnion = Annotated[
Union[RoundRobinManagerUpdate, SupervisorManagerUpdate, DynamicManagerUpdate, SleeptimeManagerUpdate, VoiceSleeptimeManagerUpdate],
Field(discriminator="manager_type"),
]
class GroupCreate(BaseModel):
agent_ids: List[str] = Field(..., description="")
description: str = Field(..., description="")
manager_config: ManagerConfigUnion = Field(RoundRobinManager(), description="")
project_id: Optional[str] = Field(None, description="The associated project id.")
shared_block_ids: List[str] = Field([], description="", deprecated=True)
hidden: Optional[bool] = Field(
None,
description="If set to True, the group will be hidden.",
)
class InternalTemplateGroupCreate(GroupCreate):
"""Used for Letta Cloud"""
base_template_id: str = Field(..., description="The id of the base template.")
template_id: str = Field(..., description="The id of the template.")
deployment_id: str = Field(..., description="The id of the deployment.")
class GroupUpdate(BaseModel):
agent_ids: Optional[List[str]] = Field(None, description="")
description: Optional[str] = Field(None, description="")
manager_config: Optional[ManagerConfigUpdateUnion] = Field(None, description="")
project_id: Optional[str] = Field(None, description="The associated project id.")
shared_block_ids: Optional[List[str]] = Field(None, description="", deprecated=True)