Agno

Trace Agno agents, teams, and workflows with Neatlogs (Python).

Wrap an Agno Agent, Team, or Workflow with neatlogs.wrap() and its runs — model calls and tool calls — are captured.

Prerequisites

pip install -U "neatlogs[agno]" agno

Usage

import os
import neatlogs

neatlogs.init(api_key=os.environ["NEATLOGS_API_KEY"], workflow_name="agno-demo")

from agno.agent import Agent
from agno.models.openai import OpenAIChat

agent = neatlogs.wrap(Agent(model=OpenAIChat(id="gpt-4o")))

print(agent.run("In one sentence, what is Agno?").content)

neatlogs.flush()
neatlogs.shutdown()

wrap() accepts an Agent, a Team, or a Workflow. An Agent or Team run becomes an AGENT trace root; a Workflow run becomes a WORKFLOW root. Either way it's created automatically, with nested LLM and TOOL spans — no manual wrapper needed; add one only to group several runs into a single trace.

Sessions & end-user

Say you call the same Agno agent a handful of times over one back-and-forth and want those runs stitched under a single session, credited to the person you're serving — wrap each turn in identify() and you're done. Since Agno opens its own root, identify() simply stamps the session and end-user onto whatever agent, team, or workflow runs inside the block:

# Same session_id every turn → one session; end_user_id attributes it to your user.
with neatlogs.identify(session_id=f"conv_{conversation_id}", end_user_id=user_id):
    response = agent.run(message)

Not every run is a conversation. A standalone workflow — a one-off job, not a back-and-forth — is a single trace with no turns to group. You still attribute it to the customer it ran for, sourcing the id and any metadata from your own user or request object:

Warning

A standalone workflow must not carry a session_id. Omit it entirely — Neatlogs sets session_id = trace_id, so the run is its own single-turn session, fully attributed to the end-user. Reusing one session_id across unrelated runs wrongly folds them into a single multi-turn conversation.

def summarize(document, user):
    # Standalone workflow — attribute to the end-user; do NOT pass session_id.
    with neatlogs.identify(
        end_user_id=str(user.id),
        end_user_metadata={"plan": user.plan},
    ):
        return agent.run(f"Summarize:\n{document}").content

Sessions and End-User Identity walk through the whole model.

On this page

Ask Neatlogs AI

Answers from the docs

How can I help?

Ask anything about instrumenting, tracing, or the Neatlogs dashboard.