Skip to content

bug(streaming-ui): sub-agent orchestrator:complete fires parent cost handler mid-turn, showing wrong Turn/Session valuesΒ #290

@kenotron

Description

@kenotron

Repo: amplifier-module-hooks-streaming-ui
File: amplifier_module_hooks_streaming_ui/__init__.py β€” _make_cost_handler()

Evidence

From a real session, a πŸ’° line appears mid-turn immediately after a sub-agent finishes β€” before the parent turn is done:

β”” Input: 12,530 (64% cached) | Output: 145 | Total: 12,675 | Cost: $0.00711955
πŸ’° Turn: $0.05 | Session: $0.05          ← spurious! sub-agent's orchestrator:complete
βœ… Tool result: delegate                    ← parent turn still in progress here
  ...
β”” Input: 93,759 (93% cached) | Output: 114 | Total: 93,873 | Cost: $0.08
πŸ’° Turn: $0.38 | Session: $2.00          ← actual end-of-turn line

Two πŸ’° lines appear per user turn when sub-agents are involved.

Root cause

Sub-agent orchestrator:complete events propagate up through the hook bus to the parent coordinator's hooks. The _on_orchestrator_complete handler registered by _make_cost_handler does not check whether the event came from a sub-session or the root session.

Secondary effect: The mid-turn firing updates state["prev_total"] to a wrong intermediate value (the parent's costs at that point, before bridge_child_cost has registered the sub-agent's costs). This corrupts the turn delta calculation for the real end-of-turn line.

The Turn: $0.05 shown mid-turn is actually the parent Opus LLM call cost (the initial call that decided to delegate) β€” not the sub-agent's haiku costs (~$0.027). This looks like cost doubling to the user.

Fix (already applied on feat/m0-cost-management)

Filter sub-session events at the top of the handler using the _ in session_id that marks sub-sessions (e.g. abc-def_foundation-file-ops):

async def _on_orchestrator_complete(event: str, data: dict):
    session_id = data.get("session_id")
    if session_id and "_" in session_id:
        return HookResult(action="continue")  # sub-session, skip
    # ... rest of handler

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions