Problem
Workspace agent metadata (the coder_agent metadata blocks that produce CPU usage, and so on) can only be read by opening a stream:
GET /api/v2/workspaceagents/{workspaceagent}/watch-metadata (SSE)
GET /api/v2/workspaceagents/{workspaceagent}/watch-metadata-ws (WebSocket)
There is no plain GET, and metadata is not embedded in any existing response: neither codersdk.WorkspaceAgent (GET /workspaceagents/{id}) nor the agents inside codersdk.Workspace.LatestBuild.Resources carry it. codersdk exposes only WatchWorkspaceAgentMetadata, which returns channels.
That makes metadata awkward for any non-UI consumer that wants a point-in-time read across many workspaces. A daemon that periodically inspects N workspaces has to open (and tear down) N streams per sweep, purely to read state the server already has in the database.
Concrete use case
We use an agent metadata item as a status channel: a workspace publishes what its long-running process is doing (working, serving, done <code>), and an external service polls that to decide when the workspace can be deleted. Metadata is a good fit because it reports continuously and distinguishes "never started" from "finished". The streaming-only read path is the only friction.
Proposal
Add a non-streaming read:
GET /api/v2/workspaceagents/{workspaceagent}/metadata
-> []codersdk.WorkspaceAgentMetadata
with a matching codersdk method, for example:
func (c *Client) WorkspaceAgentMetadata(ctx context.Context, agentID uuid.UUID) ([]WorkspaceAgentMetadata, error)
The response body would be identical to the first payload the watch endpoints already send. watchWorkspaceAgentMetadata builds exactly this from Database.GetWorkspaceAgentMetadata before entering its send loop, so the handler is mostly a matter of returning that initial state and stopping.
Optionally, a keys query parameter to fetch a subset, mirroring GetWorkspaceAgentMetadataParams.Keys.
Workaround today
Open the watch stream, read the first payload (the server sends current state immediately on connect), then cancel. It works, but every read costs a stream setup and teardown, and callers must be careful to distinguish "cancelled after reading" from a real error.
Filed by Coder Agents on behalf of @Emyrk.
Problem
Workspace agent metadata (the
coder_agentmetadatablocks that produce CPU usage, and so on) can only be read by opening a stream:GET /api/v2/workspaceagents/{workspaceagent}/watch-metadata(SSE)GET /api/v2/workspaceagents/{workspaceagent}/watch-metadata-ws(WebSocket)There is no plain
GET, and metadata is not embedded in any existing response: neithercodersdk.WorkspaceAgent(GET /workspaceagents/{id}) nor the agents insidecodersdk.Workspace.LatestBuild.Resourcescarry it.codersdkexposes onlyWatchWorkspaceAgentMetadata, which returns channels.That makes metadata awkward for any non-UI consumer that wants a point-in-time read across many workspaces. A daemon that periodically inspects N workspaces has to open (and tear down) N streams per sweep, purely to read state the server already has in the database.
Concrete use case
We use an agent metadata item as a status channel: a workspace publishes what its long-running process is doing (
working,serving,done <code>), and an external service polls that to decide when the workspace can be deleted. Metadata is a good fit because it reports continuously and distinguishes "never started" from "finished". The streaming-only read path is the only friction.Proposal
Add a non-streaming read:
with a matching
codersdkmethod, for example:The response body would be identical to the first payload the watch endpoints already send.
watchWorkspaceAgentMetadatabuilds exactly this fromDatabase.GetWorkspaceAgentMetadatabefore entering its send loop, so the handler is mostly a matter of returning that initial state and stopping.Optionally, a
keysquery parameter to fetch a subset, mirroringGetWorkspaceAgentMetadataParams.Keys.Workaround today
Open the watch stream, read the first payload (the server sends current state immediately on connect), then cancel. It works, but every read costs a stream setup and teardown, and callers must be careful to distinguish "cancelled after reading" from a real error.
Filed by Coder Agents on behalf of @Emyrk.