Skip to content

setup_agno() does not instrument Agent.acontinue_run/Team.acontinue_run (agno's paused-run resume path) #764

Description

braintrust.wrappers.agno.setup_agno() patches Agent._run/_arun/_run_stream/_arun_stream and the equivalent Team methods (braintrust/integrations/agno/patchers.py), each opening a TASK-typed span that becomes the parent for the run's llm/tool spans.

It does not patch Agent.acontinue_run/Team.acontinue_run (nor the sync continue_run). These are the entrypoints agno's AG-UI interface calls from agno.os.interfaces.agui.resume.resume_paused_run() when a paused run (e.g. one blocked on an external_execution / client-side tool, such as a UI-rendering tool the frontend executes and answers) is resumed after the client answers it.

Because no TASK span is open during that resume, the model call inside acontinue_run still gets its own llm span (that patch — Model._aresponse_stream etc. — is unaffected), but with no ambient parent span, Braintrust opens it as a brand-new trace root instead of continuing the original conversation's trace. The result: every resumed paused-run turn shows up in the UI as its own disconnected "conversation," rather than as a continuation of the one the user was actually having.

Repro: any agno AgentOS app using the AG-UI interface, with a client tool that pauses the run (external_execution=True) and setup_agno() tracing enabled. Ask the agent something that triggers the client tool, resolve the tool call from the client, and diff the trace of the initial run vs. the resumed one — they land as two separate traces sharing no root span.

Suggested fix: add a wrapper for Agent.acontinue_run/Team.acontinue_run (and the sync variants) symmetric to the existing _arun/_run wrappers, opening the same kind of TASK span. That alone won't reconnect it to the original trace across the pause — the resume happens in a separate call/request with no ambient span — so instrumenting the resume path would also need some way to recover the original run's span reference. One option: persist the exported span alongside whatever agno already tracks for the paused run's continuation state (e.g. the run's own metadata, which agno already serializes and persists), so the new TASK span for the resume can be opened with parent=<that export> instead of as a fresh root.

We worked around this downstream, in application code, by hooking into agno's run-persistence path to stash the span export on the run object and reading it back when the paused run resumes. That works, but it depends on private/internal agno symbols and duplicates work setup_agno() is already positioned to do — a fix at the setup_agno() level, with access to whatever agno tracks internally for a paused/resumed run, would be the more robust place for it.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions