From cfeed463a9acb3633bfb2d1c690dbc4f67c53259 Mon Sep 17 00:00:00 2001 From: Sarah Wooders Date: Thu, 30 Oct 2025 19:00:16 -0700 Subject: [PATCH] Revert "feat: provider-specific model configuration " (#5873) Revert "feat: provider-specific model configuration (#5774)" This reverts commit 34a334949a3ef72cd49ff0ca3da9e85d16daa57c. --- fern/openapi.json | 1403 ++++---------------------- letta/orm/agent.py | 3 - letta/schemas/agent.py | 148 +-- letta/schemas/llm_config.py | 97 +- letta/schemas/model.py | 224 ---- letta/server/server.py | 17 +- tests/managers/test_agent_manager.py | 3 - tests/sdk/conftest.py | 8 +- tests/test_client.py | 31 + 9 files changed, 261 insertions(+), 1673 deletions(-) delete mode 100644 letta/schemas/model.py diff --git a/fern/openapi.json b/fern/openapi.json index 6cbe4c3c..6f62b8e2 100644 --- a/fern/openapi.json +++ b/fern/openapi.json @@ -18571,82 +18571,11 @@ }, "llm_config": { "$ref": "#/components/schemas/LLMConfig", - "description": "Deprecated: Use `model` field instead. The LLM configuration used by the agent.", - "deprecated": true + "description": "The LLM configuration used by the agent." }, "embedding_config": { "$ref": "#/components/schemas/EmbeddingConfig", - "description": "Deprecated: Use `embedding` field instead. The embedding configuration used by the agent.", - "deprecated": true - }, - "model": { - "anyOf": [ - { - "oneOf": [ - { - "$ref": "#/components/schemas/OpenAIModel" - }, - { - "$ref": "#/components/schemas/AnthropicModel" - }, - { - "$ref": "#/components/schemas/GoogleAIModel" - }, - { - "$ref": "#/components/schemas/GoogleVertexModel" - }, - { - "$ref": "#/components/schemas/AzureModel" - }, - { - "$ref": "#/components/schemas/XAIModel" - }, - { - "$ref": "#/components/schemas/GroqModel" - }, - { - "$ref": "#/components/schemas/DeepseekModel" - }, - { - "$ref": "#/components/schemas/TogetherModel" - }, - { - "$ref": "#/components/schemas/BedrockModel" - } - ], - "discriminator": { - "propertyName": "provider", - "mapping": { - "anthropic": "#/components/schemas/AnthropicModel", - "azure": "#/components/schemas/AzureModel", - "bedrock": "#/components/schemas/BedrockModel", - "deepseek": "#/components/schemas/DeepseekModel", - "google_ai": "#/components/schemas/GoogleAIModel", - "google_vertex": "#/components/schemas/GoogleVertexModel", - "groq": "#/components/schemas/GroqModel", - "openai": "#/components/schemas/OpenAIModel", - "together": "#/components/schemas/TogetherModel", - "xai": "#/components/schemas/XAIModel" - } - } - }, - { - "type": "null" - } - ], - "title": "Model", - "description": "The model used by the agent." - }, - "embedding": { - "anyOf": [ - { - "$ref": "#/components/schemas/EmbeddingModelSettings" - }, - { - "type": "null" - } - ], - "description": "The embedding model used by the agent." + "description": "The embedding configuration used by the agent." }, "response_format": { "anyOf": [ @@ -18676,7 +18605,7 @@ } ], "title": "Response Format", - "description": "The response format used by the agent" + "description": "The response format used by the agent when returning from `send_message`." }, "description": { "anyOf": [ @@ -18705,7 +18634,7 @@ }, "memory": { "$ref": "#/components/schemas/Memory", - "description": "Deprecated: Use `blocks` field instead. The in-context memory of the agent.", + "description": "The in-context memory of the agent.", "deprecated": true }, "blocks": { @@ -18823,7 +18752,7 @@ }, "type": "array", "title": "Identity Ids", - "description": "Deprecated: Use `identities` field instead. The ids of the identities associated with this agent.", + "description": "The ids of the identities associated with this agent.", "default": [], "deprecated": true }, @@ -18863,7 +18792,7 @@ "type": "null" } ], - "description": "Deprecated: Use `managed_group` field instead. The multi-agent group that this agent manages.", + "description": "The multi-agent group that this agent manages", "deprecated": true }, "managed_group": { @@ -19025,77 +18954,6 @@ "required": ["end_index", "start_index", "title", "url"], "title": "AnnotationURLCitation" }, - "AnthropicModel": { - "properties": { - "model": { - "type": "string", - "title": "Model", - "description": "The name of the model." - }, - "max_output_tokens": { - "type": "integer", - "title": "Max Output Tokens", - "description": "The maximum number of tokens the model can generate.", - "default": 4096 - }, - "provider": { - "type": "string", - "const": "anthropic", - "title": "Provider", - "description": "The provider of the model.", - "default": "anthropic" - }, - "temperature": { - "type": "number", - "title": "Temperature", - "description": "The temperature of the model.", - "default": 1 - }, - "thinking": { - "$ref": "#/components/schemas/AnthropicThinking", - "description": "The thinking configuration for the model.", - "default": { - "type": "enabled", - "budget_tokens": 1024 - } - }, - "verbosity": { - "anyOf": [ - { - "type": "string", - "enum": ["low", "medium", "high"] - }, - { - "type": "null" - } - ], - "title": "Verbosity", - "description": "Soft control for how verbose model output should be, used for GPT-5 models." - } - }, - "type": "object", - "required": ["model"], - "title": "AnthropicModel" - }, - "AnthropicThinking": { - "properties": { - "type": { - "type": "string", - "enum": ["enabled", "disabled"], - "title": "Type", - "description": "The type of thinking to use.", - "default": "enabled" - }, - "budget_tokens": { - "type": "integer", - "title": "Budget Tokens", - "description": "The maximum number of tokens the model can use for extended thinking.", - "default": 1024 - } - }, - "type": "object", - "title": "AnthropicThinking" - }, "ApprovalCreate": { "properties": { "type": { @@ -19882,68 +19740,6 @@ "required": ["uuid"], "title": "AuthResponse" }, - "AzureModel": { - "properties": { - "model": { - "type": "string", - "title": "Model", - "description": "The name of the model." - }, - "max_output_tokens": { - "type": "integer", - "title": "Max Output Tokens", - "description": "The maximum number of tokens the model can generate.", - "default": 4096 - }, - "provider": { - "type": "string", - "const": "azure", - "title": "Provider", - "description": "The provider of the model.", - "default": "azure" - }, - "temperature": { - "type": "number", - "title": "Temperature", - "description": "The temperature of the model.", - "default": 0.7 - }, - "response_format": { - "anyOf": [ - { - "oneOf": [ - { - "$ref": "#/components/schemas/TextResponseFormat" - }, - { - "$ref": "#/components/schemas/JsonSchemaResponseFormat" - }, - { - "$ref": "#/components/schemas/JsonObjectResponseFormat" - } - ], - "discriminator": { - "propertyName": "type", - "mapping": { - "json_object": "#/components/schemas/JsonObjectResponseFormat", - "json_schema": "#/components/schemas/JsonSchemaResponseFormat", - "text": "#/components/schemas/TextResponseFormat" - } - } - }, - { - "type": "null" - } - ], - "title": "Response Format", - "description": "The response format for the model." - } - }, - "type": "object", - "required": ["model"], - "title": "AzureModel", - "description": "Azure OpenAI model configuration (OpenAI-compatible)." - }, "Base64Image": { "properties": { "type": { @@ -20195,68 +19991,6 @@ "type": "object", "title": "BatchJob" }, - "BedrockModel": { - "properties": { - "model": { - "type": "string", - "title": "Model", - "description": "The name of the model." - }, - "max_output_tokens": { - "type": "integer", - "title": "Max Output Tokens", - "description": "The maximum number of tokens the model can generate.", - "default": 4096 - }, - "provider": { - "type": "string", - "const": "bedrock", - "title": "Provider", - "description": "The provider of the model.", - "default": "bedrock" - }, - "temperature": { - "type": "number", - "title": "Temperature", - "description": "The temperature of the model.", - "default": 0.7 - }, - "response_format": { - "anyOf": [ - { - "oneOf": [ - { - "$ref": "#/components/schemas/TextResponseFormat" - }, - { - "$ref": "#/components/schemas/JsonSchemaResponseFormat" - }, - { - "$ref": "#/components/schemas/JsonObjectResponseFormat" - } - ], - "discriminator": { - "propertyName": "type", - "mapping": { - "json_object": "#/components/schemas/JsonObjectResponseFormat", - "json_schema": "#/components/schemas/JsonSchemaResponseFormat", - "text": "#/components/schemas/TextResponseFormat" - } - } - }, - { - "type": "null" - } - ], - "title": "Response Format", - "description": "The response format for the model." - } - }, - "type": "object", - "required": ["model"], - "title": "BedrockModel", - "description": "AWS Bedrock model configuration." - }, "Block": { "properties": { "value": { @@ -22710,6 +22444,28 @@ "$ref": "#/components/schemas/AgentType", "description": "The type of agent." }, + "llm_config": { + "anyOf": [ + { + "$ref": "#/components/schemas/LLMConfig" + }, + { + "type": "null" + } + ], + "description": "The LLM configuration used by the agent." + }, + "embedding_config": { + "anyOf": [ + { + "$ref": "#/components/schemas/EmbeddingConfig" + }, + { + "type": "null" + } + ], + "description": "The embedding configuration used by the agent." + }, "initial_message_sequence": { "anyOf": [ { @@ -22753,8 +22509,7 @@ "type": "boolean", "title": "Include Default Source", "description": "If true, automatically creates and attaches a default data source for this agent.", - "default": false, - "deprecated": true + "default": false }, "description": { "anyOf": [ @@ -22781,99 +22536,23 @@ "title": "Metadata", "description": "The metadata of the agent." }, - "llm_config": { - "anyOf": [ - { - "$ref": "#/components/schemas/LLMConfig" - }, - { - "type": "null" - } - ], - "description": "Deprecated: Use `model` field instead. The LLM configuration used by the agent.", - "deprecated": true - }, - "embedding_config": { - "anyOf": [ - { - "$ref": "#/components/schemas/EmbeddingConfig" - }, - { - "type": "null" - } - ], - "description": "Deprecated: Use `embedding` field instead. The embedding configuration used by the agent.", - "deprecated": true - }, "model": { "anyOf": [ { "type": "string" }, - { - "oneOf": [ - { - "$ref": "#/components/schemas/OpenAIModel" - }, - { - "$ref": "#/components/schemas/AnthropicModel" - }, - { - "$ref": "#/components/schemas/GoogleAIModel" - }, - { - "$ref": "#/components/schemas/GoogleVertexModel" - }, - { - "$ref": "#/components/schemas/AzureModel" - }, - { - "$ref": "#/components/schemas/XAIModel" - }, - { - "$ref": "#/components/schemas/GroqModel" - }, - { - "$ref": "#/components/schemas/DeepseekModel" - }, - { - "$ref": "#/components/schemas/TogetherModel" - }, - { - "$ref": "#/components/schemas/BedrockModel" - } - ], - "discriminator": { - "propertyName": "provider", - "mapping": { - "anthropic": "#/components/schemas/AnthropicModel", - "azure": "#/components/schemas/AzureModel", - "bedrock": "#/components/schemas/BedrockModel", - "deepseek": "#/components/schemas/DeepseekModel", - "google_ai": "#/components/schemas/GoogleAIModel", - "google_vertex": "#/components/schemas/GoogleVertexModel", - "groq": "#/components/schemas/GroqModel", - "openai": "#/components/schemas/OpenAIModel", - "together": "#/components/schemas/TogetherModel", - "xai": "#/components/schemas/XAIModel" - } - } - }, { "type": "null" } ], "title": "Model", - "description": "The model handle or model settings for the agent to use, specified either by a handle or an object. See the model schema for more information." + "description": "The LLM configuration handle used by the agent, specified in the format provider/model-name, as an alternative to specifying llm_config." }, "embedding": { "anyOf": [ { "type": "string" }, - { - "$ref": "#/components/schemas/EmbeddingModelSettings" - }, { "type": "null" } @@ -22903,9 +22582,8 @@ } ], "title": "Embedding Chunk Size", - "description": "Deprecated: No longer used. The embedding chunk size used by the agent.", - "default": 300, - "deprecated": true + "description": "The embedding chunk size used by the agent.", + "default": 300 }, "max_tokens": { "anyOf": [ @@ -22917,8 +22595,7 @@ } ], "title": "Max Tokens", - "description": "Deprecated: Use `model` field to configure max output tokens instead. The maximum number of tokens to generate, including reasoning step.", - "deprecated": true + "description": "The maximum number of tokens to generate, including reasoning step. If not set, the model will use its default value." }, "max_reasoning_tokens": { "anyOf": [ @@ -22930,8 +22607,7 @@ } ], "title": "Max Reasoning Tokens", - "description": "Deprecated: Use `model` field to configure reasoning tokens instead. The maximum number of tokens to generate for reasoning step.", - "deprecated": true + "description": "The maximum number of tokens to generate for reasoning step. If not set, the model will use its default value." }, "enable_reasoner": { "anyOf": [ @@ -22943,9 +22619,8 @@ } ], "title": "Enable Reasoner", - "description": "Deprecated: Use `model` field to configure reasoning instead. Whether to enable internal extended thinking step for a reasoner model.", - "default": true, - "deprecated": true + "description": "Whether to enable internal extended thinking step for a reasoner model.", + "default": true }, "reasoning": { "anyOf": [ @@ -22957,8 +22632,7 @@ } ], "title": "Reasoning", - "description": "Deprecated: Use `model` field to configure reasoning instead. Whether to enable reasoning for this agent.", - "deprecated": true + "description": "Whether to enable reasoning for this agent." }, "from_template": { "anyOf": [ @@ -22970,15 +22644,13 @@ } ], "title": "From Template", - "description": "Deprecated: please use the 'create agents from a template' endpoint instead.", - "deprecated": true + "description": "Deprecated: please use the 'create agents from a template' endpoint instead." }, "template": { "type": "boolean", "title": "Template", - "description": "Deprecated: No longer used.", - "default": false, - "deprecated": true + "description": "Deprecated: No longer used", + "default": false }, "project": { "anyOf": [ @@ -22990,7 +22662,7 @@ } ], "title": "Project", - "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.", + "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 new x_project field below.", "deprecated": true }, "tool_exec_environment_variables": { @@ -23006,8 +22678,7 @@ } ], "title": "Tool Exec Environment Variables", - "description": "Deprecated: Use `secrets` field instead. Environment variables for tool execution.", - "deprecated": true + "description": "Deprecated: use `secrets` field instead." }, "secrets": { "anyOf": [ @@ -23037,8 +22708,7 @@ } ], "title": "Memory Variables", - "description": "Deprecated: Only relevant for creating agents from a template. Use the 'create agents from a template' endpoint instead.", - "deprecated": true + "description": "The variables that should be set for the agent." }, "project_id": { "anyOf": [ @@ -23050,8 +22720,7 @@ } ], "title": "Project Id", - "description": "Deprecated: No longer used. The id of the project the agent belongs to.", - "deprecated": true + "description": "The id of the project the agent belongs to." }, "template_id": { "anyOf": [ @@ -23063,8 +22732,7 @@ } ], "title": "Template Id", - "description": "Deprecated: No longer used. The id of the template the agent belongs to.", - "deprecated": true + "description": "The id of the template the agent belongs to." }, "base_template_id": { "anyOf": [ @@ -23076,8 +22744,7 @@ } ], "title": "Base Template Id", - "description": "Deprecated: No longer used. The base template id of the agent.", - "deprecated": true + "description": "The base template id of the agent." }, "identity_ids": { "anyOf": [ @@ -23188,8 +22855,7 @@ } ], "title": "Hidden", - "description": "Deprecated: No longer used. If set to True, the agent will be hidden.", - "deprecated": true + "description": "If set to True, the agent will be hidden." }, "parallel_tool_calls": { "anyOf": [ @@ -23201,9 +22867,8 @@ } ], "title": "Parallel Tool Calls", - "description": "Deprecated: Use `model` field to configure parallel tool calls instead. If set to True, enables parallel tool calling.", - "default": false, - "deprecated": true + "description": "If set to True, enables parallel tool calling. Defaults to False.", + "default": false } }, "type": "object", @@ -23636,68 +23301,6 @@ "required": ["input", "name"], "title": "Custom" }, - "DeepseekModel": { - "properties": { - "model": { - "type": "string", - "title": "Model", - "description": "The name of the model." - }, - "max_output_tokens": { - "type": "integer", - "title": "Max Output Tokens", - "description": "The maximum number of tokens the model can generate.", - "default": 4096 - }, - "provider": { - "type": "string", - "const": "deepseek", - "title": "Provider", - "description": "The provider of the model.", - "default": "deepseek" - }, - "temperature": { - "type": "number", - "title": "Temperature", - "description": "The temperature of the model.", - "default": 0.7 - }, - "response_format": { - "anyOf": [ - { - "oneOf": [ - { - "$ref": "#/components/schemas/TextResponseFormat" - }, - { - "$ref": "#/components/schemas/JsonSchemaResponseFormat" - }, - { - "$ref": "#/components/schemas/JsonObjectResponseFormat" - } - ], - "discriminator": { - "propertyName": "type", - "mapping": { - "json_object": "#/components/schemas/JsonObjectResponseFormat", - "json_schema": "#/components/schemas/JsonSchemaResponseFormat", - "text": "#/components/schemas/TextResponseFormat" - } - } - }, - { - "type": "null" - } - ], - "title": "Response Format", - "description": "The response format for the model." - } - }, - "type": "object", - "required": ["model"], - "title": "DeepseekModel", - "description": "Deepseek model configuration (OpenAI-compatible)." - }, "DeleteDeploymentResponse": { "properties": { "deleted_blocks": { @@ -24059,24 +23662,6 @@ "title": "EmbeddingConfig", "description": "Configuration for embedding model connection and processing parameters." }, - "EmbeddingModelSettings": { - "properties": { - "model": { - "type": "string", - "title": "Model", - "description": "The name of the model." - }, - "provider": { - "type": "string", - "enum": ["openai", "ollama"], - "title": "Provider", - "description": "The provider of the model." - } - }, - "type": "object", - "required": ["model", "provider"], - "title": "EmbeddingModelSettings" - }, "FeedbackType": { "type": "string", "enum": ["positive", "negative"], @@ -25025,24 +24610,6 @@ "required": ["function", "type"], "title": "FunctionTool" }, - "GeminiThinkingConfig": { - "properties": { - "include_thoughts": { - "type": "boolean", - "title": "Include Thoughts", - "description": "Whether to include thoughts in the model's response.", - "default": true - }, - "thinking_budget": { - "type": "integer", - "title": "Thinking Budget", - "description": "The thinking budget for the model.", - "default": 1024 - } - }, - "type": "object", - "title": "GeminiThinkingConfig" - }, "GenerateToolInput": { "properties": { "tool_name": { @@ -25114,206 +24681,6 @@ "required": ["tool", "sample_args", "response"], "title": "GenerateToolOutput" }, - "GoogleAIModel": { - "properties": { - "model": { - "type": "string", - "title": "Model", - "description": "The name of the model." - }, - "max_output_tokens": { - "type": "integer", - "title": "Max Output Tokens", - "description": "The maximum number of tokens the model can generate.", - "default": 65536 - }, - "provider": { - "type": "string", - "const": "google_ai", - "title": "Provider", - "description": "The provider of the model.", - "default": "google_ai" - }, - "temperature": { - "type": "number", - "title": "Temperature", - "description": "The temperature of the model.", - "default": 0.7 - }, - "thinking_config": { - "$ref": "#/components/schemas/GeminiThinkingConfig", - "description": "The thinking configuration for the model.", - "default": { - "include_thoughts": true, - "thinking_budget": 1024 - } - }, - "response_schema": { - "anyOf": [ - { - "oneOf": [ - { - "$ref": "#/components/schemas/TextResponseFormat" - }, - { - "$ref": "#/components/schemas/JsonSchemaResponseFormat" - }, - { - "$ref": "#/components/schemas/JsonObjectResponseFormat" - } - ], - "discriminator": { - "propertyName": "type", - "mapping": { - "json_object": "#/components/schemas/JsonObjectResponseFormat", - "json_schema": "#/components/schemas/JsonSchemaResponseFormat", - "text": "#/components/schemas/TextResponseFormat" - } - } - }, - { - "type": "null" - } - ], - "title": "Response Schema", - "description": "The response schema for the model." - } - }, - "type": "object", - "required": ["model"], - "title": "GoogleAIModel" - }, - "GoogleVertexModel": { - "properties": { - "model": { - "type": "string", - "title": "Model", - "description": "The name of the model." - }, - "max_output_tokens": { - "type": "integer", - "title": "Max Output Tokens", - "description": "The maximum number of tokens the model can generate.", - "default": 65536 - }, - "provider": { - "type": "string", - "const": "google_vertex", - "title": "Provider", - "description": "The provider of the model.", - "default": "google_vertex" - }, - "temperature": { - "type": "number", - "title": "Temperature", - "description": "The temperature of the model.", - "default": 0.7 - }, - "thinking_config": { - "$ref": "#/components/schemas/GeminiThinkingConfig", - "description": "The thinking configuration for the model.", - "default": { - "include_thoughts": true, - "thinking_budget": 1024 - } - }, - "response_schema": { - "anyOf": [ - { - "oneOf": [ - { - "$ref": "#/components/schemas/TextResponseFormat" - }, - { - "$ref": "#/components/schemas/JsonSchemaResponseFormat" - }, - { - "$ref": "#/components/schemas/JsonObjectResponseFormat" - } - ], - "discriminator": { - "propertyName": "type", - "mapping": { - "json_object": "#/components/schemas/JsonObjectResponseFormat", - "json_schema": "#/components/schemas/JsonSchemaResponseFormat", - "text": "#/components/schemas/TextResponseFormat" - } - } - }, - { - "type": "null" - } - ], - "title": "Response Schema", - "description": "The response schema for the model." - } - }, - "type": "object", - "required": ["model"], - "title": "GoogleVertexModel" - }, - "GroqModel": { - "properties": { - "model": { - "type": "string", - "title": "Model", - "description": "The name of the model." - }, - "max_output_tokens": { - "type": "integer", - "title": "Max Output Tokens", - "description": "The maximum number of tokens the model can generate.", - "default": 4096 - }, - "provider": { - "type": "string", - "const": "groq", - "title": "Provider", - "description": "The provider of the model.", - "default": "groq" - }, - "temperature": { - "type": "number", - "title": "Temperature", - "description": "The temperature of the model.", - "default": 0.7 - }, - "response_format": { - "anyOf": [ - { - "oneOf": [ - { - "$ref": "#/components/schemas/TextResponseFormat" - }, - { - "$ref": "#/components/schemas/JsonSchemaResponseFormat" - }, - { - "$ref": "#/components/schemas/JsonObjectResponseFormat" - } - ], - "discriminator": { - "propertyName": "type", - "mapping": { - "json_object": "#/components/schemas/JsonObjectResponseFormat", - "json_schema": "#/components/schemas/JsonSchemaResponseFormat", - "text": "#/components/schemas/TextResponseFormat" - } - } - }, - { - "type": "null" - } - ], - "title": "Response Format", - "description": "The response format for the model." - } - }, - "type": "object", - "required": ["model"], - "title": "GroqModel", - "description": "Groq model configuration (OpenAI-compatible)." - }, "Group": { "properties": { "id": { @@ -26613,6 +25980,28 @@ "$ref": "#/components/schemas/AgentType", "description": "The type of agent." }, + "llm_config": { + "anyOf": [ + { + "$ref": "#/components/schemas/LLMConfig" + }, + { + "type": "null" + } + ], + "description": "The LLM configuration used by the agent." + }, + "embedding_config": { + "anyOf": [ + { + "$ref": "#/components/schemas/EmbeddingConfig" + }, + { + "type": "null" + } + ], + "description": "The embedding configuration used by the agent." + }, "initial_message_sequence": { "anyOf": [ { @@ -26656,8 +26045,7 @@ "type": "boolean", "title": "Include Default Source", "description": "If true, automatically creates and attaches a default data source for this agent.", - "default": false, - "deprecated": true + "default": false }, "description": { "anyOf": [ @@ -26684,99 +26072,23 @@ "title": "Metadata", "description": "The metadata of the agent." }, - "llm_config": { - "anyOf": [ - { - "$ref": "#/components/schemas/LLMConfig" - }, - { - "type": "null" - } - ], - "description": "Deprecated: Use `model` field instead. The LLM configuration used by the agent.", - "deprecated": true - }, - "embedding_config": { - "anyOf": [ - { - "$ref": "#/components/schemas/EmbeddingConfig" - }, - { - "type": "null" - } - ], - "description": "Deprecated: Use `embedding` field instead. The embedding configuration used by the agent.", - "deprecated": true - }, "model": { "anyOf": [ { "type": "string" }, - { - "oneOf": [ - { - "$ref": "#/components/schemas/OpenAIModel" - }, - { - "$ref": "#/components/schemas/AnthropicModel" - }, - { - "$ref": "#/components/schemas/GoogleAIModel" - }, - { - "$ref": "#/components/schemas/GoogleVertexModel" - }, - { - "$ref": "#/components/schemas/AzureModel" - }, - { - "$ref": "#/components/schemas/XAIModel" - }, - { - "$ref": "#/components/schemas/GroqModel" - }, - { - "$ref": "#/components/schemas/DeepseekModel" - }, - { - "$ref": "#/components/schemas/TogetherModel" - }, - { - "$ref": "#/components/schemas/BedrockModel" - } - ], - "discriminator": { - "propertyName": "provider", - "mapping": { - "anthropic": "#/components/schemas/AnthropicModel", - "azure": "#/components/schemas/AzureModel", - "bedrock": "#/components/schemas/BedrockModel", - "deepseek": "#/components/schemas/DeepseekModel", - "google_ai": "#/components/schemas/GoogleAIModel", - "google_vertex": "#/components/schemas/GoogleVertexModel", - "groq": "#/components/schemas/GroqModel", - "openai": "#/components/schemas/OpenAIModel", - "together": "#/components/schemas/TogetherModel", - "xai": "#/components/schemas/XAIModel" - } - } - }, { "type": "null" } ], "title": "Model", - "description": "The model handle or model settings for the agent to use, specified either by a handle or an object. See the model schema for more information." + "description": "The LLM configuration handle used by the agent, specified in the format provider/model-name, as an alternative to specifying llm_config." }, "embedding": { "anyOf": [ { "type": "string" }, - { - "$ref": "#/components/schemas/EmbeddingModelSettings" - }, { "type": "null" } @@ -26806,9 +26118,8 @@ } ], "title": "Embedding Chunk Size", - "description": "Deprecated: No longer used. The embedding chunk size used by the agent.", - "default": 300, - "deprecated": true + "description": "The embedding chunk size used by the agent.", + "default": 300 }, "max_tokens": { "anyOf": [ @@ -26820,8 +26131,7 @@ } ], "title": "Max Tokens", - "description": "Deprecated: Use `model` field to configure max output tokens instead. The maximum number of tokens to generate, including reasoning step.", - "deprecated": true + "description": "The maximum number of tokens to generate, including reasoning step. If not set, the model will use its default value." }, "max_reasoning_tokens": { "anyOf": [ @@ -26833,8 +26143,7 @@ } ], "title": "Max Reasoning Tokens", - "description": "Deprecated: Use `model` field to configure reasoning tokens instead. The maximum number of tokens to generate for reasoning step.", - "deprecated": true + "description": "The maximum number of tokens to generate for reasoning step. If not set, the model will use its default value." }, "enable_reasoner": { "anyOf": [ @@ -26846,9 +26155,8 @@ } ], "title": "Enable Reasoner", - "description": "Deprecated: Use `model` field to configure reasoning instead. Whether to enable internal extended thinking step for a reasoner model.", - "default": true, - "deprecated": true + "description": "Whether to enable internal extended thinking step for a reasoner model.", + "default": true }, "reasoning": { "anyOf": [ @@ -26860,8 +26168,7 @@ } ], "title": "Reasoning", - "description": "Deprecated: Use `model` field to configure reasoning instead. Whether to enable reasoning for this agent.", - "deprecated": true + "description": "Whether to enable reasoning for this agent." }, "from_template": { "anyOf": [ @@ -26873,15 +26180,13 @@ } ], "title": "From Template", - "description": "Deprecated: please use the 'create agents from a template' endpoint instead.", - "deprecated": true + "description": "Deprecated: please use the 'create agents from a template' endpoint instead." }, "template": { "type": "boolean", "title": "Template", - "description": "Deprecated: No longer used.", - "default": false, - "deprecated": true + "description": "Deprecated: No longer used", + "default": false }, "project": { "anyOf": [ @@ -26893,7 +26198,7 @@ } ], "title": "Project", - "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.", + "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 new x_project field below.", "deprecated": true }, "tool_exec_environment_variables": { @@ -26909,8 +26214,7 @@ } ], "title": "Tool Exec Environment Variables", - "description": "Deprecated: Use `secrets` field instead. Environment variables for tool execution.", - "deprecated": true + "description": "Deprecated: use `secrets` field instead." }, "secrets": { "anyOf": [ @@ -26940,8 +26244,7 @@ } ], "title": "Memory Variables", - "description": "Deprecated: Only relevant for creating agents from a template. Use the 'create agents from a template' endpoint instead.", - "deprecated": true + "description": "The variables that should be set for the agent." }, "project_id": { "anyOf": [ @@ -26953,8 +26256,7 @@ } ], "title": "Project Id", - "description": "Deprecated: No longer used. The id of the project the agent belongs to.", - "deprecated": true + "description": "The id of the project the agent belongs to." }, "template_id": { "type": "string", @@ -27075,8 +26377,7 @@ } ], "title": "Hidden", - "description": "Deprecated: No longer used. If set to True, the agent will be hidden.", - "deprecated": true + "description": "If set to True, the agent will be hidden." }, "parallel_tool_calls": { "anyOf": [ @@ -27088,9 +26389,8 @@ } ], "title": "Parallel Tool Calls", - "description": "Deprecated: Use `model` field to configure parallel tool calls instead. If set to True, enables parallel tool calling.", - "default": false, - "deprecated": true + "description": "If set to True, enables parallel tool calling. Defaults to False.", + "default": false }, "deployment_id": { "type": "string", @@ -29542,87 +28842,6 @@ "title": "OmittedReasoningContent", "description": "A placeholder for reasoning content we know is present, but isn't returned by the provider (e.g. OpenAI GPT-5 on ChatCompletions)" }, - "OpenAIModel": { - "properties": { - "model": { - "type": "string", - "title": "Model", - "description": "The name of the model." - }, - "max_output_tokens": { - "type": "integer", - "title": "Max Output Tokens", - "description": "The maximum number of tokens the model can generate.", - "default": 4096 - }, - "provider": { - "type": "string", - "const": "openai", - "title": "Provider", - "description": "The provider of the model.", - "default": "openai" - }, - "temperature": { - "type": "number", - "title": "Temperature", - "description": "The temperature of the model.", - "default": 0.7 - }, - "reasoning": { - "$ref": "#/components/schemas/OpenAIReasoning", - "description": "The reasoning configuration for the model.", - "default": { - "reasoning_effort": "high" - } - }, - "response_format": { - "anyOf": [ - { - "oneOf": [ - { - "$ref": "#/components/schemas/TextResponseFormat" - }, - { - "$ref": "#/components/schemas/JsonSchemaResponseFormat" - }, - { - "$ref": "#/components/schemas/JsonObjectResponseFormat" - } - ], - "discriminator": { - "propertyName": "type", - "mapping": { - "json_object": "#/components/schemas/JsonObjectResponseFormat", - "json_schema": "#/components/schemas/JsonSchemaResponseFormat", - "text": "#/components/schemas/TextResponseFormat" - } - } - }, - { - "type": "null" - } - ], - "title": "Response Format", - "description": "The response format for the model." - } - }, - "type": "object", - "required": ["model"], - "title": "OpenAIModel" - }, - "OpenAIReasoning": { - "properties": { - "reasoning_effort": { - "type": "string", - "enum": ["minimal", "low", "medium", "high"], - "title": "Reasoning Effort", - "description": "The reasoning effort to use when generating text reasoning models", - "default": "minimal" - } - }, - "type": "object", - "title": "OpenAIReasoning" - }, "Organization": { "properties": { "id": { @@ -33077,68 +32296,6 @@ "title": "TextResponseFormat", "description": "Response format for plain text responses." }, - "TogetherModel": { - "properties": { - "model": { - "type": "string", - "title": "Model", - "description": "The name of the model." - }, - "max_output_tokens": { - "type": "integer", - "title": "Max Output Tokens", - "description": "The maximum number of tokens the model can generate.", - "default": 4096 - }, - "provider": { - "type": "string", - "const": "together", - "title": "Provider", - "description": "The provider of the model.", - "default": "together" - }, - "temperature": { - "type": "number", - "title": "Temperature", - "description": "The temperature of the model.", - "default": 0.7 - }, - "response_format": { - "anyOf": [ - { - "oneOf": [ - { - "$ref": "#/components/schemas/TextResponseFormat" - }, - { - "$ref": "#/components/schemas/JsonSchemaResponseFormat" - }, - { - "$ref": "#/components/schemas/JsonObjectResponseFormat" - } - ], - "discriminator": { - "propertyName": "type", - "mapping": { - "json_object": "#/components/schemas/JsonObjectResponseFormat", - "json_schema": "#/components/schemas/JsonSchemaResponseFormat", - "text": "#/components/schemas/TextResponseFormat" - } - } - }, - { - "type": "null" - } - ], - "title": "Response Format", - "description": "The response format for the model." - } - }, - "type": "object", - "required": ["model"], - "title": "TogetherModel", - "description": "Together AI model configuration (OpenAI-compatible)." - }, "Tool": { "properties": { "id": { @@ -34595,6 +33752,28 @@ "title": "Tool Rules", "description": "The tool rules governing the agent." }, + "llm_config": { + "anyOf": [ + { + "$ref": "#/components/schemas/LLMConfig" + }, + { + "type": "null" + } + ], + "description": "The LLM configuration used by the agent." + }, + "embedding_config": { + "anyOf": [ + { + "$ref": "#/components/schemas/EmbeddingConfig" + }, + { + "type": "null" + } + ], + "description": "The embedding configuration used by the agent." + }, "message_ids": { "anyOf": [ { @@ -34733,70 +33912,18 @@ { "type": "string" }, - { - "oneOf": [ - { - "$ref": "#/components/schemas/OpenAIModel" - }, - { - "$ref": "#/components/schemas/AnthropicModel" - }, - { - "$ref": "#/components/schemas/GoogleAIModel" - }, - { - "$ref": "#/components/schemas/GoogleVertexModel" - }, - { - "$ref": "#/components/schemas/AzureModel" - }, - { - "$ref": "#/components/schemas/XAIModel" - }, - { - "$ref": "#/components/schemas/GroqModel" - }, - { - "$ref": "#/components/schemas/DeepseekModel" - }, - { - "$ref": "#/components/schemas/TogetherModel" - }, - { - "$ref": "#/components/schemas/BedrockModel" - } - ], - "discriminator": { - "propertyName": "provider", - "mapping": { - "anthropic": "#/components/schemas/AnthropicModel", - "azure": "#/components/schemas/AzureModel", - "bedrock": "#/components/schemas/BedrockModel", - "deepseek": "#/components/schemas/DeepseekModel", - "google_ai": "#/components/schemas/GoogleAIModel", - "google_vertex": "#/components/schemas/GoogleVertexModel", - "groq": "#/components/schemas/GroqModel", - "openai": "#/components/schemas/OpenAIModel", - "together": "#/components/schemas/TogetherModel", - "xai": "#/components/schemas/XAIModel" - } - } - }, { "type": "null" } ], "title": "Model", - "description": "The model used by the agent, specified either by a handle or an object. See the model schema for more information." + "description": "The LLM configuration handle used by the agent, specified in the format provider/model-name, as an alternative to specifying llm_config." }, "embedding": { "anyOf": [ { "type": "string" }, - { - "$ref": "#/components/schemas/EmbeddingModelSettings" - }, { "type": "null" } @@ -34816,6 +33943,18 @@ "title": "Context Window Limit", "description": "The context window limit used by the agent." }, + "max_tokens": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Max Tokens", + "description": "The maximum number of tokens to generate, including reasoning step. If not set, the model will use its default value." + }, "reasoning": { "anyOf": [ { @@ -34826,33 +33965,9 @@ } ], "title": "Reasoning", - "description": "Deprecated: Use `model` field to configure reasoning instead. Whether to enable reasoning for this agent.", - "deprecated": true + "description": "Whether to enable reasoning for this agent." }, - "llm_config": { - "anyOf": [ - { - "$ref": "#/components/schemas/LLMConfig" - }, - { - "type": "null" - } - ], - "description": "Deprecated: Use `model` field instead. The LLM configuration used by the agent.", - "deprecated": true - }, - "embedding_config": { - "anyOf": [ - { - "$ref": "#/components/schemas/EmbeddingConfig" - }, - { - "type": "null" - } - ], - "description": "The embedding configuration used by the agent." - }, - "parallel_tool_calls": { + "enable_sleeptime": { "anyOf": [ { "type": "boolean" @@ -34861,10 +33976,8 @@ "type": "null" } ], - "title": "Parallel Tool Calls", - "description": "Deprecated: Use `model` field to configure parallel tool calls instead. If set to True, enables parallel tool calling.", - "default": false, - "deprecated": true + "title": "Enable Sleeptime", + "description": "If set to True, memory management will move to a background agent thread." }, "response_format": { "anyOf": [ @@ -34894,33 +34007,7 @@ } ], "title": "Response Format", - "description": "Deprecated: Use `model` field to configure response format instead. The response format for the agent.", - "deprecated": true - }, - "max_tokens": { - "anyOf": [ - { - "type": "integer" - }, - { - "type": "null" - } - ], - "title": "Max Tokens", - "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": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ], - "title": "Enable Sleeptime", - "description": "If set to True, memory management will move to a background agent thread." + "description": "The response format for the agent." }, "last_run_completion": { "anyOf": [ @@ -34994,6 +34081,19 @@ ], "title": "Hidden", "description": "If set to True, the agent will be hidden." + }, + "parallel_tool_calls": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Parallel Tool Calls", + "description": "If set to True, enables parallel tool calling. Defaults to False.", + "default": false } }, "type": "object", @@ -35506,68 +34606,6 @@ "type": "object", "title": "VoiceSleeptimeManagerUpdate" }, - "XAIModel": { - "properties": { - "model": { - "type": "string", - "title": "Model", - "description": "The name of the model." - }, - "max_output_tokens": { - "type": "integer", - "title": "Max Output Tokens", - "description": "The maximum number of tokens the model can generate.", - "default": 4096 - }, - "provider": { - "type": "string", - "const": "xai", - "title": "Provider", - "description": "The provider of the model.", - "default": "xai" - }, - "temperature": { - "type": "number", - "title": "Temperature", - "description": "The temperature of the model.", - "default": 0.7 - }, - "response_format": { - "anyOf": [ - { - "oneOf": [ - { - "$ref": "#/components/schemas/TextResponseFormat" - }, - { - "$ref": "#/components/schemas/JsonSchemaResponseFormat" - }, - { - "$ref": "#/components/schemas/JsonObjectResponseFormat" - } - ], - "discriminator": { - "propertyName": "type", - "mapping": { - "json_object": "#/components/schemas/JsonObjectResponseFormat", - "json_schema": "#/components/schemas/JsonSchemaResponseFormat", - "text": "#/components/schemas/TextResponseFormat" - } - } - }, - { - "type": "null" - } - ], - "title": "Response Format", - "description": "The response format for the model." - } - }, - "type": "object", - "required": ["model"], - "title": "XAIModel", - "description": "xAI model configuration (OpenAI-compatible)." - }, "letta__schemas__agent_file__AgentSchema": { "properties": { "name": { @@ -35738,6 +34776,28 @@ "$ref": "#/components/schemas/AgentType", "description": "The type of agent." }, + "llm_config": { + "anyOf": [ + { + "$ref": "#/components/schemas/LLMConfig" + }, + { + "type": "null" + } + ], + "description": "The LLM configuration used by the agent." + }, + "embedding_config": { + "anyOf": [ + { + "$ref": "#/components/schemas/EmbeddingConfig" + }, + { + "type": "null" + } + ], + "description": "The embedding configuration used by the agent." + }, "initial_message_sequence": { "anyOf": [ { @@ -35781,8 +34841,7 @@ "type": "boolean", "title": "Include Default Source", "description": "If true, automatically creates and attaches a default data source for this agent.", - "default": false, - "deprecated": true + "default": false }, "description": { "anyOf": [ @@ -35809,99 +34868,23 @@ "title": "Metadata", "description": "The metadata of the agent." }, - "llm_config": { - "anyOf": [ - { - "$ref": "#/components/schemas/LLMConfig" - }, - { - "type": "null" - } - ], - "description": "Deprecated: Use `model` field instead. The LLM configuration used by the agent.", - "deprecated": true - }, - "embedding_config": { - "anyOf": [ - { - "$ref": "#/components/schemas/EmbeddingConfig" - }, - { - "type": "null" - } - ], - "description": "Deprecated: Use `embedding` field instead. The embedding configuration used by the agent.", - "deprecated": true - }, "model": { "anyOf": [ { "type": "string" }, - { - "oneOf": [ - { - "$ref": "#/components/schemas/OpenAIModel" - }, - { - "$ref": "#/components/schemas/AnthropicModel" - }, - { - "$ref": "#/components/schemas/GoogleAIModel" - }, - { - "$ref": "#/components/schemas/GoogleVertexModel" - }, - { - "$ref": "#/components/schemas/AzureModel" - }, - { - "$ref": "#/components/schemas/XAIModel" - }, - { - "$ref": "#/components/schemas/GroqModel" - }, - { - "$ref": "#/components/schemas/DeepseekModel" - }, - { - "$ref": "#/components/schemas/TogetherModel" - }, - { - "$ref": "#/components/schemas/BedrockModel" - } - ], - "discriminator": { - "propertyName": "provider", - "mapping": { - "anthropic": "#/components/schemas/AnthropicModel", - "azure": "#/components/schemas/AzureModel", - "bedrock": "#/components/schemas/BedrockModel", - "deepseek": "#/components/schemas/DeepseekModel", - "google_ai": "#/components/schemas/GoogleAIModel", - "google_vertex": "#/components/schemas/GoogleVertexModel", - "groq": "#/components/schemas/GroqModel", - "openai": "#/components/schemas/OpenAIModel", - "together": "#/components/schemas/TogetherModel", - "xai": "#/components/schemas/XAIModel" - } - } - }, { "type": "null" } ], "title": "Model", - "description": "The model handle or model settings for the agent to use, specified either by a handle or an object. See the model schema for more information." + "description": "The LLM configuration handle used by the agent, specified in the format provider/model-name, as an alternative to specifying llm_config." }, "embedding": { "anyOf": [ { "type": "string" }, - { - "$ref": "#/components/schemas/EmbeddingModelSettings" - }, { "type": "null" } @@ -35931,9 +34914,8 @@ } ], "title": "Embedding Chunk Size", - "description": "Deprecated: No longer used. The embedding chunk size used by the agent.", - "default": 300, - "deprecated": true + "description": "The embedding chunk size used by the agent.", + "default": 300 }, "max_tokens": { "anyOf": [ @@ -35945,8 +34927,7 @@ } ], "title": "Max Tokens", - "description": "Deprecated: Use `model` field to configure max output tokens instead. The maximum number of tokens to generate, including reasoning step.", - "deprecated": true + "description": "The maximum number of tokens to generate, including reasoning step. If not set, the model will use its default value." }, "max_reasoning_tokens": { "anyOf": [ @@ -35958,8 +34939,7 @@ } ], "title": "Max Reasoning Tokens", - "description": "Deprecated: Use `model` field to configure reasoning tokens instead. The maximum number of tokens to generate for reasoning step.", - "deprecated": true + "description": "The maximum number of tokens to generate for reasoning step. If not set, the model will use its default value." }, "enable_reasoner": { "anyOf": [ @@ -35971,9 +34951,8 @@ } ], "title": "Enable Reasoner", - "description": "Deprecated: Use `model` field to configure reasoning instead. Whether to enable internal extended thinking step for a reasoner model.", - "default": true, - "deprecated": true + "description": "Whether to enable internal extended thinking step for a reasoner model.", + "default": true }, "reasoning": { "anyOf": [ @@ -35985,8 +34964,7 @@ } ], "title": "Reasoning", - "description": "Deprecated: Use `model` field to configure reasoning instead. Whether to enable reasoning for this agent.", - "deprecated": true + "description": "Whether to enable reasoning for this agent." }, "from_template": { "anyOf": [ @@ -35998,15 +34976,13 @@ } ], "title": "From Template", - "description": "Deprecated: please use the 'create agents from a template' endpoint instead.", - "deprecated": true + "description": "Deprecated: please use the 'create agents from a template' endpoint instead." }, "template": { "type": "boolean", "title": "Template", - "description": "Deprecated: No longer used.", - "default": false, - "deprecated": true + "description": "Deprecated: No longer used", + "default": false }, "project": { "anyOf": [ @@ -36018,7 +34994,7 @@ } ], "title": "Project", - "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.", + "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 new x_project field below.", "deprecated": true }, "tool_exec_environment_variables": { @@ -36034,8 +35010,7 @@ } ], "title": "Tool Exec Environment Variables", - "description": "Deprecated: Use `secrets` field instead. Environment variables for tool execution.", - "deprecated": true + "description": "Deprecated: use `secrets` field instead." }, "secrets": { "anyOf": [ @@ -36065,8 +35040,7 @@ } ], "title": "Memory Variables", - "description": "Deprecated: Only relevant for creating agents from a template. Use the 'create agents from a template' endpoint instead.", - "deprecated": true + "description": "The variables that should be set for the agent." }, "project_id": { "anyOf": [ @@ -36078,8 +35052,7 @@ } ], "title": "Project Id", - "description": "Deprecated: No longer used. The id of the project the agent belongs to.", - "deprecated": true + "description": "The id of the project the agent belongs to." }, "template_id": { "anyOf": [ @@ -36091,8 +35064,7 @@ } ], "title": "Template Id", - "description": "Deprecated: No longer used. The id of the template the agent belongs to.", - "deprecated": true + "description": "The id of the template the agent belongs to." }, "base_template_id": { "anyOf": [ @@ -36104,8 +35076,7 @@ } ], "title": "Base Template Id", - "description": "Deprecated: No longer used. The base template id of the agent.", - "deprecated": true + "description": "The base template id of the agent." }, "identity_ids": { "anyOf": [ @@ -36216,8 +35187,7 @@ } ], "title": "Hidden", - "description": "Deprecated: No longer used. If set to True, the agent will be hidden.", - "deprecated": true + "description": "If set to True, the agent will be hidden." }, "parallel_tool_calls": { "anyOf": [ @@ -36229,9 +35199,8 @@ } ], "title": "Parallel Tool Calls", - "description": "Deprecated: Use `model` field to configure parallel tool calls instead. If set to True, enables parallel tool calling.", - "default": false, - "deprecated": true + "description": "If set to True, enables parallel tool calling. Defaults to False.", + "default": false }, "id": { "type": "string", diff --git a/letta/orm/agent.py b/letta/orm/agent.py index 95c0d064..fc1f17a8 100644 --- a/letta/orm/agent.py +++ b/letta/orm/agent.py @@ -280,8 +280,6 @@ class Agent(SqlalchemyBase, OrganizationMixin, ProjectMixin, TemplateEntityMixin if resolver: state[field_name] = resolver() - state["model"] = self.llm_config._to_model() if self.llm_config else None - return self.__pydantic_model__(**state) async def to_pydantic_async( @@ -419,6 +417,5 @@ class Agent(SqlalchemyBase, OrganizationMixin, ProjectMixin, TemplateEntityMixin state["managed_group"] = multi_agent_group state["tool_exec_environment_variables"] = tool_exec_environment_variables state["secrets"] = tool_exec_environment_variables - state["model"] = self.llm_config._to_model() if self.llm_config else None return self.__pydantic_model__(**state) diff --git a/letta/schemas/agent.py b/letta/schemas/agent.py index f07b4eca..48912f8f 100644 --- a/letta/schemas/agent.py +++ b/letta/schemas/agent.py @@ -17,7 +17,6 @@ from letta.schemas.letta_base import OrmMetadataBase 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 EmbeddingModelSettings, ModelSettings from letta.schemas.openai.chat_completion_response import UsageStatistics from letta.schemas.response_format import ResponseFormatUnion from letta.schemas.source import Source @@ -88,19 +87,11 @@ class AgentState(OrmMetadataBase, validate_assignment=True): # 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: EmbeddingConfig = Field( - ..., description="Deprecated: Use `embedding` field instead. The embedding configuration used by the agent.", deprecated=True - ) - model: Optional[ModelSettings] = Field(None, description="The model used by the agent.") - embedding: Optional[EmbeddingModelSettings] = Field(None, description="The embedding model used by the agent.") - + # llm information + llm_config: LLMConfig = Field(..., description="The LLM configuration used by the agent.") + embedding_config: EmbeddingConfig = Field(..., description="The embedding configuration used by the agent.") response_format: Optional[ResponseFormatUnion] = Field( - None, - description="The response format used by the agent", + None, description="The response format used by the agent when returning from `send_message`." ) # This is an object representing the in-process state of a running `Agent` @@ -108,7 +99,7 @@ class AgentState(OrmMetadataBase, validate_assignment=True): 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) + memory: Memory = Field(..., description="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="The sources used by the agent.") @@ -126,9 +117,7 @@ class AgentState(OrmMetadataBase, validate_assignment=True): 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 - ) + identity_ids: List[str] = Field([], description="The ids of the identities associated with this agent.", deprecated=True) identities: List[Identity] = Field([], description="The identities associated with this agent.") # An advanced configuration that makes it so this agent does not remember any previous messages @@ -141,9 +130,7 @@ class AgentState(OrmMetadataBase, validate_assignment=True): 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 - ) + multi_agent_group: Optional[Group] = Field(None, description="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.") @@ -215,6 +202,8 @@ class CreateAgent(BaseModel, validate_assignment=True): # 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.memgpt_v2_agent, description="The type of agent.") + llm_config: Optional[LLMConfig] = Field(None, description="The LLM configuration used by the agent.") + embedding_config: Optional[EmbeddingConfig] = Field(None, description="The embedding configuration used by the 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( @@ -227,78 +216,43 @@ class CreateAgent(BaseModel, validate_assignment=True): # 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 + include_default_source: bool = Field( + False, description="If true, automatically creates and attaches a default data source for this agent." ) 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 | ModelSettings] = Field( # TODO: make this required (breaking change) + model: Optional[str] = Field( None, - description="The model handle or model settings for the agent to use, specified either by a handle or an object. See the model schema for more information.", + description="The LLM configuration handle used by the agent, specified in the format " + "provider/model-name, as an alternative to specifying llm_config.", ) - embedding: Optional[str | EmbeddingModelSettings] = Field( + embedding: Optional[str] = Field( None, description="The embedding configuration handle used by the agent, specified in the format provider/model-name." ) - 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 - ) + embedding_chunk_size: Optional[int] = Field(DEFAULT_EMBEDDING_CHUNK_SIZE, description="The embedding chunk size used by the agent.") 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, + description="The maximum number of tokens to generate, including reasoning step. If not set, the model will use its default value.", ) 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, + None, description="The maximum number of tokens to generate for reasoning step. If not set, the model will use its default value." ) - 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) + enable_reasoner: Optional[bool] = Field(True, description="Whether to enable internal extended thinking step for a reasoner model.") + reasoning: Optional[bool] = Field(None, description="Whether to enable reasoning for this agent.") + from_template: Optional[str] = Field(None, description="Deprecated: please use the 'create agents from a template' endpoint instead.") + template: bool = Field(False, description="Deprecated: No longer used") 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 + 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 new x_project field below.", ) + 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.") - 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 - ) + memory_variables: Optional[Dict[str, str]] = Field(None, description="The variables that should be set for the 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[str]] = Field(None, description="The ids of the identities associated with this agent.") message_buffer_autoclear: bool = Field( False, @@ -317,14 +271,9 @@ class CreateAgent(BaseModel, validate_assignment=True): # ) 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( - False, - description="Deprecated: Use `model` field to configure parallel tool calls instead. If set to True, enables parallel tool calling.", - deprecated=True, + description="If set to True, the agent will be hidden.", ) + parallel_tool_calls: Optional[bool] = Field(False, description="If set to True, enables parallel tool calling. Defaults to False.") @field_validator("name") @classmethod @@ -406,6 +355,8 @@ class UpdateAgent(BaseModel): 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.") + llm_config: Optional[LLMConfig] = Field(None, description="The LLM configuration used by the agent.") + embedding_config: Optional[EmbeddingConfig] = Field(None, description="The embedding configuration used by the agent.") message_ids: Optional[List[str]] = 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.") @@ -419,42 +370,22 @@ class UpdateAgent(BaseModel): 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 | ModelSettings] = Field( + model: Optional[str] = Field( None, - description="The model used by the agent, specified either by a handle or an object. See the model schema for more information.", + description="The LLM configuration handle used by the agent, specified in the format " + "provider/model-name, as an alternative to specifying llm_config.", ) - embedding: Optional[str | EmbeddingModelSettings] = Field( + embedding: Optional[str] = Field( None, description="The embedding configuration handle used by the agent, specified in the format provider/model-name." ) 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( - False, - description="Deprecated: Use `model` field 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` 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, + description="The maximum number of tokens to generate, including reasoning step. If not set, the model will use its default value.", ) - + reasoning: Optional[bool] = Field(None, description="Whether to enable reasoning for this agent.") 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="The response format for the agent.") 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.") timezone: Optional[str] = Field(None, description="The timezone of the agent (IANA format).") @@ -470,6 +401,7 @@ class UpdateAgent(BaseModel): None, description="If set to True, the agent will be hidden.", ) + parallel_tool_calls: Optional[bool] = Field(False, description="If set to True, enables parallel tool calling. Defaults to False.") model_config = ConfigDict(extra="ignore") # Ignores extra fields diff --git a/letta/schemas/llm_config.py b/letta/schemas/llm_config.py index bd768d0a..69c6b25c 100644 --- a/letta/schemas/llm_config.py +++ b/letta/schemas/llm_config.py @@ -1,4 +1,4 @@ -from typing import TYPE_CHECKING, Annotated, Literal, Optional, Union +from typing import TYPE_CHECKING, Literal, Optional from pydantic import BaseModel, ConfigDict, Field, model_validator @@ -7,9 +7,6 @@ from letta.errors import LettaInvalidArgumentError from letta.log import get_logger from letta.schemas.enums import AgentType, ProviderCategory -if TYPE_CHECKING: - from letta.schemas.model import ModelSettings - logger = get_logger(__name__) @@ -255,98 +252,6 @@ class LLMConfig(BaseModel): + (f" [ip={self.model_endpoint}]" if self.model_endpoint else "") ) - def _to_model(self) -> "ModelSettings": - """ - Convert LLMConfig back into a Model schema (OpenAIModel, AnthropicModel, etc.). - This is the inverse of the _to_legacy_config_params() methods in model.py. - """ - from letta.schemas.model import ( - AnthropicModel, - AnthropicThinking, - AzureModel, - BedrockModel, - DeepseekModel, - GeminiThinkingConfig, - GoogleAIModel, - GoogleVertexModel, - GroqModel, - Model, - OpenAIModel, - OpenAIReasoning, - TogetherModel, - XAIModel, - ) - - if self.model_endpoint_type == "openai": - return OpenAIModel( - model=self.model, - max_output_tokens=self.max_tokens or 4096, - temperature=self.temperature, - reasoning=OpenAIReasoning(reasoning_effort=self.reasoning_effort or "minimal"), - ) - elif self.model_endpoint_type == "anthropic": - thinking_type = "enabled" if self.enable_reasoner else "disabled" - return AnthropicModel( - model=self.model, - max_output_tokens=self.max_tokens or 4096, - temperature=self.temperature, - thinking=AnthropicThinking(type=thinking_type, budget_tokens=self.max_reasoning_tokens or 1024), - verbosity=self.verbosity, - ) - elif self.model_endpoint_type == "google_ai": - return GoogleAIModel( - model=self.model, - max_output_tokens=self.max_tokens or 65536, - temperature=self.temperature, - thinking_config=GeminiThinkingConfig( - include_thoughts=self.max_reasoning_tokens > 0, thinking_budget=self.max_reasoning_tokens or 1024 - ), - ) - elif self.model_endpoint_type == "google_vertex": - return GoogleVertexModel( - model=self.model, - max_output_tokens=self.max_tokens or 65536, - temperature=self.temperature, - thinking_config=GeminiThinkingConfig( - include_thoughts=self.max_reasoning_tokens > 0, thinking_budget=self.max_reasoning_tokens or 1024 - ), - ) - elif self.model_endpoint_type == "azure": - return AzureModel( - model=self.model, - max_output_tokens=self.max_tokens or 4096, - temperature=self.temperature, - ) - elif self.model_endpoint_type == "xai": - return XAIModel( - model=self.model, - max_output_tokens=self.max_tokens or 4096, - temperature=self.temperature, - ) - elif self.model_endpoint_type == "groq": - return GroqModel( - model=self.model, - max_output_tokens=self.max_tokens or 4096, - temperature=self.temperature, - ) - elif self.model_endpoint_type == "deepseek": - return DeepseekModel( - model=self.model, - max_output_tokens=self.max_tokens or 4096, - temperature=self.temperature, - ) - elif self.model_endpoint_type == "together": - return TogetherModel( - model=self.model, - max_output_tokens=self.max_tokens or 4096, - temperature=self.temperature, - ) - elif self.model_endpoint_type == "bedrock": - return Model(model=self.model, max_output_tokens=self.max_tokens or 4096) - else: - # If we don't know the model type, use the default Model schema - return Model(model=self.model, max_output_tokens=self.max_tokens or 4096) - @classmethod def is_openai_reasoning_model(cls, config: "LLMConfig") -> bool: from letta.llm_api.openai_client import is_openai_reasoning_model diff --git a/letta/schemas/model.py b/letta/schemas/model.py deleted file mode 100644 index 1cb334d5..00000000 --- a/letta/schemas/model.py +++ /dev/null @@ -1,224 +0,0 @@ -from typing import Annotated, Literal, Optional, Union - -from pydantic import BaseModel, Field - -from letta.schemas.llm_config import LLMConfig -from letta.schemas.response_format import ResponseFormatUnion - - -class Model(BaseModel): - """Schema for defining settings for a model""" - - model: str = Field(..., description="The name of the model.") - max_output_tokens: int = Field(4096, description="The maximum number of tokens the model can generate.") - - -class OpenAIReasoning(BaseModel): - reasoning_effort: Literal["minimal", "low", "medium", "high"] = Field( - "minimal", description="The reasoning effort to use when generating text reasoning models" - ) - - # TODO: implement support for this - # summary: Optional[Literal["auto", "detailed"]] = Field( - # None, description="The reasoning summary level to use when generating text reasoning models" - # ) - - -class OpenAIModel(Model): - provider: Literal["openai"] = Field("openai", description="The provider of the model.") - temperature: float = Field(0.7, description="The temperature of the model.") - reasoning: OpenAIReasoning = Field(OpenAIReasoning(reasoning_effort="high"), description="The reasoning configuration for the model.") - response_format: Optional[ResponseFormatUnion] = Field(None, description="The response format for the model.") - - # TODO: implement support for these - # reasoning_summary: Optional[Literal["none", "short", "detailed"]] = Field( - # None, description="The reasoning summary level to use when generating text reasoning models" - # ) - # max_tool_calls: int = Field(10, description="The maximum number of tool calls the model can make.") - # parallel_tool_calls: bool = Field(False, description="Whether the model supports parallel tool calls.") - # top_logprobs: int = Field(10, description="The number of top logprobs to return.") - # top_p: float = Field(1.0, description="The top-p value to use when generating text.") - - def _to_legacy_config_params(self) -> dict: - return { - "temperature": self.temperature, - "max_tokens": self.max_output_tokens, - "reasoning_effort": self.reasoning.reasoning_effort, - "response_format": self.response_format, - } - - -# "thinking": { -# "type": "enabled", -# "budget_tokens": 10000 -# } - - -class AnthropicThinking(BaseModel): - type: Literal["enabled", "disabled"] = Field("enabled", description="The type of thinking to use.") - budget_tokens: int = Field(1024, description="The maximum number of tokens the model can use for extended thinking.") - - -class AnthropicModel(Model): - provider: Literal["anthropic"] = Field("anthropic", description="The provider of the model.") - temperature: float = Field(1.0, description="The temperature of the model.") - thinking: AnthropicThinking = Field( - AnthropicThinking(type="enabled", budget_tokens=1024), description="The thinking configuration for the model." - ) - - # gpt-5 models only - verbosity: Optional[Literal["low", "medium", "high"]] = Field( - None, - description="Soft control for how verbose model output should be, used for GPT-5 models.", - ) - - # TODO: implement support for these - # top_k: Optional[int] = Field(None, description="The number of top tokens to return.") - # top_p: Optional[float] = Field(None, description="The top-p value to use when generating text.") - - def _to_legacy_config_params(self) -> dict: - return { - "temperature": self.temperature, - "max_tokens": self.max_output_tokens, - "extended_thinking": self.thinking.type == "enabled", - "thinking_budget_tokens": self.thinking.budget_tokens, - "verbosity": self.verbosity, - } - - -class GeminiThinkingConfig(BaseModel): - include_thoughts: bool = Field(True, description="Whether to include thoughts in the model's response.") - thinking_budget: int = Field(1024, description="The thinking budget for the model.") - - -class GoogleAIModel(Model): - provider: Literal["google_ai"] = Field("google_ai", description="The provider of the model.") - temperature: float = Field(0.7, description="The temperature of the model.") - thinking_config: GeminiThinkingConfig = Field( - GeminiThinkingConfig(include_thoughts=True, thinking_budget=1024), description="The thinking configuration for the model." - ) - response_schema: Optional[ResponseFormatUnion] = Field(None, description="The response schema for the model.") - max_output_tokens: int = Field(65536, description="The maximum number of tokens the model can generate.") - - def _to_legacy_config_params(self) -> dict: - return { - "temperature": self.temperature, - "max_tokens": self.max_output_tokens, - "max_reasoning_tokens": self.thinking_config.thinking_budget if self.thinking_config.include_thoughts else 0, - } - - -class GoogleVertexModel(GoogleAIModel): - provider: Literal["google_vertex"] = Field("google_vertex", description="The provider of the model.") - - -class AzureModel(Model): - """Azure OpenAI model configuration (OpenAI-compatible).""" - - provider: Literal["azure"] = Field("azure", description="The provider of the model.") - temperature: float = Field(0.7, description="The temperature of the model.") - response_format: Optional[ResponseFormatUnion] = Field(None, description="The response format for the model.") - - def _to_legacy_config_params(self) -> dict: - return { - "temperature": self.temperature, - "max_tokens": self.max_output_tokens, - "response_format": self.response_format, - } - - -class XAIModel(Model): - """xAI model configuration (OpenAI-compatible).""" - - provider: Literal["xai"] = Field("xai", description="The provider of the model.") - temperature: float = Field(0.7, description="The temperature of the model.") - response_format: Optional[ResponseFormatUnion] = Field(None, description="The response format for the model.") - - def _to_legacy_config_params(self) -> dict: - return { - "temperature": self.temperature, - "max_tokens": self.max_output_tokens, - "response_format": self.response_format, - } - - -class GroqModel(Model): - """Groq model configuration (OpenAI-compatible).""" - - provider: Literal["groq"] = Field("groq", description="The provider of the model.") - temperature: float = Field(0.7, description="The temperature of the model.") - response_format: Optional[ResponseFormatUnion] = Field(None, description="The response format for the model.") - - def _to_legacy_config_params(self) -> dict: - return { - "temperature": self.temperature, - "max_tokens": self.max_output_tokens, - "response_format": self.response_format, - } - - -class DeepseekModel(Model): - """Deepseek model configuration (OpenAI-compatible).""" - - provider: Literal["deepseek"] = Field("deepseek", description="The provider of the model.") - temperature: float = Field(0.7, description="The temperature of the model.") - response_format: Optional[ResponseFormatUnion] = Field(None, description="The response format for the model.") - - def _to_legacy_config_params(self) -> dict: - return { - "temperature": self.temperature, - "max_tokens": self.max_output_tokens, - "response_format": self.response_format, - } - - -class TogetherModel(Model): - """Together AI model configuration (OpenAI-compatible).""" - - provider: Literal["together"] = Field("together", description="The provider of the model.") - temperature: float = Field(0.7, description="The temperature of the model.") - response_format: Optional[ResponseFormatUnion] = Field(None, description="The response format for the model.") - - def _to_legacy_config_params(self) -> dict: - return { - "temperature": self.temperature, - "max_tokens": self.max_output_tokens, - "response_format": self.response_format, - } - - -class BedrockModel(Model): - """AWS Bedrock model configuration.""" - - provider: Literal["bedrock"] = Field("bedrock", description="The provider of the model.") - temperature: float = Field(0.7, description="The temperature of the model.") - response_format: Optional[ResponseFormatUnion] = Field(None, description="The response format for the model.") - - def _to_legacy_config_params(self) -> dict: - return { - "temperature": self.temperature, - "max_tokens": self.max_output_tokens, - "response_format": self.response_format, - } - - -ModelSettings = Annotated[ - Union[ - OpenAIModel, - AnthropicModel, - GoogleAIModel, - GoogleVertexModel, - AzureModel, - XAIModel, - GroqModel, - DeepseekModel, - TogetherModel, - BedrockModel, - ], - Field(discriminator="provider"), -] - -class EmbeddingModelSettings(BaseModel): - model: str = Field(..., description="The name of the model.") - provider: Literal["openai", "ollama"] = Field(..., description="The provider of the model.") - diff --git a/letta/server/server.py b/letta/server/server.py index 06ef7027..00fc2031 100644 --- a/letta/server/server.py +++ b/letta/server/server.py @@ -414,31 +414,18 @@ class SyncServer(object): actor: User, ) -> AgentState: if request.llm_config is None: - additional_config_params = {} if request.model is None: if settings.default_llm_handle is None: raise LettaInvalidArgumentError("Must specify either model or llm_config in request", argument_name="model") else: - handle = settings.default_llm_handle - else: - if isinstance(request.model, str): - handle = request.model - elif isinstance(request.model, list): - raise LettaInvalidArgumentError("Multiple models are not supported yet") - else: - # EXTREMELEY HACKY, TEMPORARY WORKAROUND - handle = f"{request.model.provider}/{request.model.model}" - # TODO: figure out how to override various params - additional_config_params = request.model._to_legacy_config_params() - + request.model = settings.default_llm_handle config_params = { - "handle": handle, + "handle": request.model, "context_window_limit": request.context_window_limit, "max_tokens": request.max_tokens, "max_reasoning_tokens": request.max_reasoning_tokens, "enable_reasoner": request.enable_reasoner, } - config_params.update(additional_config_params) log_event(name="start get_cached_llm_config", attributes=config_params) request.llm_config = await self.get_cached_llm_config_async(actor=actor, **config_params) log_event(name="end get_cached_llm_config", attributes=config_params) diff --git a/tests/managers/test_agent_manager.py b/tests/managers/test_agent_manager.py index 9fe830b4..08433bc1 100644 --- a/tests/managers/test_agent_manager.py +++ b/tests/managers/test_agent_manager.py @@ -1036,7 +1036,6 @@ async def test_agent_state_schema_unchanged(server: SyncServer): from letta.schemas.group import Group from letta.schemas.llm_config import LLMConfig from letta.schemas.memory import Memory - from letta.schemas.model import EmbeddingModelSettings, ModelSettings from letta.schemas.response_format import ResponseFormatUnion from letta.schemas.source import Source from letta.schemas.tool import Tool @@ -1057,8 +1056,6 @@ async def test_agent_state_schema_unchanged(server: SyncServer): "agent_type": AgentType, # LLM information "llm_config": LLMConfig, - "model": ModelSettings, - "embedding": EmbeddingModelSettings, "embedding_config": EmbeddingConfig, "response_format": (ResponseFormatUnion, type(None)), # State fields diff --git a/tests/sdk/conftest.py b/tests/sdk/conftest.py index 6733302b..89b5f882 100644 --- a/tests/sdk/conftest.py +++ b/tests/sdk/conftest.py @@ -138,11 +138,7 @@ def create_test_module( expected_values = processed_params | processed_extra_expected for key, value in expected_values.items(): if hasattr(item, key): - if key == "model" or key == "embedding": - # NOTE: add back these tests after v1 migration - continue - print(f"item.{key}: {getattr(item, key)}") - assert custom_model_dump(getattr(item, key)) == value, f"For key {key}, expected {value}, but got {getattr(item, key)}" + assert custom_model_dump(getattr(item, key)) == value @pytest.mark.order(1) def test_retrieve(handler): @@ -276,8 +272,6 @@ def custom_model_dump(model): return model if isinstance(model, list): return [custom_model_dump(item) for item in model] - if isinstance(model, dict): - return {key: custom_model_dump(value) for key, value in model.items()} else: return model.model_dump() diff --git a/tests/test_client.py b/tests/test_client.py index 436ddb40..f7db7bf2 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -587,6 +587,37 @@ def test_agent_creation(client: Letta): client.agents.delete(agent_id=agent.id) +# -------------------------------------------------------------------------------------------------------------------- +# Agent sources +# -------------------------------------------------------------------------------------------------------------------- +def test_attach_detach_agent_source(client: Letta, agent: AgentState): + """Test that we can attach and detach a source from an agent""" + + # Create a source + source = client.sources.create( + name="test_source", + embedding="openai/text-embedding-3-small", + ) + initial_sources = client.agents.sources.list(agent_id=agent.id) + assert source.id not in [s.id for s in initial_sources] + + # Attach source + client.agents.sources.attach(agent_id=agent.id, source_id=source.id) + + # Verify source is attached + final_sources = client.agents.sources.list(agent_id=agent.id) + assert source.id in [s.id for s in final_sources] + + # Detach source + client.agents.sources.detach(agent_id=agent.id, source_id=source.id) + + # Verify source is detached + final_sources = client.agents.sources.list(agent_id=agent.id) + assert source.id not in [s.id for s in final_sources] + + client.sources.delete(source.id) + + # -------------------------------------------------------------------------------------------------------------------- # Agent Initial Message Sequence # --------------------------------------------------------------------------------------------------------------------