User request
Implement the API/proto surface needed to move Console Activity lists (Workloads / Storage / Threads) to server-side sort/filter/pagination with deterministic cursor pagination, plus updated authorization relations.
Source spec: https://github.com/agynio/architecture/blob/main/changes/2026-04-24-activity-server-side-lists.md
Specification (architecture/product)
From:
changes/2026-04-24-activity-server-side-lists.md
architecture/runners.md#listworkloads-request-shape + #listvolumes-request-shape
architecture/threads.md#listorganizationthreads-request-shape
product/console/console.md (Workloads/Storage/Threads)
Key decisions to reflect in protos:
- All three lists require deterministic cursor pagination with stable secondary sort by
id (cursor includes tie-breaker).
- Search applies only to Storage/Volumes: case-insensitive substring match on “volume name”.
- Storage status enum is canonical Runners
VolumeStatus: provisioning | active | deprovisioning | deleted | failed.
- Volume list items include
attachments[] { kind, id, name } and volume_name so Console never renders raw IDs.
- Auth model changes (handled in
agynio/authorization) require callers to hold:
can_view_workloads on org for Workloads list
can_view_volumes on org for Storage list
can_view_threads on org for Threads list (expanded to include cluster admins)
NOTE: Volume “name” mapping
Current agents.v1.Volume proto has description but no explicit name field. Console currently displays Volume.description as the human label in some views.
Until/unless a dedicated Volume.name is introduced, treat ListVolumes/Activity volume_name as:
- primary:
agents.Volume.description
- fallback:
agents.Volume.mount_path (if description is empty)
Work items
Runners API (proto/agynio/api/runners/v1/runners.proto)
- Extend
ListWorkloadsRequest to match the documented list envelope:
organization_id (required at runtime)
filter.* (agent_id_in, runner_id_in, status_in, started_after, started_before, pending_sample)
sort.* (field: started|agent|runner|status|duration; direction: asc|desc)
page_token, page_size
- Keep existing fields for backwards compatibility if needed; mark deprecated if appropriate.
- Extend
ListVolumesRequest similarly:
filter.* (status_in, runner_id_in, attached_to_kind_in, pending_sample, volume_name_substring)
sort.* (field: name|size|status|created; direction)
- Extend response item messages:
Workload: add agent_name, runner_name
Volume: add volume_name and repeated Attachment attachments
- Define
Attachment + AttachmentKind enum (agent|mcp|hook)
Threads API (proto/agynio/api/threads/v1/threads.proto)
- Add new RPC + messages per spec:
ListOrganizationThreads(ListOrganizationThreadsRequest) returns (ListOrganizationThreadsResponse)
- request includes
organization_id, filter.*, sort.*, page_token, page_size
- response includes
threads[] and next_page_token
- Participant enrichment:
- extend
Participant with nickname (string) so list responses can include @nickname.
- Keep existing
GetOrganizationThreads RPC for compatibility (Gateway currently exposes it); implementers may delegate internally.
Identity API (proto/agynio/api/identity/v1/identity.proto)
- Add a reverse/batch nickname lookup needed to enrich thread participants:
- e.g.
BatchGetNicknames / ResolveIdentityNicknames style RPC
- Input:
organization_id + identity_ids[]
- Output: repeated results
{ identity_id, nickname } (missing nicknames are omitted or returned empty; define behavior)
Gateway API surface (proto/agynio/api/gateway/v1/*.proto)
- Expose the new
Threads.ListOrganizationThreads RPC through the Gateway (likely alongside existing GetOrganizationThreads for compatibility).
Buf / codegen
- Update
buf modules as needed and ensure downstream repos can update their buf.lock + regenerate.
Acceptance
- Protos compile and are compatible with downstream regeneration.
- New/updated request/response shapes support the server-side list behaviors described in the spec, including deterministic pagination tie-breakers.
User request
Implement the API/proto surface needed to move Console Activity lists (Workloads / Storage / Threads) to server-side sort/filter/pagination with deterministic cursor pagination, plus updated authorization relations.
Source spec: https://github.com/agynio/architecture/blob/main/changes/2026-04-24-activity-server-side-lists.md
Specification (architecture/product)
From:
changes/2026-04-24-activity-server-side-lists.mdarchitecture/runners.md#listworkloads-request-shape+#listvolumes-request-shapearchitecture/threads.md#listorganizationthreads-request-shapeproduct/console/console.md(Workloads/Storage/Threads)Key decisions to reflect in protos:
id(cursor includes tie-breaker).VolumeStatus:provisioning | active | deprovisioning | deleted | failed.attachments[] { kind, id, name }andvolume_nameso Console never renders raw IDs.agynio/authorization) require callers to hold:can_view_workloadson org for Workloads listcan_view_volumeson org for Storage listcan_view_threadson org for Threads list (expanded to include cluster admins)NOTE: Volume “name” mapping
Current
agents.v1.Volumeproto hasdescriptionbut no explicitnamefield. Console currently displaysVolume.descriptionas the human label in some views.Until/unless a dedicated
Volume.nameis introduced, treatListVolumes/Activityvolume_nameas:agents.Volume.descriptionagents.Volume.mount_path(if description is empty)Work items
Runners API (
proto/agynio/api/runners/v1/runners.proto)ListWorkloadsRequestto match the documented list envelope:organization_id(required at runtime)filter.*(agent_id_in, runner_id_in, status_in, started_after, started_before, pending_sample)sort.*(field: started|agent|runner|status|duration; direction: asc|desc)page_token,page_sizeListVolumesRequestsimilarly:filter.*(status_in, runner_id_in, attached_to_kind_in, pending_sample, volume_name_substring)sort.*(field: name|size|status|created; direction)Workload: addagent_name,runner_nameVolume: addvolume_nameandrepeated Attachment attachmentsAttachment+AttachmentKindenum (agent|mcp|hook)Threads API (
proto/agynio/api/threads/v1/threads.proto)ListOrganizationThreads(ListOrganizationThreadsRequest) returns (ListOrganizationThreadsResponse)organization_id,filter.*,sort.*,page_token,page_sizethreads[]andnext_page_tokenParticipantwithnickname(string) so list responses can include@nickname.GetOrganizationThreadsRPC for compatibility (Gateway currently exposes it); implementers may delegate internally.Identity API (
proto/agynio/api/identity/v1/identity.proto)BatchGetNicknames/ResolveIdentityNicknamesstyle RPCorganization_id+identity_ids[]{ identity_id, nickname }(missing nicknames are omitted or returned empty; define behavior)Gateway API surface (
proto/agynio/api/gateway/v1/*.proto)Threads.ListOrganizationThreadsRPC through the Gateway (likely alongside existingGetOrganizationThreadsfor compatibility).Buf / codegen
bufmodules as needed and ensure downstream repos can update theirbuf.lock+ regenerate.Acceptance