Blog

Ask Elastic Agent Builder why it's slow: Natural-language trace analysis

Four agent performance questions your Agent Builder traces can answer, covering token spend by model, tool error rates, slow conversation turns, and recent prompts. The ES|QL for each is here, including the type cast SUM() needs.

Agent Builder is available now GA. Get started with an Elastic Cloud Trial, and check out the documentation for Agent Builder here.

Ask Elastic Agent Builder how many tokens your agents burned today, and it writes the Elasticsearch Query Language (ES|QL) and runs it against your OpenTelemetry (OTel) trace data. Then it answers in the chat UI. The same holds for your other agent performance questions: Which tool fails most often? Which conversation turns are slowest? What have users actually been asking? Elastic Agent Builder is designed for this purpose. It allows users to ship agents grounded in your data in minutes. 

If tracing is on, the agent-builder-traces skill is already loaded on every agent in your space and there’s nothing to install. The first post in our series covered enabling OTel tracing and the out-of-the-box (OOTB) dashboards, along with threshold alerts. This post is about asking.

What is the agent-builder-traces skill?

agent-builder-traces is a built-in Agent Builder skill. It takes a natural-language question, generates an ES|QL query from it, executes that query against your trace index, and returns a plain-language summary. The index it targets is traces-agent_builder.otel-<space-id>, where <space-id> is the Kibana space that you’re working in. Using the exact space-scoped index pattern, rather than a wildcard, keeps data from other spaces out of your results.

Under the hood, the skill uses a single inline tool: agent-builder-traces.generate_esql. Instead of calling this tool directly, you ask a question and the agent calls the tool on your behalf, passing your question as the prompt for ES|QL generation. The tool resolves the current space's trace index, builds a query using the default model, executes it against Elasticsearch, and returns the result.

Which privacy settings control what your traces capture?

Several fields containing sensitive information are off by default. You can enable them in Gen AI Settings (Stack Management > AI Assistants), under the "Agent Builder Traces" section. Expand the Advanced privacy settings to find them.

Setting key

What it captures

agentBuilder:tracing:includeUserPrompts

User messages

agentBuilder:tracing:includeLlmResponses

Large language model (LLM) response text

agentBuilder:tracing:includeToolDetails

Tool call arguments and results

agentBuilder:tracing:includeSystemPrompt

The agent's system prompt

agentBuilder:tracing:includeRealNames

Real tool, agent, and conversation names (hashed when off)

agentBuilder:tracing:includeRealIds

Real conversation and workflow IDs (hashed when off)

agentBuilder:tracing:includeUserData

Real user IDs and usernames (hashed when off)

Why is my trace analysis query returning empty rows?

If the skill returns empty rows or tells you that a field is unavailable, check two things: whether the relevant setting is enabled in your configuration, and whether your query time window overlaps with any recorded spans. The skill reports exactly what the query returned; it doesn’t fabricate content when fields are empty..

What agent performance questions can you ask?

Examples of questions that you can ask include:

How many tokens have my agents used, by model?

Ask: How many input and output tokens have my agents used in the last 24 hours, broken down by model?

ES|QL: 

FROM traces-agent_builder.otel-<space-id>
| WHERE span.name LIKE "chat *" AND @timestamp >= NOW() - 24 hours
| STATS
    input_tokens  = SUM(TO_LONG(attributes.gen_ai.usage.input_tokens)),
    output_tokens = SUM(TO_LONG(attributes.gen_ai.usage.output_tokens))
  BY attributes.gen_ai.request.model
| SORT input_tokens DESC

The TO_LONG() cast around each token field is required. These fields can surface as mixed integer and long types across index generations, and ES|QL’s SUM() needs an explicit numeric conversion before it can aggregate them. If you write your own queries against this index and hit unexpected type errors, this is usually why.

Which tools are failing most often?

Ask: What is the error rate for each tool over the last 7 days?

ES|QL: 

FROM traces-agent_builder.otel-default
| WHERE @timestamp >= NOW() - 7 days
| WHERE span.name LIKE "execute_tool *"
| STATS total_calls = COUNT(*), error_count = COUNT(*) WHERE status.code == "Error" BY tool_name = attributes.gen_ai.tool.name
| EVAL error_rate_pct = ROUND(error_count * 100.0 / total_calls, 2)
| SORT error_rate_pct DESC
| LIMIT 100

