* feat: add ID format validation to agent and user schemas Reuse existing validator types (ToolId, SourceId, BlockId, MessageId, IdentityId, UserId) from letta.validators to enforce ID format validation at the schema level. This ensures malformed IDs are rejected with a 422 validation error instead of causing 500 database errors. Changes: - CreateAgent: validate tool_ids, source_ids, folder_ids, block_ids, identity_ids - UpdateAgent: validate tool_ids, source_ids, folder_ids, block_ids, message_ids, identity_ids - UserUpdate: validate id 🤖 Generated with [Letta Code](https://letta.com) Co-Authored-By: Letta <noreply@letta.com> * chore: regenerate API spec and SDK * fix: override ID validation in AgentSchema for agent file portability AgentSchema extends CreateAgent but needs to allow arbitrary short IDs (e.g., tool-0, block-0) for portable agent files. Override the validated ID fields to use plain List[str] instead of the validated types. Also fix test_agent.af to use proper UUID-format IDs. 🤖 Generated with [Letta Code](https://letta.com) Co-Authored-By: Letta <noreply@letta.com> * chore: regenerate API spec and SDK 🤖 Generated with [Letta Code](https://letta.com) Co-Authored-By: Letta <noreply@letta.com> * fix: revert test_agent.af - short IDs are valid for agent files 🤖 Generated with [Letta Code](https://letta.com) Co-Authored-By: Letta <noreply@letta.com> * fix openapi schema --------- Co-authored-by: Letta <noreply@letta.com>
564 lines
30 KiB
Python
564 lines
30 KiB
Python
from datetime import datetime
|
|
from enum import Enum
|
|
from typing import Dict, List, Literal, Optional
|
|
|
|
from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
|
|
|
|
from letta.constants import (
|
|
CORE_MEMORY_LINE_NUMBER_WARNING,
|
|
DEFAULT_EMBEDDING_CHUNK_SIZE,
|
|
MAX_FILES_OPEN_LIMIT,
|
|
MAX_PER_FILE_VIEW_WINDOW_CHAR_LIMIT,
|
|
)
|
|
from letta.errors import AgentExportProcessingError, LettaInvalidArgumentError
|
|
from letta.schemas.block import Block, CreateBlock
|
|
from letta.schemas.embedding_config import EmbeddingConfig
|
|
from letta.schemas.enums import PrimitiveType
|
|
from letta.schemas.environment_variables import AgentEnvironmentVariable
|
|
from letta.schemas.file import FileStatus
|
|
from letta.schemas.group import Group
|
|
from letta.schemas.identity import Identity
|
|
from letta.schemas.letta_base import OrmMetadataBase
|
|
from letta.schemas.letta_message import ApprovalRequestMessage
|
|
from letta.schemas.letta_stop_reason import StopReasonType
|
|
from letta.schemas.llm_config import LLMConfig
|
|
from letta.schemas.memory import Memory
|
|
from letta.schemas.message import Message, MessageCreate
|
|
from letta.schemas.model import ModelSettingsUnion
|
|
from letta.schemas.openai.chat_completion_response import UsageStatistics
|
|
from letta.schemas.response_format import ResponseFormatUnion
|
|
from letta.schemas.source import Source
|
|
from letta.schemas.tool import Tool
|
|
from letta.schemas.tool_rule import ToolRule
|
|
from letta.services.summarizer.summarizer_config import CompactionSettings
|
|
from letta.utils import calculate_file_defaults_based_on_context_window, create_random_username
|
|
from letta.validators import BlockId, IdentityId, MessageId, SourceId, ToolId
|
|
|
|
|
|
# TODO: Remove this upon next OSS release, there's a duplicate AgentType in enums
|
|
# TODO: This is done in the interest of time to avoid needing to update the sandbox template IDs on cloud/rebuild
|
|
class AgentType(str, Enum):
|
|
"""
|
|
Enum to represent the type of agent.
|
|
"""
|
|
|
|
memgpt_agent = "memgpt_agent" # the OG set of memgpt tools
|
|
memgpt_v2_agent = "memgpt_v2_agent" # memgpt style tools, but refreshed
|
|
letta_v1_agent = "letta_v1_agent" # simplification of the memgpt loop, no heartbeats or forced tool calls
|
|
react_agent = "react_agent" # basic react agent, no memory tools
|
|
workflow_agent = "workflow_agent" # workflow with auto-clearing message buffer
|
|
split_thread_agent = "split_thread_agent"
|
|
sleeptime_agent = "sleeptime_agent"
|
|
voice_convo_agent = "voice_convo_agent"
|
|
voice_sleeptime_agent = "voice_sleeptime_agent"
|
|
|
|
|
|
# Relationship field literal type for AgentState include field to join related objects
|
|
AgentRelationships = Literal[
|
|
"agent.blocks",
|
|
"agent.identities",
|
|
"agent.managed_group",
|
|
"agent.pending_approval",
|
|
"agent.secrets",
|
|
"agent.sources",
|
|
"agent.tags",
|
|
"agent.tools",
|
|
]
|
|
|
|
|
|
class AgentState(OrmMetadataBase, validate_assignment=True):
|
|
"""Representation of an agent's state. This is the state of the agent at a given time, and is persisted in the DB backend. The state has all the information needed to recreate a persisted agent."""
|
|
|
|
__id_prefix__ = PrimitiveType.AGENT.value
|
|
|
|
# NOTE: this is what is returned to the client and also what is used to initialize `Agent`
|
|
id: str = Field(..., description="The id of the agent. Assigned by the database.")
|
|
name: str = Field(..., description="The name of the agent.")
|
|
# tool rules
|
|
tool_rules: Optional[List[ToolRule]] = Field(default=None, description="The list of tool rules.")
|
|
# in-context memory
|
|
message_ids: Optional[List[str]] = Field(default=None, description="The ids of the messages in the agent's in-context memory.")
|
|
|
|
# system prompt
|
|
system: str = Field(..., description="The system prompt used by the agent.")
|
|
|
|
# agent configuration
|
|
agent_type: AgentType = Field(..., description="The type of agent.")
|
|
|
|
# model information
|
|
llm_config: LLMConfig = Field(
|
|
..., description="Deprecated: Use `model` field instead. The LLM configuration used by the agent.", deprecated=True
|
|
)
|
|
embedding_config: Optional[EmbeddingConfig] = Field(
|
|
None, description="Deprecated: Use `embedding` field instead. The embedding configuration used by the agent.", deprecated=True
|
|
)
|
|
model: Optional[str] = Field(None, description="The model handle used by the agent (format: provider/model-name).")
|
|
embedding: Optional[str] = Field(None, description="The embedding model handle used by the agent (format: provider/model-name).")
|
|
model_settings: Optional[ModelSettingsUnion] = Field(None, description="The model settings used by the agent.")
|
|
compaction_settings: Optional[CompactionSettings] = Field(
|
|
None, description="The compaction settings configuration used for compaction."
|
|
)
|
|
|
|
response_format: Optional[ResponseFormatUnion] = Field(
|
|
None,
|
|
description="The response format used by the agent",
|
|
)
|
|
|
|
# This is an object representing the in-process state of a running `Agent`
|
|
# Field in this object can be theoretically edited by tools, and will be persisted by the ORM
|
|
description: Optional[str] = Field(None, description="The description of the agent.")
|
|
metadata: Optional[Dict] = Field(None, description="The metadata of the agent.")
|
|
|
|
memory: Memory = Field(..., description="Deprecated: Use `blocks` field instead. The in-context memory of the agent.", deprecated=True)
|
|
blocks: List[Block] = Field(..., description="The memory blocks used by the agent.")
|
|
tools: List[Tool] = Field(..., description="The tools used by the agent.")
|
|
sources: List[Source] = Field(
|
|
..., description="Deprecated: Use `folders` field instead. The sources used by the agent.", deprecated=True
|
|
)
|
|
tags: List[str] = Field(..., description="The tags associated with the agent.")
|
|
tool_exec_environment_variables: List[AgentEnvironmentVariable] = Field(
|
|
default_factory=list,
|
|
description="Deprecated: use `secrets` field instead.",
|
|
deprecated=True,
|
|
)
|
|
secrets: List[AgentEnvironmentVariable] = Field(
|
|
default_factory=list, description="The environment variables for tool execution specific to this agent."
|
|
)
|
|
project_id: Optional[str] = Field(None, description="The id of the project the agent belongs to.")
|
|
template_id: Optional[str] = Field(None, description="The id of the template the agent belongs to.")
|
|
base_template_id: Optional[str] = Field(None, description="The base template id of the agent.")
|
|
deployment_id: Optional[str] = Field(None, description="The id of the deployment.")
|
|
entity_id: Optional[str] = Field(None, description="The id of the entity within the template.")
|
|
identity_ids: List[str] = Field(
|
|
[], description="Deprecated: Use `identities` field instead. The ids of the identities associated with this agent.", deprecated=True
|
|
)
|
|
identities: List[Identity] = Field([], description="The identities associated with this agent.")
|
|
pending_approval: Optional[ApprovalRequestMessage] = Field(
|
|
None, description="The latest approval request message pending for this agent, if any."
|
|
)
|
|
|
|
# An advanced configuration that makes it so this agent does not remember any previous messages
|
|
message_buffer_autoclear: bool = Field(
|
|
False,
|
|
description="If set to True, the agent will not remember previous messages (though the agent will still retain state via core memory blocks and archival/recall memory). Not recommended unless you have an advanced use case.",
|
|
)
|
|
enable_sleeptime: Optional[bool] = Field(
|
|
None,
|
|
description="If set to True, memory management will move to a background agent thread.",
|
|
)
|
|
|
|
multi_agent_group: Optional[Group] = Field(
|
|
None, description="Deprecated: Use `managed_group` field instead. The multi-agent group that this agent manages.", deprecated=True
|
|
)
|
|
managed_group: Optional[Group] = Field(None, description="The multi-agent group that this agent manages")
|
|
# Run metrics
|
|
last_run_completion: Optional[datetime] = Field(None, description="The timestamp when the agent last completed a run.")
|
|
last_run_duration_ms: Optional[int] = Field(None, description="The duration in milliseconds of the agent's last run.")
|
|
last_stop_reason: Optional[StopReasonType] = Field(None, description="The stop reason from the agent's last run.")
|
|
|
|
# timezone
|
|
timezone: Optional[str] = Field(None, description="The timezone of the agent (IANA format).")
|
|
|
|
# file related controls
|
|
max_files_open: Optional[int] = Field(
|
|
None,
|
|
description="Maximum number of files that can be open at once for this agent. Setting this too high may exceed the context window, which will break the agent.",
|
|
)
|
|
per_file_view_window_char_limit: Optional[int] = Field(
|
|
None,
|
|
description="The per-file view window character limit for this agent. Setting this too high may exceed the context window, which will break the agent.",
|
|
)
|
|
|
|
# indexing controls
|
|
hidden: Optional[bool] = Field(
|
|
None,
|
|
description="If set to True, the agent will be hidden.",
|
|
)
|
|
|
|
def get_agent_env_vars_as_dict(self) -> Dict[str, str]:
|
|
# Get environment variables for this agent (value is already decrypted via from_orm_async)
|
|
per_agent_env_vars = {}
|
|
for agent_env_var_obj in self.secrets:
|
|
# Use the pre-decrypted value field (populated by from_orm_async)
|
|
per_agent_env_vars[agent_env_var_obj.key] = agent_env_var_obj.value or ""
|
|
return per_agent_env_vars
|
|
|
|
@model_validator(mode="after")
|
|
def set_file_defaults_based_on_context_window(self) -> "AgentState":
|
|
"""Set reasonable defaults for file-related fields based on the model's context window size."""
|
|
# Only set defaults if not explicitly provided
|
|
if self.max_files_open is not None and self.per_file_view_window_char_limit is not None:
|
|
return self
|
|
|
|
# Get context window size from llm_config
|
|
context_window = self.llm_config.context_window if self.llm_config and self.llm_config.context_window else None
|
|
|
|
# Calculate defaults using the helper function
|
|
default_max_files, default_char_limit = calculate_file_defaults_based_on_context_window(context_window)
|
|
|
|
# Apply defaults only if not set
|
|
if self.max_files_open is None:
|
|
self.max_files_open = default_max_files
|
|
if self.per_file_view_window_char_limit is None:
|
|
self.per_file_view_window_char_limit = default_char_limit
|
|
|
|
return self
|
|
|
|
|
|
class CreateAgent(BaseModel, validate_assignment=True): #
|
|
# all optional as server can generate defaults
|
|
name: str = Field(default_factory=lambda: create_random_username(), description="The name of the agent.")
|
|
|
|
# memory creation
|
|
memory_blocks: Optional[List[CreateBlock]] = Field(
|
|
None,
|
|
description="The blocks to create in the agent's in-context memory.",
|
|
)
|
|
# TODO: This is a legacy field and should be removed ASAP to force `tool_ids` usage
|
|
tools: Optional[List[str]] = Field(None, description="The tools used by the agent.")
|
|
tool_ids: Optional[List[ToolId]] = Field(None, description="The ids of the tools used by the agent.")
|
|
source_ids: Optional[List[SourceId]] = Field(
|
|
None, description="Deprecated: Use `folder_ids` field instead. The ids of the sources used by the agent.", deprecated=True
|
|
)
|
|
folder_ids: Optional[List[SourceId]] = Field(None, description="The ids of the folders used by the agent.")
|
|
block_ids: Optional[List[BlockId]] = Field(None, description="The ids of the blocks used by the agent.")
|
|
tool_rules: Optional[List[ToolRule]] = Field(None, description="The tool rules governing the agent.")
|
|
tags: Optional[List[str]] = Field(None, description="The tags associated with the agent.")
|
|
system: Optional[str] = Field(None, description="The system prompt used by the agent.")
|
|
agent_type: AgentType = Field(default_factory=lambda: AgentType.letta_v1_agent, description="The type of agent.")
|
|
# Note: if this is None, then we'll populate with the standard "more human than human" initial message sequence
|
|
# If the client wants to make this empty, then the client can set the arg to an empty list
|
|
initial_message_sequence: Optional[List[MessageCreate]] = Field(
|
|
None, description="The initial set of messages to put in the agent's in-context memory."
|
|
)
|
|
include_base_tools: bool = Field(True, description="If true, attaches the Letta core tools (e.g. core_memory related functions).")
|
|
include_multi_agent_tools: bool = Field(
|
|
False, description="If true, attaches the Letta multi-agent tools (e.g. sending a message to another agent)."
|
|
)
|
|
include_base_tool_rules: Optional[bool] = Field(
|
|
None, description="If true, attaches the Letta base tool rules (e.g. deny all tools not explicitly allowed)."
|
|
)
|
|
include_default_source: bool = Field( # TODO: get rid of this
|
|
False, description="If true, automatically creates and attaches a default data source for this agent.", deprecated=True
|
|
)
|
|
description: Optional[str] = Field(None, description="The description of the agent.")
|
|
metadata: Optional[Dict] = Field(None, description="The metadata of the agent.")
|
|
|
|
# model configuration
|
|
llm_config: Optional[LLMConfig] = Field(
|
|
None, description="Deprecated: Use `model` field instead. The LLM configuration used by the agent.", deprecated=True
|
|
)
|
|
embedding_config: Optional[EmbeddingConfig] = Field(
|
|
None, description="Deprecated: Use `embedding` field instead. The embedding configuration used by the agent.", deprecated=True
|
|
)
|
|
model: Optional[str] = Field( # TODO: make this required (breaking change)
|
|
None,
|
|
description="The model handle for the agent to use (format: provider/model-name).",
|
|
)
|
|
embedding: Optional[str] = Field(None, description="The embedding model handle used by the agent (format: provider/model-name).")
|
|
model_settings: Optional[ModelSettingsUnion] = Field(None, description="The model settings for the agent.")
|
|
compaction_settings: Optional[CompactionSettings] = Field(
|
|
None, description="The compaction settings configuration used for compaction."
|
|
)
|
|
|
|
context_window_limit: Optional[int] = Field(None, description="The context window limit used by the agent.")
|
|
embedding_chunk_size: Optional[int] = Field(
|
|
DEFAULT_EMBEDDING_CHUNK_SIZE, description="Deprecated: No longer used. The embedding chunk size used by the agent.", deprecated=True
|
|
)
|
|
max_tokens: Optional[int] = Field(
|
|
None,
|
|
description="Deprecated: Use `model` field to configure max output tokens instead. The maximum number of tokens to generate, including reasoning step.",
|
|
deprecated=True,
|
|
)
|
|
max_reasoning_tokens: Optional[int] = Field(
|
|
None,
|
|
description="Deprecated: Use `model` field to configure reasoning tokens instead. The maximum number of tokens to generate for reasoning step.",
|
|
deprecated=True,
|
|
)
|
|
enable_reasoner: Optional[bool] = Field(
|
|
True,
|
|
description="Deprecated: Use `model` field to configure reasoning instead. Whether to enable internal extended thinking step for a reasoner model.",
|
|
deprecated=True,
|
|
)
|
|
reasoning: Optional[bool] = Field(
|
|
None,
|
|
description="Deprecated: Use `model` field to configure reasoning instead. Whether to enable reasoning for this agent.",
|
|
deprecated=True,
|
|
)
|
|
from_template: Optional[str] = Field(
|
|
None, description="Deprecated: please use the 'create agents from a template' endpoint instead.", deprecated=True
|
|
)
|
|
template: bool = Field(False, description="Deprecated: No longer used.", deprecated=True)
|
|
project: Optional[str] = Field(
|
|
None,
|
|
deprecated=True,
|
|
description="Deprecated: Project should now be passed via the X-Project header instead of in the request body. If using the SDK, this can be done via the x_project parameter.",
|
|
)
|
|
tool_exec_environment_variables: Optional[Dict[str, str]] = Field(
|
|
None, description="Deprecated: Use `secrets` field instead. Environment variables for tool execution.", deprecated=True
|
|
)
|
|
secrets: Optional[Dict[str, str]] = Field(None, description="The environment variables for tool execution specific to this agent.")
|
|
memory_variables: Optional[Dict[str, str]] = Field(
|
|
None,
|
|
description="Deprecated: Only relevant for creating agents from a template. Use the 'create agents from a template' endpoint instead.",
|
|
deprecated=True,
|
|
)
|
|
project_id: Optional[str] = Field(
|
|
None, description="Deprecated: No longer used. The id of the project the agent belongs to.", deprecated=True
|
|
)
|
|
template_id: Optional[str] = Field(
|
|
None, description="Deprecated: No longer used. The id of the template the agent belongs to.", deprecated=True
|
|
)
|
|
base_template_id: Optional[str] = Field(
|
|
None, description="Deprecated: No longer used. The base template id of the agent.", deprecated=True
|
|
)
|
|
identity_ids: Optional[List[IdentityId]] = Field(None, description="The ids of the identities associated with this agent.")
|
|
message_buffer_autoclear: bool = Field(
|
|
False,
|
|
description="If set to True, the agent will not remember previous messages (though the agent will still retain state via core memory blocks and archival/recall memory). Not recommended unless you have an advanced use case.",
|
|
)
|
|
enable_sleeptime: Optional[bool] = Field(None, description="If set to True, memory management will move to a background agent thread.")
|
|
response_format: Optional[ResponseFormatUnion] = Field(
|
|
None,
|
|
description="Deprecated: Use `model_settings` field to configure response format instead. The response format for the agent.",
|
|
deprecated=True,
|
|
)
|
|
timezone: Optional[str] = Field(None, description="The timezone of the agent (IANA format).")
|
|
max_files_open: Optional[int] = Field(
|
|
None,
|
|
description="Maximum number of files that can be open at once for this agent. Setting this too high may exceed the context window, which will break the agent.",
|
|
)
|
|
per_file_view_window_char_limit: Optional[int] = Field(
|
|
None,
|
|
description="The per-file view window character limit for this agent. Setting this too high may exceed the context window, which will break the agent.",
|
|
)
|
|
hidden: Optional[bool] = Field(
|
|
None,
|
|
description="Deprecated: No longer used. If set to True, the agent will be hidden.",
|
|
deprecated=True,
|
|
)
|
|
parallel_tool_calls: Optional[bool] = Field(
|
|
None,
|
|
description="Deprecated: Use `model_settings` to configure parallel tool calls instead. If set to True, enables parallel tool calling.",
|
|
deprecated=True,
|
|
)
|
|
|
|
@field_validator("name")
|
|
@classmethod
|
|
def validate_name(cls, name: str) -> str:
|
|
"""Validate the requested new agent name (prevent bad inputs)"""
|
|
|
|
import re
|
|
|
|
if not name:
|
|
# don't check if not provided
|
|
return name
|
|
|
|
# Regex for allowed characters (Unicode letters, digits, spaces, hyphens, underscores, apostrophes)
|
|
# \w in Python 3 with re.UNICODE matches Unicode letters, digits, and underscores
|
|
# We explicitly allow: letters (any language), digits, spaces, hyphens, underscores, apostrophes
|
|
# We block filesystem-unsafe characters: / \ : * ? " < > |
|
|
if not re.match(r"^[\w '\-]+$", name, re.UNICODE):
|
|
raise AgentExportProcessingError(
|
|
f"Agent name '{name}' contains invalid characters. Only letters (any language), digits, spaces, "
|
|
f"hyphens, underscores, and apostrophes are allowed. Please avoid filesystem-unsafe characters "
|
|
f'like: / \\ : * ? " < > |'
|
|
)
|
|
|
|
# Further checks can be added here...
|
|
# TODO
|
|
|
|
return name
|
|
|
|
@field_validator("model")
|
|
@classmethod
|
|
def validate_model(cls, model: Optional[str]) -> Optional[str]:
|
|
if not model:
|
|
return model
|
|
|
|
if "/" not in model:
|
|
raise LettaInvalidArgumentError("The model handle should be in the format provider/model-name", argument_name="model")
|
|
|
|
provider_name, model_name = model.split("/", 1)
|
|
if not provider_name or not model_name:
|
|
raise LettaInvalidArgumentError("The model handle should be in the format provider/model-name", argument_name="model")
|
|
|
|
return model
|
|
|
|
@field_validator("embedding")
|
|
@classmethod
|
|
def validate_embedding(cls, embedding: Optional[str]) -> Optional[str]:
|
|
if not embedding:
|
|
return embedding
|
|
|
|
if "/" not in embedding:
|
|
raise ValueError("The embedding handle should be in the format provider/model-name")
|
|
|
|
provider_name, embedding_name = embedding.split("/", 1)
|
|
if not provider_name or not embedding_name:
|
|
raise ValueError("The embedding handle should be in the format provider/model-name")
|
|
|
|
return embedding
|
|
|
|
@field_validator("max_files_open")
|
|
@classmethod
|
|
def validate_max_files_open(cls, value: Optional[int]) -> Optional[int]:
|
|
"""Validate max_files_open is within acceptable range."""
|
|
if value is not None and value > MAX_FILES_OPEN_LIMIT:
|
|
raise LettaInvalidArgumentError(
|
|
f"max_files_open cannot exceed {MAX_FILES_OPEN_LIMIT}. Got: {value}",
|
|
argument_name="max_files_open",
|
|
)
|
|
return value
|
|
|
|
@field_validator("per_file_view_window_char_limit")
|
|
@classmethod
|
|
def validate_per_file_view_window_char_limit(cls, value: Optional[int]) -> Optional[int]:
|
|
"""Validate per_file_view_window_char_limit is within int32 range for database compatibility."""
|
|
if value is not None and value > MAX_PER_FILE_VIEW_WINDOW_CHAR_LIMIT:
|
|
raise LettaInvalidArgumentError(
|
|
f"per_file_view_window_char_limit cannot exceed {MAX_PER_FILE_VIEW_WINDOW_CHAR_LIMIT}. Got: {value}",
|
|
argument_name="per_file_view_window_char_limit",
|
|
)
|
|
return value
|
|
|
|
@model_validator(mode="after")
|
|
def validate_sleeptime_for_agent_type(self) -> "CreateAgent":
|
|
"""Validate that enable_sleeptime is True when agent_type is a specific value"""
|
|
AGENT_TYPES_REQUIRING_SLEEPTIME = {AgentType.voice_convo_agent}
|
|
|
|
if self.agent_type in AGENT_TYPES_REQUIRING_SLEEPTIME:
|
|
if not self.enable_sleeptime:
|
|
raise ValueError(f"Agent type {self.agent_type} requires enable_sleeptime to be True")
|
|
|
|
return self
|
|
|
|
|
|
class InternalTemplateAgentCreate(CreateAgent):
|
|
"""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.")
|
|
entity_id: str = Field(..., description="The id of the entity within the template.")
|
|
|
|
|
|
class UpdateAgent(BaseModel):
|
|
name: Optional[str] = Field(None, description="The name of the agent.")
|
|
tool_ids: Optional[List[ToolId]] = Field(None, description="The ids of the tools used by the agent.")
|
|
source_ids: Optional[List[SourceId]] = Field(
|
|
None, description="Deprecated: Use `folder_ids` field instead. The ids of the sources used by the agent.", deprecated=True
|
|
)
|
|
folder_ids: Optional[List[SourceId]] = Field(None, description="The ids of the folders used by the agent.")
|
|
block_ids: Optional[List[BlockId]] = Field(None, description="The ids of the blocks used by the agent.")
|
|
tags: Optional[List[str]] = Field(None, description="The tags associated with the agent.")
|
|
system: Optional[str] = Field(None, description="The system prompt used by the agent.")
|
|
tool_rules: Optional[List[ToolRule]] = Field(None, description="The tool rules governing the agent.")
|
|
message_ids: Optional[List[MessageId]] = Field(None, description="The ids of the messages in the agent's in-context memory.")
|
|
description: Optional[str] = Field(None, description="The description of the agent.")
|
|
metadata: Optional[Dict] = Field(None, description="The metadata of the agent.")
|
|
tool_exec_environment_variables: Optional[Dict[str, str]] = Field(None, description="Deprecated: use `secrets` field instead")
|
|
secrets: Optional[Dict[str, str]] = Field(None, description="The environment variables for tool execution specific to this agent.")
|
|
project_id: Optional[str] = Field(None, description="The id of the project the agent belongs to.")
|
|
template_id: Optional[str] = Field(None, description="The id of the template the agent belongs to.")
|
|
base_template_id: Optional[str] = Field(None, description="The base template id of the agent.")
|
|
identity_ids: Optional[List[IdentityId]] = Field(None, description="The ids of the identities associated with this agent.")
|
|
message_buffer_autoclear: Optional[bool] = Field(
|
|
None,
|
|
description="If set to True, the agent will not remember previous messages (though the agent will still retain state via core memory blocks and archival/recall memory). Not recommended unless you have an advanced use case.",
|
|
)
|
|
|
|
# model configuration
|
|
model: Optional[str] = Field(
|
|
None,
|
|
description="The model handle used by the agent (format: provider/model-name).",
|
|
)
|
|
embedding: Optional[str] = Field(None, description="The embedding model handle used by the agent (format: provider/model-name).")
|
|
model_settings: Optional[ModelSettingsUnion] = Field(None, description="The model settings for the agent.")
|
|
compaction_settings: Optional[CompactionSettings] = Field(
|
|
None, description="The compaction settings configuration used for compaction."
|
|
)
|
|
|
|
context_window_limit: Optional[int] = Field(None, description="The context window limit used by the agent.")
|
|
reasoning: Optional[bool] = Field(
|
|
None,
|
|
description="Deprecated: Use `model` field to configure reasoning instead. Whether to enable reasoning for this agent.",
|
|
deprecated=True,
|
|
)
|
|
llm_config: Optional[LLMConfig] = Field(
|
|
None, description="Deprecated: Use `model` field instead. The LLM configuration used by the agent.", deprecated=True
|
|
)
|
|
embedding_config: Optional[EmbeddingConfig] = Field(None, description="The embedding configuration used by the agent.")
|
|
parallel_tool_calls: Optional[bool] = Field(
|
|
None,
|
|
description="Deprecated: Use `model_settings` to configure parallel tool calls instead. If set to True, enables parallel tool calling.",
|
|
deprecated=True,
|
|
)
|
|
response_format: Optional[ResponseFormatUnion] = Field(
|
|
None,
|
|
description="Deprecated: Use `model_settings` field to configure response format instead. The response format for the agent.",
|
|
deprecated=True,
|
|
)
|
|
max_tokens: Optional[int] = Field(
|
|
None,
|
|
description="Deprecated: Use `model` field to configure max output tokens instead. The maximum number of tokens to generate, including reasoning step.",
|
|
deprecated=True,
|
|
)
|
|
|
|
enable_sleeptime: Optional[bool] = Field(None, description="If set to True, memory management will move to a background agent thread.")
|
|
last_run_completion: Optional[datetime] = Field(None, description="The timestamp when the agent last completed a run.")
|
|
last_run_duration_ms: Optional[int] = Field(None, description="The duration in milliseconds of the agent's last run.")
|
|
last_stop_reason: Optional[StopReasonType] = Field(None, description="The stop reason from the agent's last run.")
|
|
timezone: Optional[str] = Field(None, description="The timezone of the agent (IANA format).")
|
|
max_files_open: Optional[int] = Field(
|
|
None,
|
|
description="Maximum number of files that can be open at once for this agent. Setting this too high may exceed the context window, which will break the agent.",
|
|
)
|
|
per_file_view_window_char_limit: Optional[int] = Field(
|
|
None,
|
|
description="The per-file view window character limit for this agent. Setting this too high may exceed the context window, which will break the agent.",
|
|
)
|
|
hidden: Optional[bool] = Field(
|
|
None,
|
|
description="If set to True, the agent will be hidden.",
|
|
)
|
|
|
|
model_config = ConfigDict(extra="ignore") # Ignores extra fields
|
|
|
|
@field_validator("max_files_open")
|
|
@classmethod
|
|
def validate_max_files_open(cls, value: Optional[int]) -> Optional[int]:
|
|
"""Validate max_files_open is within acceptable range."""
|
|
if value is not None and value > MAX_FILES_OPEN_LIMIT:
|
|
raise LettaInvalidArgumentError(
|
|
f"max_files_open cannot exceed {MAX_FILES_OPEN_LIMIT}. Got: {value}",
|
|
argument_name="max_files_open",
|
|
)
|
|
return value
|
|
|
|
@field_validator("per_file_view_window_char_limit")
|
|
@classmethod
|
|
def validate_per_file_view_window_char_limit(cls, value: Optional[int]) -> Optional[int]:
|
|
"""Validate per_file_view_window_char_limit is within int32 range for database compatibility."""
|
|
if value is not None and value > MAX_PER_FILE_VIEW_WINDOW_CHAR_LIMIT:
|
|
raise LettaInvalidArgumentError(
|
|
f"per_file_view_window_char_limit cannot exceed {MAX_PER_FILE_VIEW_WINDOW_CHAR_LIMIT}. Got: {value}",
|
|
argument_name="per_file_view_window_char_limit",
|
|
)
|
|
return value
|
|
|
|
|
|
class AgentStepResponse(BaseModel):
|
|
messages: List[Message] = Field(..., description="The messages generated during the agent's step.")
|
|
heartbeat_request: bool = Field(..., description="Whether the agent requested a heartbeat (i.e. follow-up execution).")
|
|
function_failed: bool = Field(..., description="Whether the agent step ended because a function call failed.")
|
|
in_context_memory_warning: bool = Field(
|
|
..., description="Whether the agent step ended because the in-context memory is near its limit."
|
|
)
|
|
usage: UsageStatistics = Field(..., description="Usage statistics of the LLM call during the agent's step.")
|
|
|
|
|
|
def get_prompt_template_for_agent_type(agent_type: Optional[AgentType] = None):
|
|
"""Deprecated. Templates are not used anymore; fast renderer handles formatting."""
|
|
return ""
|