Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions dispatch_cli/mcp/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
EventTraceResponse,
GetScheduleRequest,
GetScheduleResponse,
ListLongTermMemoriesResponse,
ListSchedulesRequest,
ListSchedulesResponse,
RebootAgentResponse,
Expand Down Expand Up @@ -270,6 +271,16 @@ def get_invocation_history(
resp.raise_for_status()
return resp.json()

# Memory Operations
def list_long_term_memories(
self, agent_name: str, namespace: str
) -> ListLongTermMemoriesResponse:
"""List all long-term memories for an agent."""
url = self._namespaced_url(f"/memory/long-term/agent/{agent_name}", namespace)
resp = self.client.get(url)
resp.raise_for_status()
return ListLongTermMemoriesResponse.model_validate(resp.json())

# Async Invoke Operations (for MCP tools that need non-blocking behavior)
async def invoke_function_async(
self,
Expand Down
20 changes: 20 additions & 0 deletions dispatch_cli/mcp/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,3 +225,23 @@ class EventTraceResponse(BaseModel):
description="Tree-structured events with invocation enrichment"
)
llm_summary: dict[str, Any] | None = None


# Memory Models


class MemoryEntry(BaseModel):
"""A single long-term memory entry."""

mem_key: str = Field(description="Memory key")
mem_value: str = Field(description="Memory value")
last_updated: str | None = Field(
default=None, description="Last update timestamp (ISO 8601)"
)


class ListLongTermMemoriesResponse(BaseModel):
"""Response from listing long-term memories."""

agent_name: str = Field(description="Agent name")
memories: list[MemoryEntry] = Field(description="List of memory entries")
35 changes: 34 additions & 1 deletion dispatch_cli/mcp/operator/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
EventTraceResponse,
GetScheduleRequest,
GetScheduleResponse,
ListLongTermMemoriesResponse,
ListSchedulesRequest,
ListSchedulesResponse,
RebootAgentResponse,
Expand Down Expand Up @@ -537,6 +538,15 @@ class ReadLocalAgentLogsResponse(BaseModel):
total_lines: int = Field(description="Total number of lines retrieved")


class ListLongTermMemoriesRequest(BaseModel):
"""Request payload for listing long-term memories."""

agent_name: str = Field(description="Agent name")
namespace: str = Field(
description="Namespace the agent belongs to. Use list_namespaces to discover valid namespaces."
)


# Helper functions for testable core logic


Expand Down Expand Up @@ -805,13 +815,19 @@ async def my_function(payload: MyInput) -> MyOutput:
# Retrieve data
value = await memory.long_term.get(mem_key="user_prefs")

# List all memories for the agent
all_memories = await memory.long_term.list()

# Delete data
await memory.long_term.delete(mem_key="user_prefs")

# Override agent_name if needed (e.g., reading another agent's data)
value = await memory.long_term.get(mem_key="user_prefs", agent_name="other-agent")
all_memories = await memory.long_term.list(agent_name="other-agent")
```

You can also use the `list_long_term_memories` MCP tool to inspect an agent's memories.

### Short-term Memory (Session Store)
```python
# Store session data
Expand Down Expand Up @@ -1421,6 +1437,23 @@ async def get_invocation_status(
completed_at=result.get("completed_at"),
)

@mcp.tool()
async def list_long_term_memories(
request: ListLongTermMemoriesRequest,
) -> ListLongTermMemoriesResponse:
"""List all long-term memories for an agent.

Returns all key-value pairs stored in the agent's long-term memory.

Args:
request: ListLongTermMemoriesRequest with agent_name and namespace

Returns:
ListLongTermMemoriesResponse with agent_name and list of memory entries
"""
ns = _get_namespace(request.namespace)
return client.list_long_term_memories(request.agent_name, namespace=ns)

@mcp.tool()
async def start_local_agent_dev(
request: StartLocalAgentDevRequest,
Expand Down Expand Up @@ -2196,7 +2229,7 @@ async def submit_feedback(
"""
async_client = await client._get_async_client()
response = await async_client.post(
client._global_url("/api/unstable/feedback/"),
client._global_url("/feedback/"),
json=request.model_dump(),
)
response.raise_for_status()
Expand Down
5 changes: 4 additions & 1 deletion dispatch_cli/router/static/components.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dispatch_cli/router/static/components.js.map

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "dispatch-cli"
version = "0.6.0"
version = "0.7.1"
description = ""
authors = [
{name = "Diamond Bishop", email = "diamond.bishop@datadoghq.com"},
Expand Down Expand Up @@ -34,7 +34,7 @@ dependencies = [
]

[tool.uv.sources]
dispatch_agents = {git = "https://github.com/datadog-labs/dispatch_agents_sdk", tag = "v0.9.0"}
dispatch_agents = {git = "https://github.com/datadog-labs/dispatch_agents_sdk", tag = "v0.10.0"}

[dependency-groups]
dev = [
Expand Down
26 changes: 13 additions & 13 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading