Skip to content
This repository was archived by the owner on May 26, 2026. It is now read-only.

feat(kora): KR-AGENT-ACTIVITY-PANEL — recent agent calls lens (stub)#114

Merged
rafe-walker merged 1 commit into
feature/phase2-upgradesfrom
feat/kora-KR-AGENT-ACTIVITY-PANEL
May 22, 2026
Merged

feat(kora): KR-AGENT-ACTIVITY-PANEL — recent agent calls lens (stub)#114
rafe-walker merged 1 commit into
feature/phase2-upgradesfrom
feat/kora-KR-AGENT-ACTIVITY-PANEL

Conversation

@rafe-walker

Copy link
Copy Markdown
Owner

Summary

Operator observability for the /mcp endpoint — a panel surfacing
recent agent-driven MCP tool calls so the operator can see which
agents (claude_pm, kora drones, etc.) are touching Kora and whether
their calls succeeded, were capability-denied, or failed outright.

Pairs with CC#3's KR-MCP-RUNTIME-SURFACE bucket — ST2 will swap the
stub /api/agent-activity/recent body for the real per-call ledger
maintained by kora_cli/listeners/mcp.py. Shape is pinned by the
new test suite so the FE shipping in this PR keeps rendering during
the cut-over.

What's in here

  • Backend stub: GET /api/agent-activity/recent returning 5
    representative calls deliberately spanning ok /
    capability_denied / denied_prod_only so the operator's first
    look surfaces what failure modes look like. stub: true keeps the
    FE banner visible.
  • AgentActivityPanel.tsx (new): stats strip (total + per-caller
    breakdown) + status filter pills + caller dropdown + expandable
    timeline rows with tool_name (mono) + caller badge + status pill
    • relative time + duration (with bar tinted warning ≥ 500ms).
  • /agent-activity route + nav entry with the Workflow icon
    (placed between /webhook-events and /mcp-clients per spec
    layout note). Activity is reserved by /operational-state so
    Workflow is the semantic next-best — "agent-driven tool calls
    flowing through Kora".
  • Dashboard card feat(KR-2 ST4): chain events + Constitution + session context — closes KR-2 #8 ("Agent Activity"): preserves
    lg:grid-cols-3 per PM preference — row 2 becomes 3+3+2 instead
    of bumping to cols-4. Headline goes destructive when
    denied > 10 OR any handler_error / timeout appears in the
    visible window (mirrors WebhookEvents dead_letter > 5 rule).

3-layer security contract

Standardizing the pattern from KR-WEBHOOK-EVENTS #109 (PM-validated
"walk-the-whole-payload guard is exactly the right shape"):

  1. result_summary is a SHORT TEXTUAL summary — never raw JSON
    payloads. Backend test pins via _JSON_LEAK regex against
    { / } / [ / ].
  2. caller_actor_kind is a LABEL — never bearer-token or
    token-hash shaped. Backend test pins via _HEX_TOKEN_PIN (≥16
    hex chars) + _BASE64_TOKEN_PIN (≥20 b64 chars) regexes, plus a
    walk-the-whole-payload sweep that catches future drift if an
    `auth_token_hash` field is ever added to a call entry or a
    session id gets stuffed into `result_summary`.
  3. TS interface enforces both contractsAgentCall declares
    the fields as plain strings with the wire contract documented
    inline; no raw_payload or auth_token field exists on the type.

Test plan

  • tests/kora_cli/test_web_server_agent_activity.py — 10 tests:
    shape, 5-call pin, status diversity, per-entry schema, JSON-leak
    guard (per-field), token-shape guards (per-field + whole-payload),
    by_caller_24h reconciliation, cron-regression sanity.
  • Full admin-panel regression: 202/202 across 19 suites.
  • pnpm tsc --noEmit clean.
  • pnpm build clean.
  • Manual smoke: load /agent-activity, exercise filters, expand
    rows, confirm STUB banner + destructive tone trigger.

Notes

  • Diag bundle: the existing /api/diag-bundle doesn't include
    heartbeat / mcp_clients / webhook_events either — keeping
    agent_activity out of it too for now, separate cleanup bucket
    re-syncs the bundle source list across all newer panels at once.
  • Convention divergence from spec: bucket spec hints
    /admin/agent-activity and pages/admin/ — using the established
    flat /agent-activity route + web/src/pages/ location to match
    every prior panel in this branch.

🤖 Generated with Claude Code

Operator observability for the /mcp endpoint — surfaces recent
agent-driven MCP tool calls (claude_pm, kora drones, etc.) so the
operator can see which agents are touching Kora and whether their
calls succeeded, were capability-denied, or failed.

Single-PR scope:
  * GET /api/agent-activity/recent stub — 5 representative calls
    deliberately spanning ok / capability_denied / denied_prod_only
    so the first look at the panel surfaces what failure modes
    actually look like. stub:true keeps the FE banner visible.
  * AgentActivityPanel.tsx — stats strip + status filter pills +
    caller dropdown + expandable timeline.
  * Dashboard card #8 (Workflow icon — Activity is reserved by
    /operational-state). Layout: keeps lg:grid-cols-3 per PM
    preference; row 2 becomes 3+3+2 instead of bumping to cols-4.
    Headline goes destructive when denied >10 OR any
    handler_error/timeout in the visible window.

3-layer security contract (standardizing the pattern from
KR-WEBHOOK-EVENTS #109):
  1. result_summary is a SHORT TEXTUAL summary — never raw JSON.
     Backend test pins via _JSON_LEAK regex against {/}/[/].
  2. caller_actor_kind is a LABEL — never bearer-token or
     token-hash shaped. Backend test pins via _HEX_TOKEN_PIN
     (≥16 hex) + _BASE64_TOKEN_PIN (≥20 b64) regexes, plus a
     walk-the-whole-payload sweep that catches future drift.
  3. TS interface declares both fields as plain strings with the
     wire contract documented inline — no raw_payload or
     auth_token field exists on AgentCall.

CC#3's KR-MCP-RUNTIME-SURFACE ST2 swaps the stub body for the
real per-call ledger maintained by kora_cli/listeners/mcp.py.
Shape is pinned by the new test suite so the FE shipping off this
PR keeps rendering correctly during the cut-over.

Tests:
  * tests/kora_cli/test_web_server_agent_activity.py — 10 tests
    covering shape, status diversity, both security regex guards
    (per-field + whole-payload), by_caller_24h reconciliation,
    cron-regression sanity.
  * Full admin-panel regression: 202/202 across 19 suites
    (heartbeat, mcp_clients, webhook_events, agent_activity,
    health_rollup, operational_state, cost_state, boot_status,
    dr_state, sea_tickets, kora_control, runbooks, charter,
    capabilities, chain_events, diag_bundle, mcp, host_header,
    gateway_identity).
  * tsc --noEmit + vite build both clean.

Diag bundle note: the existing /api/diag-bundle doesn't include
heartbeat / mcp_clients / webhook_events either — keeping
agent_activity out of it too, separate cleanup bucket for
re-syncing the bundle source list.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@rafe-walker rafe-walker merged commit ee04cb5 into feature/phase2-upgrades May 22, 2026
@rafe-walker rafe-walker deleted the feat/kora-KR-AGENT-ACTIVITY-PANEL branch May 22, 2026 06:47
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant