Skip to content

Commit 96ddc0a

Browse files
4shubShubham Naik
andauthored
feat: add not_indexable property to agents (#3653)
Co-authored-by: Shubham Naik <[email protected]>
1 parent 30cacc3 commit 96ddc0a

File tree

5 files changed

+62
-0
lines changed

5 files changed

+62
-0
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
"""Add hidden property to agents
2+
3+
Revision ID: 15b577c62f3f
4+
Revises: 4c6c9ef0387d
5+
Create Date: 2025-07-30 13:19:15.213121
6+
7+
"""
8+
9+
from typing import Sequence, Union
10+
11+
import sqlalchemy as sa
12+
13+
from alembic import op
14+
15+
# revision identifiers, used by Alembic.
16+
revision: str = "15b577c62f3f"
17+
down_revision: Union[str, None] = "4c6c9ef0387d"
18+
branch_labels: Union[str, Sequence[str], None] = None
19+
depends_on: Union[str, Sequence[str], None] = None
20+
21+
22+
def upgrade() -> None:
23+
op.add_column("agents", sa.Column("hidden", sa.Boolean(), nullable=True))
24+
25+
# Set hidden=true for existing agents with project names starting with "templates"
26+
connection = op.get_bind()
27+
connection.execute(sa.text("UPDATE agents SET hidden = true WHERE project_id LIKE 'templates-%'"))
28+
29+
30+
def downgrade() -> None:
31+
op.drop_column("agents", "hidden")

letta/orm/agent.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ class Agent(SqlalchemyBase, OrganizationMixin, ProjectMixin, AsyncAttrs):
100100
Integer, nullable=True, doc="The per-file view window character limit for this agent."
101101
)
102102

103+
# indexing controls
104+
hidden: Mapped[Optional[bool]] = mapped_column(Boolean, nullable=True, default=None, doc="If set to True, the agent will be hidden.")
105+
103106
# relationships
104107
organization: Mapped["Organization"] = relationship("Organization", back_populates="agents", lazy="raise")
105108
tool_exec_environment_variables: Mapped[List["AgentEnvironmentVariable"]] = relationship(
@@ -210,6 +213,7 @@ def to_pydantic(self, include_relationships: Optional[Set[str]] = None) -> Pydan
210213
"timezone": self.timezone,
211214
"max_files_open": self.max_files_open,
212215
"per_file_view_window_char_limit": self.per_file_view_window_char_limit,
216+
"hidden": self.hidden,
213217
# optional field defaults
214218
"tags": [],
215219
"tools": [],
@@ -297,6 +301,7 @@ async def to_pydantic_async(self, include_relationships: Optional[Set[str]] = No
297301
"last_run_duration_ms": self.last_run_duration_ms,
298302
"max_files_open": self.max_files_open,
299303
"per_file_view_window_char_limit": self.per_file_view_window_char_limit,
304+
"hidden": self.hidden,
300305
}
301306
optional_fields = {
302307
"tags": [],

letta/schemas/agent.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,12 @@ class AgentState(OrmMetadataBase, validate_assignment=True):
122122
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.",
123123
)
124124

125+
# indexing controls
126+
hidden: Optional[bool] = Field(
127+
None,
128+
description="If set to True, the agent will be hidden.",
129+
)
130+
125131
def get_agent_env_vars_as_dict(self) -> Dict[str, str]:
126132
# Get environment variables for this agent specifically
127133
per_agent_env_vars = {}
@@ -236,6 +242,10 @@ class CreateAgent(BaseModel, validate_assignment=True): #
236242
None,
237243
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.",
238244
)
245+
hidden: Optional[bool] = Field(
246+
None,
247+
description="If set to True, the agent will be hidden.",
248+
)
239249

240250
@field_validator("name")
241251
@classmethod
@@ -338,6 +348,10 @@ class UpdateAgent(BaseModel):
338348
None,
339349
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.",
340350
)
351+
hidden: Optional[bool] = Field(
352+
None,
353+
description="If set to True, the agent will be hidden.",
354+
)
341355

342356
class Config:
343357
extra = "ignore" # Ignores extra fields

letta/server/rest_api/routers/v1/agents.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,11 @@ async def list_agents(
8686
"created_at",
8787
description="Field to sort by. Options: 'created_at' (default), 'last_run_completion'",
8888
),
89+
show_hidden_agents: bool | None = Query(
90+
False,
91+
include_in_schema=False,
92+
description="If set to True, include agents marked as hidden in the results.",
93+
),
8994
):
9095
"""
9196
List all agents associated with a given user.
@@ -115,6 +120,7 @@ async def list_agents(
115120
include_relationships=include_relationships,
116121
ascending=ascending,
117122
sort_by=sort_by,
123+
show_hidden_agents=show_hidden_agents,
118124
)
119125

120126

letta/services/agent_manager.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1034,6 +1034,7 @@ async def list_agents_async(
10341034
include_relationships: Optional[List[str]] = None,
10351035
ascending: bool = True,
10361036
sort_by: Optional[str] = "created_at",
1037+
show_hidden_agents: Optional[bool] = None,
10371038
) -> List[PydanticAgentState]:
10381039
"""
10391040
Retrieves agents with optimized filtering and optional field selection.
@@ -1055,6 +1056,7 @@ async def list_agents_async(
10551056
include_relationships (Optional[List[str]]): List of fields to load for performance optimization.
10561057
ascending (bool): Sort agents in ascending order.
10571058
sort_by (Optional[str]): Sort agents by this field.
1059+
show_hidden_agents (bool): If True, include agents marked as hidden in the results.
10581060
10591061
Returns:
10601062
List[PydanticAgentState]: The filtered list of matching agents.
@@ -1068,6 +1070,10 @@ async def list_agents_async(
10681070
query = _apply_identity_filters(query, identity_id, identifier_keys)
10691071
query = _apply_tag_filter(query, tags, match_all_tags)
10701072
query = _apply_relationship_filters(query, include_relationships)
1073+
1074+
# Apply hidden filter
1075+
if not show_hidden_agents:
1076+
query = query.where((AgentModel.hidden.is_(None)) | (AgentModel.hidden == False))
10711077
query = await _apply_pagination_async(query, before, after, session, ascending=ascending, sort_by=sort_by)
10721078

10731079
if limit:

0 commit comments

Comments
 (0)