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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions