Traces Reference¶
The plugin generates connected distributed traces using OpenClaw's hook-based plugin API.
Trace Structure¶
Every user message produces a trace tree:
openclaw.request (SERVER span — full message lifecycle)
├── openclaw.agent.turn (INTERNAL — LLM processing)
│ ├── gen_ai.usage.input_tokens: 4521
│ ├── gen_ai.usage.output_tokens: 892
│ ├── gen_ai.response.model: claude-opus-4-5
│ ├── tool.exec (INTERNAL — 156ms)
│ ├── tool.Read (INTERNAL — 12ms)
│ └── tool.web_fetch (INTERNAL — 1200ms)
└── openclaw.command.new (INTERNAL — if session reset)
All spans within a request share the same traceId and are linked via parent-child relationships.
Request Span¶
Created by the message_received hook. This is the root span for the entire request lifecycle.
| Field | Value |
|---|---|
| Span Name | openclaw.request |
| Kind | SERVER |
Attributes:
| Attribute | Type | Description |
|---|---|---|
openclaw.message.channel |
string | Source channel (whatsapp, telegram, discord, etc.) |
openclaw.session.key |
string | Session identifier |
openclaw.message.direction |
string | Always "inbound" |
openclaw.message.from |
string | Sender identifier |
openclaw.request.duration_ms |
int | Total request duration |
Agent Turn Span¶
Created by the before_model_resolve hook at the earliest point in the agent
run, enriched by before_prompt_build once session history is loaded, and
ended by agent_end. Child of the request span.
Prior to v0.2.0 this span was created in the legacy before_agent_start hook.
See CHANGELOG and ISI-730 for the migration details.
| Field | Value |
|---|---|
| Span Name | openclaw.agent.turn |
| Kind | INTERNAL |
Attributes:
| Attribute | Type | Description |
|---|---|---|
openclaw.agent.id |
string | Agent identifier |
openclaw.session.key |
string | Session identifier |
openclaw.prompt.chars |
int | Length of the user prompt (set by before_prompt_build) |
openclaw.session.message_count |
int | Session history size fed to the LLM (set by before_prompt_build) |
openclaw.agent.duration_ms |
int | Turn duration in milliseconds |
openclaw.agent.success |
boolean | Whether the turn completed successfully |
openclaw.agent.error |
string | Error message (if failed) |
gen_ai.usage.input_tokens |
int | Total input tokens (including cache read/write) |
gen_ai.usage.output_tokens |
int | Total output tokens |
gen_ai.response.model |
string | Actual model used (from last assistant message) |
Schema
1.3.0(ISI-1004) removedgen_ai.usage.total_tokens— compute it asgen_ai.usage.input_tokens + gen_ai.usage.output_tokens.
gen_ai.request.model on the turn span
The agent turn span no longer carries gen_ai.request.model — in
OpenClaw 2026.2+ the model has not been resolved when the span is
created (before_model_resolve fires pre-resolution). The resolved
model is recorded as gen_ai.response.model at agent_end and is
also available on openclaw.llm.call spans from the llm_input hook.
Token Counts
Token counts are summed across all assistant messages in the turn. If the agent makes multiple LLM calls (e.g., tool use loop), the totals reflect all calls combined. Cache tokens (cacheRead, cacheWrite) are included in the input token count.
Tool Execution Spans¶
Created by the tool_result_persist hook. Child of the agent turn span.
| Field | Value |
|---|---|
| Span Name | tool.<tool_name> |
| Kind | INTERNAL |
Examples: tool.exec, tool.web_fetch, tool.browser, tool.Read, tool.Write, tool.memory_search, tool.Edit
Attributes:
| Attribute | Type | Description |
|---|---|---|
openclaw.tool.name |
string | Tool name |
openclaw.tool.call_id |
string | Unique tool call identifier |
openclaw.tool.is_synthetic |
boolean | Whether the tool call is synthetic |
openclaw.tool.result_chars |
int | Total characters in result |
openclaw.tool.result_parts |
int | Number of content parts in result |
openclaw.session.key |
string | Session identifier |
openclaw.agent.id |
string | Agent identifier |
Status: OK on success, ERROR if the tool returned an error.
Command Spans¶
Created when session commands are issued.
| Span Name | Kind | Description |
|---|---|---|
openclaw.command.new |
INTERNAL | /new command |
openclaw.command.reset |
INTERNAL | /reset command |
openclaw.command.stop |
INTERNAL | /stop command |
Attributes:
| Attribute | Type | Description |
|---|---|---|
openclaw.command.action |
string | Command name |
openclaw.command.session_key |
string | Session identifier |
openclaw.command.source |
string | Command source |
Gateway Spans¶
| Span Name | Kind | Description |
|---|---|---|
openclaw.gateway.startup |
INTERNAL | Gateway startup event |
Trace Context Propagation¶
The plugin maintains a sessionContextMap keyed by sessionKey:
message_receivedcreates a root span and stores its contextbefore_model_resolvecreates an agent turn span as a child of the rootbefore_prompt_buildenriches the agent turn span with prompt/history attrstool_result_persistcreates tool spans as children of the agent turnagent_endends the agent turn and root spans, cleans up the context
Stale contexts (no agent_end within 5 minutes) are automatically cleaned up.
Example DQL Queries (Dynatrace)¶
Token usage per agent turn:
fetch spans, samplingRatio:1
| filter contains(endpoint.name, "openclaw.agent.turn")
| fields start_time, duration, gen_ai.usage.input_tokens,
gen_ai.usage.output_tokens,
total_tokens = toLong(gen_ai.usage.input_tokens) + toLong(gen_ai.usage.output_tokens),
gen_ai.response.model
| sort start_time desc
| limit 20
Tool execution breakdown:
fetch spans, samplingRatio:1
| filter startsWith(span.name, "tool.")
| fields start_time, span.name, duration, openclaw.tool.result_chars
| sort start_time desc
| limit 50
Full trace for a session:
fetch spans, samplingRatio:1
| filter openclaw.session.key == "agent:main:main"
| fields start_time, span.name, duration, span.kind, trace.id
| sort start_time desc
Semantic Conventions¶
The plugin follows OpenTelemetry GenAI Semantic Conventions for token-related attributes (gen_ai.usage.*, gen_ai.response.model). Custom OpenClaw attributes use the openclaw.* namespace.