Shub/let 6339 add endpoint for counting non hidden agents [LET-6339] (#6406)

* feat: add hidden agent count

* feat: add hidden agent count

* chore; hiddne agents

---------

Co-authored-by: Shubham Naik <shub@memgpt.ai>
This commit is contained in:
Shubham Naik
2025-11-26 11:18:12 -08:00
committed by Caren Thomas
parent 96ed4791ea
commit 2ee1ff50dd
3 changed files with 218 additions and 1 deletions

View File

@@ -10034,6 +10034,51 @@
}
}
},
"/v1/_internal_agents/count": {
"get": {
"tags": ["_internal_agents"],
"summary": "Count Agents",
"description": "Get the total number of agents for a user, with option to exclude hidden agents.",
"operationId": "count_internal_agents",
"parameters": [
{
"name": "exclude_hidden",
"in": "query",
"required": false,
"schema": {
"type": "boolean",
"description": "If True, excludes hidden agents from the count. If False, includes all agents.",
"default": true,
"title": "Exclude Hidden"
},
"description": "If True, excludes hidden agents from the count. If False, includes all agents."
}
],
"responses": {
"200": {
"description": "Successful Response",
"content": {
"application/json": {
"schema": {
"type": "integer",
"title": "Response Count Internal Agents"
}
}
}
},
"422": {
"description": "Validation Error",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPValidationError"
}
}
}
}
}
}
},
"/v1/_internal_agents/{agent_id}/core-memory/blocks/{block_label}": {
"patch": {
"tags": ["_internal_agents"],

View File

@@ -1,4 +1,4 @@
from fastapi import APIRouter, Body, Depends
from fastapi import APIRouter, Body, Depends, Query
from letta.schemas.block import Block, BlockUpdate
from letta.server.rest_api.dependencies import HeaderParams, get_headers, get_letta_server
@@ -8,6 +8,28 @@ from letta.validators import AgentId
router = APIRouter(prefix="/_internal_agents", tags=["_internal_agents"])
@router.get("/count", response_model=int, operation_id="count_internal_agents")
async def count_agents(
exclude_hidden: bool = Query(True, description="If True, excludes hidden agents from the count. If False, includes all agents."),
server: "SyncServer" = Depends(get_letta_server),
headers: HeaderParams = Depends(get_headers),
):
"""
Get the total number of agents for a user, with option to exclude hidden agents.
"""
actor = await server.user_manager.get_actor_or_default_async(actor_id=headers.actor_id)
# When exclude_hidden=True, we want show_hidden_agents=False
# When exclude_hidden=False, we want show_hidden_agents=True
show_hidden_agents = not exclude_hidden
# Always use count_agents_async to ensure proper filtering
return await server.agent_manager.count_agents_async(
actor=actor,
show_hidden_agents=show_hidden_agents,
)
@router.patch("/{agent_id}/core-memory/blocks/{block_label}", response_model=Block, operation_id="modify_internal_core_memory_block")
async def modify_block_for_agent(
block_label: str,

View File

@@ -0,0 +1,150 @@
import os
from typing import List
import httpx
import pytest
from letta_client import Letta
from letta.schemas.agent import AgentState
@pytest.fixture(scope="function")
def test_agents(client: Letta) -> List[AgentState]:
"""
Creates test agents - some hidden, some not hidden.
Cleans them up after the test.
"""
agents = []
# Create 3 non-hidden agents
for i in range(3):
agent = client.agents.create(
name=f"test_agent_visible_{i}",
tags=["test", "visible"],
model="openai/gpt-4o-mini",
embedding="openai/text-embedding-3-small",
)
agents.append(agent)
# Create 2 hidden agents
for i in range(2):
# Create agent as hidden using direct HTTP call (SDK might not support hidden parameter yet)
response = httpx.post(
f"{client._client._base_url}/v1/agents/",
json={
"name": f"test_agent_hidden_{i}",
"tags": ["test", "hidden"],
"model": "openai/gpt-4o-mini",
"embedding": "openai/text-embedding-3-small",
"hidden": True,
},
headers=client._client._headers,
timeout=10.0,
)
response.raise_for_status()
agent_data = response.json()
# Create a simple AgentState-like object for tracking
class SimpleAgent:
def __init__(self, id):
self.id = id
agents.append(SimpleAgent(agent_data["id"]))
yield agents
# Cleanup
for agent in agents:
try:
client.agents.delete(agent.id)
except:
pass
def test_internal_agents_count_exclude_hidden(client: Letta, test_agents: List[AgentState]):
"""
Test that the internal agents count endpoint correctly excludes hidden agents
when exclude_hidden=True (default).
"""
# Make a request to the internal endpoint
# Note: We need to use the raw HTTP client since the SDK might not have this endpoint
response = httpx.get(
f"{client._client._base_url}/v1/_internal_agents/count",
params={"exclude_hidden": True},
headers=client._client._headers,
timeout=10.0,
)
assert response.status_code == 200
count = response.json()
# Should count at least the 3 visible agents we created
# (there might be other agents in the system)
assert isinstance(count, int)
assert count >= 3
# Get the total count with hidden agents included
response_with_hidden = httpx.get(
f"{client._client._base_url}/v1/_internal_agents/count",
params={"exclude_hidden": False},
headers=client._client._headers,
timeout=10.0,
)
assert response_with_hidden.status_code == 200
count_with_hidden = response_with_hidden.json()
# The count with hidden should be at least 2 more than without hidden
assert count_with_hidden >= count + 2
def test_internal_agents_count_include_all(client: Letta, test_agents: List[AgentState]):
"""
Test that the internal agents count endpoint correctly includes all agents
when exclude_hidden=False.
"""
response = httpx.get(
f"{client._client._base_url}/v1/_internal_agents/count",
params={"exclude_hidden": False},
headers=client._client._headers,
timeout=10.0,
)
assert response.status_code == 200
count = response.json()
# Should count at least all 5 agents we created (3 visible + 2 hidden)
assert isinstance(count, int)
assert count >= 5
def test_internal_agents_count_default_behavior(client: Letta, test_agents: List[AgentState]):
"""
Test that the default behavior (exclude_hidden=True) works correctly.
"""
# Call without specifying exclude_hidden (should default to True)
response = httpx.get(
f"{client._client._base_url}/v1/_internal_agents/count",
headers=client._client._headers,
timeout=10.0,
)
assert response.status_code == 200
count = response.json()
# Should count at least the 3 visible agents we created
assert isinstance(count, int)
assert count >= 3
# This should be the same as explicitly setting exclude_hidden=True
response_explicit = httpx.get(
f"{client._client._base_url}/v1/_internal_agents/count",
params={"exclude_hidden": True},
headers=client._client._headers,
timeout=10.0,
)
count_explicit = response_explicit.json()
# The two counts should be equal
assert count == count_explicit