The tool error rate query aggregates across spans named ‘execute_tool’ and compares status.code == "Error" counts to total counts per tool name. The result shows which tools are failing most often. 

Which conversation turns are slowest?

Ask: Show me the 10 slowest conversation turns in the last hour.

ES|QL: 

FROM traces-agent_builder.otel-default
| WHERE @timestamp >= NOW() - 1 hour
| WHERE span.name LIKE "invoke_agent *" AND attributes.elastic.inference.span.kind == "CHAIN"
| EVAL duration_seconds = duration / 1000000000.0
| KEEP attributes.gen_ai.conversation.id, attributes.gen_ai.agent.id, @timestamp, duration_seconds
| SORT duration_seconds DESC
| LIMIT 10

The skill queries spans where span.name LIKE "invoke_agent *" and attributes.elastic.inference.span.kind == "CHAIN". These correspond to individual conversation turns, from the moment a user sends a message to when the agent returns a response. Durations are stored in nanoseconds, so the skill converts to seconds before sorting.

What have users been asking my agents?

Ask: What questions have users been asking in the last 30 minutes?

ES|QL: 

FROM traces-agent_builder.otel-default
| WHERE @timestamp >= NOW() - 30 min
| WHERE span.name LIKE "chat *"
| WHERE attributes.gen_ai.input.messages IS NOT NULL
| SORT @timestamp DESC
| KEEP @timestamp, attributes.gen_ai.conversation.id, attributes.gen_ai.input.messages
| LIMIT 100

The recent-prompts query returns data only when agentBuilder:tracing:includeUserPrompts is set to true. When the setting is off, the attributes.gen_ai.input.messages field is empty and the skill will suggest that you check your Include User Prompts privacy setting.

When should you use Discover or Kibana Lens instead?

The skill targets one index pattern: traces-agent_builder.otel-<space-id>. Two scenarios fall outside that boundary.

Can the skill query my own application indices?

If you want to run ad hoc questions against data that you've indexed yourself, use a general data exploration skill or write ES|QL directly in Discover. The agent-builder-traces skill won’t query outside the Agent Builder traces index.

Can the skill build or edit dashboards?

The skill focuses on ad hoc queries and generating summary text. If your goal is to build a permanent visualization from your trace data, use Lens or the dashboard-management skill instead. We covered that specific process in depth in the first post in our series.

The skill sits alongside two other ways of watching your agents.

Tool

Best for

You use it when

agent-builder-traces skill

Ad hoc agent performance questions

You notice something and want an answer without leaving the chat

OOTB dashboards

Ongoing visibility

You want trends over time without asking anything

Threshold alerts

Automated monitoring

You define a condition once and get notified when it's breached

How to build evaluation pipelines from agent trace data

Spans in traces-agent_builder.otel-<space-id> capture real execution data from every conversation turn and LLM call running in your space. That record is the raw material for evaluation pipelines: automated checks on response quality and latency budgets per agent type, along with regression detection when you update a system prompt. The next post in our series covers how to build those eval loops from trace data that Agent Builder is already collecting.

How helpful was this content?

Related Content

Agentic workflows in Elasticsearch: pause an AI agent for human approval, resume 72 hours later

Agentic workflows in Elasticsearch: pause an AI agent for human approval, resume 72 hours later

Alex Salgado
You and your AI agent shouldn't be using curl: Introducing the Elastic CLI and Agent Skills

You and your AI agent shouldn't be using curl: Introducing the Elastic CLI and Agent Skills

Josh Mock
Trust, but benchmark: How we let an AI agent optimize Elasticsearch

Trust, but benchmark: How we let an AI agent optimize Elasticsearch

Thomas Veasey
AI root cause analysis in Elastic Agent Builder that cites its evidence

AI root cause analysis in Elastic Agent Builder that cites its evidence

Jeffrey Rengifo
Know your facts: How Elasticsearch AI Indices let agents skip the reading and keep the answer

Know your facts: How Elasticsearch AI Indices let agents skip the reading and keep the answer

Kathleen DeRusso

Ready to build state of the art search experiences?

Sufficiently advanced search isn’t achieved with the efforts of one. Elasticsearch is powered by data scientists, ML ops, engineers, and many more who are just as passionate about search as you are. Let’s connect and work together to build the magical search experience that will get you the results you want.