Core Concepts
You’ll learn the core mental model behind Opswald: how traces, spans, and decisions work together to give you full visibility into your AI agents.
Traces
A trace represents a single execution of your AI agent — one user request, one agent run, one complete workflow.
with opswald.trace('customer-support-run') as t: # Everything inside this block belongs to one trace ...Traces have:
- A name to identify what the agent was doing
- A start time and end time
- A collection of spans (the individual steps)
- Metadata you attach (user ID, session ID, etc.)
Spans
A span is a single step inside a trace. Every LLM call, tool invocation, or custom operation is a span.
with opswald.span('generate-reply', kind='llm_call', provider='openai', model='gpt-4o') as s: s.set_input({'messages': [...]}) result = openai.chat.completions.create(...) s.set_output({'response': result.choices[0].message.content}) s.set_tokens(input_tokens=150, output_tokens=89)Span Kinds
| Kind | What it captures |
|---|---|
llm_call | LLM API calls (OpenAI, Anthropic, etc.) |
tool_call | Tool/function invocations |
error | Error events and exceptions |
custom | Any custom operation you want to track |
Nesting
Spans nest inside each other to show the call hierarchy:
with opswald.trace('agent-run') as t: with opswald.span('step-1', kind='llm_call', provider='openai', model='gpt-4o') as s1: # This span is a child of the trace with opswald.span('sub-step', kind='tool_call') as s2: # This span is a child of step-1 ...This creates a tree structure visible in the dashboard, showing exactly how your agent’s execution flowed.
Decisions
When your agent chooses between multiple paths — which tool to call, how to respond, whether to escalate — that’s a decision. Opswald captures these decision points so you can see:
- What options the agent considered
- Which option it chose
- What context led to that choice
Decisions appear as branching points in the Decision Graph.
Tool Calls
Tool calls are spans with kind='tool_call'. They represent your agent invoking external tools — search APIs, databases, calculators, or any function the agent can call.
with opswald.span('search-docs', kind='tool_call') as s: s.set_input({'query': 'refund policy', 'tool': 'vector_search'}) results = vector_db.search('refund policy') s.set_output({'results': results, 'count': len(results)})How They Fit Together
Trace: "customer-support-run"├── Span: "classify-intent" (llm_call)│ └── Decision: route to "refund" handler├── Span: "lookup-policy" (tool_call)├── Span: "generate-reply" (llm_call)└── Span: "send-response" (custom)Every trace tells a story. Opswald helps you read it.
Next Steps
- Traces Overview — Deep dive into traces
- Spans Deep Dive — Everything about span types and lifecycle
- Decision Graph — Visualize agent decisions