From 9cf16b2cfd1f805547baf0fe890b403d4ea29f12 Mon Sep 17 00:00:00 2001 From: Sarah Wooders Date: Tue, 5 Nov 2024 17:31:40 -0800 Subject: [PATCH] feat: add ability to list agents by `name` for REST API and python SDK (#1982) --- README.md | 2 +- letta/client/client.py | 7 ++++++- letta/server/rest_api/routers/v1/agents.py | 7 ++++++- tests/test_client.py | 4 ++++ 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6064b7a33..20e3343e0 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ **👾 Letta** is an open source framework for building stateful LLM applications. You can use Letta to build **stateful agents** with advanced reasoning capabilities and transparent long-term memory. The Letta framework is white box and model-agnostic. - + [![Discord](https://img.shields.io/discord/1161736243340640419?label=Discord&logo=discord&logoColor=5865F2&style=flat-square&color=5865F2)](https://discord.gg/letta) [![Twitter Follow](https://img.shields.io/badge/Follow-%40Letta__AI-1DA1F2?style=flat-square&logo=x&logoColor=white)](https://twitter.com/Letta_AI) [![arxiv 2310.08560](https://img.shields.io/badge/Research-2310.08560-B31B1B?logo=arxiv&style=flat-square)](https://arxiv.org/abs/2310.08560) diff --git a/letta/client/client.py b/letta/client/client.py index b8b0c70bf..128ab4de0 100644 --- a/letta/client/client.py +++ b/letta/client/client.py @@ -612,7 +612,12 @@ class RESTClient(AbstractClient): agent_id (str): ID of the agent """ # TODO: implement this - raise NotImplementedError + response = requests.get(f"{self.base_url}/{self.api_prefix}/agents", headers=self.headers, params={"name": agent_name}) + agents = [AgentState(**agent) for agent in response.json()] + if len(agents) == 0: + return None + assert len(agents) == 1, f"Multiple agents with the same name: {agents}" + return agents[0].id # memory def get_in_context_memory(self, agent_id: str) -> Memory: diff --git a/letta/server/rest_api/routers/v1/agents.py b/letta/server/rest_api/routers/v1/agents.py index a30674c1d..6836d765d 100644 --- a/letta/server/rest_api/routers/v1/agents.py +++ b/letta/server/rest_api/routers/v1/agents.py @@ -40,6 +40,7 @@ router = APIRouter(prefix="/agents", tags=["agents"]) @router.get("/", response_model=List[AgentState], operation_id="list_agents") def list_agents( + name: Optional[str] = Query(None, description="Name of the agent"), server: "SyncServer" = Depends(get_letta_server), user_id: Optional[str] = Header(None, alias="user_id"), # Extract user_id from header, default to None if not present ): @@ -49,7 +50,11 @@ def list_agents( """ actor = server.get_user_or_default(user_id=user_id) - return server.list_agents(user_id=actor.id) + agents = server.list_agents(user_id=actor.id) + # TODO: move this logic to the ORM + if name: + agents = [a for a in agents if a.name == name] + return agents @router.get("/{agent_id}/context", response_model=ContextWindowOverview, operation_id="get_agent_context_window") diff --git a/tests/test_client.py b/tests/test_client.py index f1a4d090b..dda27cce2 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -103,6 +103,10 @@ def test_agent(client: Union[LocalClient, RESTClient], agent: AgentState): renamed_agent = client.get_agent(agent_id=agent.id) assert renamed_agent.name == new_name, "Agent renaming failed" + # get agent id + agent_id = client.get_agent_id(agent_name=new_name) + assert agent_id == agent.id, "Agent ID retrieval failed" + # test client.delete_agent and client.agent_exists delete_agent = client.create_agent(name="DeleteTestAgent") assert client.agent_exists(agent_id=delete_agent.id), "Agent creation failed"