feat: GET /agent/status + idempotent POST same-state #22

Merged
hzhang merged 2 commits from feat/get-agent-status into main 2026-05-22 21:59:10 +00:00
Contributor

Two-in-one cleanup for the calendar agent-status endpoint:

  1. NEW GET /calendar/agent/status — read-only status query, no side effects. Used by Fabric.OpenclawPlugin's triage on_call gate so it can check whether the on-duty agent is currently on_call without flipping their state. Returns {agent_id, status} or 404. Previously the only verb was POST (for transitions), so plugin's getAgentStatus GET silently 405'd in HF.OpenclawPlugin too.

  2. POST /agent/status same-state → 200 no_change=true + state-machine violations → 409 with the real error message instead of 500. Was 500 on busy → busy because _assert_current(IDLE) raised AgentStatusError which wasn't caught.

Verified in sim: idempotent same-state returns {ok, no_change:true} HTTP 200; bad transition returns {detail:"Agent X is on_call; expected one of [idle]"} HTTP 409.

🤖 Generated with Claude Code

Two-in-one cleanup for the calendar agent-status endpoint: 1. **NEW GET `/calendar/agent/status`** — read-only status query, no side effects. Used by Fabric.OpenclawPlugin's triage on_call gate so it can check whether the on-duty agent is currently `on_call` without flipping their state. Returns `{agent_id, status}` or 404. Previously the only verb was POST (for transitions), so plugin's `getAgentStatus` GET silently 405'd in HF.OpenclawPlugin too. 2. **POST `/agent/status` same-state → 200 no_change=true** + state-machine violations → 409 with the real error message instead of 500. Was 500 on `busy → busy` because `_assert_current(IDLE)` raised `AgentStatusError` which wasn't caught. Verified in sim: idempotent same-state returns `{ok, no_change:true}` HTTP 200; bad transition returns `{detail:"Agent X is on_call; expected one of [idle]"}` HTTP 409. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
hzhang added 2 commits 2026-05-22 21:59:07 +00:00
Previously only POST /agent/status existed (for state transitions).
Fabric.OpenclawPlugin's triage on-call gate needs to check whether
the on-duty agent is currently on_call without flipping their state —
so the wake decision is read-only. GET returns {agent_id, status},
404 if unknown.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Same-state transition was 500 (transition_to_busy asserts current=IDLE).
Now: short-circuit identical target → 200 no_change=true. Any other
state-machine violation surfaces as 409 with the actual error message
instead of generic 500.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
hzhang merged commit efe262e85b into main 2026-05-22 21:59:10 +00:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: zhi/HarborForge.Backend#22