fix(calendar): read agent status by agent_id alone (cross-agent gate)

GET /calendar/agent/status went through _require_agent, which filters by
agent_id AND claw_identifier. But this is a cross-agent READ — the caller asks
about a DIFFERENT agent and passes its OWN X-Claw-Identifier (the CLI falls
back to hostname). So the query required target.claw == caller's-hostname and
spuriously 404'd whenever they differed: `hf agent status-of <other>` worked
only when the caller's host happened to equal the target's registered claw
(e.g. fine on the node whose hostname matched, 404 everywhere else). This broke
the delegate-task / on-call-handoff status gates.

Look the agent up by agent_id alone for the read; accept but ignore
X-Claw-Identifier (now optional). The POST (write own status) still identifies
the caller by agent_id + claw via _require_agent.

Verified: `hf agent status-of <agent>` now returns {agent_id, status} from any
caller/host; unknown agent still 404s.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
h z
2026-06-11 09:29:52 +01:00
parent 52d71635bc
commit 778a6c392a

View File

@@ -568,17 +568,28 @@ def agent_update_virtual_slot(
)
def get_agent_status(
agent_id: str = Query(..., description="Target agent_id"),
x_claw_identifier: str = Header(..., alias="X-Claw-Identifier"),
x_claw_identifier: str = Header(None, alias="X-Claw-Identifier"),
db: Session = Depends(get_db),
):
"""Return `{agent_id, status}` so callers (Fabric.OpenclawPlugin's
triage on-call gate, etc.) can decide whether the agent is currently
eligible without flipping their state.
triage on-call gate, delegate-task / on-call-handoff status gates, etc.)
can decide whether the agent is currently eligible without flipping
their state.
This is a cross-agent READ: look the agent up by `agent_id` ALONE. We do
NOT scope by the caller's claw_identifier — the caller is asking about a
DIFFERENT agent, and the X-Claw-Identifier the CLI sends is the caller's
own (often just a hostname fallback), so requiring target.claw == that
header spuriously 404'd whenever the two claws differed (e.g. any
`hf agent status-of` from a host whose hostname != the target's
registered claw). The header is accepted but ignored.
No-op for unknown agents — returns 404 with `{detail: 'Agent not
found'}` so the caller can decide whether to fail-open or fail-closed.
"""
agent = _require_agent(db, agent_id, x_claw_identifier)
agent = db.query(Agent).filter(Agent.agent_id == agent_id).first()
if agent is None:
raise HTTPException(status_code=404, detail="Agent not found")
return {
"agent_id": agent.agent_id,
"status": agent.status.value if hasattr(agent.status, 'value') else str(agent.status),