AgentOpsAgentOps 0.4.21 · Python 3.10+
0%
1
Curious builder0 XP earned · 300 to level 2
0 daysFinish a lesson to begin
Badge collection0 of 6 unlocked
11 small wins to finish your pathNext lesson

Span kinds: agents, operations and tools

Decorators mark what each part of your code is: @agent on a class, @operation or @task on its methods, @tool on functions it calls. Each call becomes a nested span.

Examplekinds.py, after the setup lines from lesson 2
from agentops.sdk.decorators import agent, operation, tool

ORDERS = {"A-1001": "shipped on 12 March"}


@tool(cost=0.002)
def lookup_order(order_id):
    return ORDERS.get(order_id, "no such order")


@agent(name="desk")
class Desk:
    @operation
    def answer(self, ticket):
        return f"Order status: {lookup_order('A-1001')}"


@agentops.trace(name="support-ticket")
def handle(ticket):
    return Desk().answer(ticket)
Examplekinds.py, after the setup lines from lesson 2, continued
print(handle("Where is my order A-1001?"))
local_collector.flush()
local_collector.tree()
Example
python kinds.py

The trace holds four spans, nested by which function called which. Creating Desk() started the agent span; answer, an @operation, ran inside it, and lookup_order inside that. The span names are the function or agent name plus the kind. AgentOps records @operation as a task span; the two decorators are the same.

Example
python attributes.py

Each span carries the function's input and output as JSON: task.input, tool.output and so on. The cost given to @tool is recorded as gen_ai.usage.total_cost, not shown here, so a dashboard can add up what tools cost per trace.

DecoratorSpan kindUse it on
@agentops.tracesessionThe function that handles one request
@agentagentA class that does the work
@operation, @tasktaskA step of the agent
@workflowworkflowA group of steps
@tooltoolA call to something outside, with an optional cost
@guardrailguardrailA check on input or output, lesson 8
Try it yourself
  • Add a @workflow method that calls answer twice and print the tree.
  • Call lookup_order outside any trace and see what the collector gets.
  • Pass name="order-lookup" to @tool.

Slow is fine. Stopping is the only problem.