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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ Packages without a separate changelog are covered by the cross-package notes bel
### Fixed

- `GET /v1/nodes` no longer fetches a workspace's entire node history to serve a default listing: `name`, `capability`, and a new `status` liveness selector are now pushed into SQL, and `status=online` returns only fresh-heartbeat live nodes. An explicit `history=true` mode adds bounded, non-truncating cursor pagination for reading full history (e.g. `--all`). `active_agents` is now flagged with `active_agents_stale` once a node is offline, so a frozen historical count is never presented as current occupancy. (Fixes [#422](https://github.com/AgentWorkforce/relaycast/issues/422))
- Keyed agent session events now survive lost responses without duplicate events, while conflicting key reuse returns a typed error. A `status.*` event's status mutation and durable completion marker are applied atomically so retries cannot leave a stale agent row behind a successful response.
- Migration `0056_session_event_status_completion.sql` reconciles pre-existing keyed status events without fabricating completion, recovering only rows proven older than the event and conservatively preserving rows touched by later status or liveness writers.

## [8.8.0] - 2026-09-10

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -976,7 +976,7 @@ POST /v1/actions Register an action (agent-to-agent RPC)
POST /v1/actions/:name/invoke Invoke an action (workspace-scoped / global alias)
POST /v1/nodes/:node/actions/:name/invoke Invoke a node-addressed action
DELETE /v1/nodes/:node/providers/:name Remove a node provider
POST /v1/agents/:name/events Emit an agent session event
POST /v1/agents/:name/events Emit an agent session event (optional Idempotency-Key replays identical retries; status.changed requires payload.status)
POST /v1/directory/agents Publish an agent to the directory
GET /v1/directory/search Search the agent directory
POST /v1/route Skill-based agent routing
Expand Down
45 changes: 42 additions & 3 deletions openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5531,8 +5531,10 @@ paths:
post:
summary: Emit agent session event
description: >
Record a session event for an agent (e.g. `status.active`, `status.idle`). An agent token
may only post events for itself; a workspace key may post for any agent.
Record a session event for an agent (e.g. `status.active`, `status.idle`). For
`status.changed`, `payload.status` is required and accepts `active`, `idle`, `blocked`,
`waiting`, `offline`, or the legacy alias `online`. An agent token may only post events
for itself; a workspace key may post for any agent.
tags:
- Agents
security:
Expand All @@ -5544,6 +5546,16 @@ paths:
required: true
schema:
type: string
- name: Idempotency-Key
in: header
required: false
description: >-
Stable caller-generated key for retries. Within one workspace and agent, an identical
request replays the original event (with `Idempotency-Replayed: true`) instead of
appending another event. Reusing a key with a different payload returns 409.
Comment thread
khaliqgant marked this conversation as resolved.
schema:
type: string
maxLength: 255
requestBody:
required: true
content:
Expand All @@ -5559,11 +5571,38 @@ paths:
type: object
responses:
'201':
description: Event recorded
description: Event recorded, or idempotently replayed for a repeated `Idempotency-Key`
headers:
Idempotency-Replayed:
description: Set to `true` when the original event is replayed.
schema:
type: string
enum: ['true']
content:
application/json:
schema:
$ref: '#/components/schemas/SuccessResponse'
'400':
description: Invalid Idempotency-Key
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'409':
description: Idempotency-Key was reused with a different payload
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'503':
description: >
`idempotency_unavailable` — the durable event identity claim could not be
confirmed after a storage conflict. Retry the same logical request with the
same Idempotency-Key; do not mint a replacement key.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
get:
summary: List agent session events
description: List recorded session events for an agent. Observer tokens require `activity:read`; `agent_ids` and `created_after` filters apply.
Expand Down
2 changes: 2 additions & 0 deletions packages/engine/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ and this project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.ht
### Fixed

- `listNodes`/`GET /v1/nodes` push `name`, `capability`, and a new `status` (`online`/`offline`) liveness selector into SQL instead of fetching the whole workspace roster and filtering in JS. `history=true` adds a bounded, non-truncating cursor pagination contract (`{ nodes, next_cursor }`, paged via `cursor`/`limit`, capped at 500/page) for explicit full-history reads. Without `history`, the response stays the legacy bare array. Roster entries add `active_agents_stale` (true once a node is offline) so `active_agents` is never read back as authoritative current occupancy. Added `idx_nodes_status_heartbeat` to keep the live-selection query indexed. An observer token's authorized `active_agents` count is computed with bounded, JSON-array-bound SQL joins instead of one `inArray`/`IN (...)` bind per visible node id, keeping every roster query under D1's 100-parameter limit regardless of page size or history/legacy path.
- `POST /v1/agents/:name/events` durably replays identical `Idempotency-Key` retries and rejects conflicting payload reuse. Status mutations and their completion markers are applied atomically, so an interrupted status retry can finish without returning success against a stale agent row.
- Migration `0056_session_event_status_completion.sql` reconciles pre-existing keyed status events without fabricating completion, recovering only rows proven older than the event and conservatively preserving rows touched by later status or liveness writers.

## [8.8.0] - 2026-09-10

Expand Down
Loading
Loading