Query Agent Catalog Traces with SQL++
- how-to
You can also use SQL++ through the Query Service or Capella Analytics to query your Agent Catalog activity logs.
Using queries might return more details on traces that you cannot see through the Agent Tracer UI.
Prerequisites
-
You have completed the Prerequisites and Installed and Set Up Environment Variables for the Agent Catalog.
-
You have deployed a single node or multi-node Capella operational cluster running Couchbase Server version 8.0 or later with the Search Service enabled.
This should be the same cluster you add to your environment variables for the Agent Catalog.
For more information about how to add Services to a cluster, see Modify the Cluster Configuration.
-
You have indexed and published tools and prompts to the Agent Catalog.
-
You have Add Spans and Callbacks to Your Agent.
-
If you want to use Capella Analytics to query traces, you must create a Capella Analytics cluster and configure your Agent Catalog cluster as a remote data source.
-
Your user account has the
Organization OwnerorProject Creatororganization role, or 1 of the following project roles: -
You have logged into the Capella UI.
Procedure
To query traces from the Agent Catalog:
-
Query Service
-
Capella Analytics
-
In the Capella UI, on the Operational page, click the name of the cluster where you uploaded your Agent Catalog activity.
-
Go to .
-
Do 1 of the following, or write your own query for your log data:
-
In the Capella UI, on the Analytics page, click the name of the cluster where you created the link to your Agent Catalog operational cluster.
-
Do 1 of the following, or write your own query for your log data:
Query the Sessions View
The following example queries use a generated data view called Sessions to return data on specific sessions in your agent activity.
This can include agent handoff information, for help with debugging multi-agent systems.
-
Query Service
-
Capella Analytics
Copy and paste the following query into the Query Service’s Query Workbench, replacing the placeholders with the bucket and scope for your Agent Catalog activity logs:
FROM
`[BUCKET_NAME]`.`[SCOPE_NAME]`.Sessions() s
SELECT
s.sid,
s.cid,
s.root,
s.start_t,
s.content,
s.ann
LIMIT 10;
If you want to specifically filter for agent handoff messages in the Sessions view, add a WHERE clause to your query for kind = "edge":
FROM
`[BUCKET_NAME]`.`[SCOPE_NAME]`.Sessions() s
SELECT
s.sid,
s.cid,
s.root,
s.start_t,
s.content,
s.ann
WHERE kind = "edge"
LIMIT 10;
Copy and paste the following query into the Capella Analytics workbench.
Replace the placeholders with the database, scope, and collection link name from your Analytics cluster remote link to your Agent Catalog activity logs.
This query creates the Sessions data view:
CREATE OR REPLACE ANALYTICS VIEW `[DATABASE_NAME]`.`[SCOPE_NAME]`.Sessions AS
FROM
`[DATABASE_NAME]`.`[SCOPE_NAME]`.`[COLLECTION_NAME]` AS l
LETTING
sid = l.span.session,
cid = {
"identifier": l.catalog_version.identifier,
"timestamp": l.catalog_version.timestamp
},
root = l.span.name[0]
GROUP BY
sid,
cid,
root
GROUP AS g
LETTING
content = (
FROM
g AS gi
SELECT
gi.l.content AS event,
gi.l.timestamp AS timestamp,
gi.l.span.name AS name,
gi.l.annotations AS annotations,
ROW_NUMBER()
OVER (
ORDER BY
STR_TO_MILLIS(gi.l.timestamp) ASC
) AS seq_num
ORDER BY
seq_num
),
annotations = (
FROM
g AS gi
WHERE
gi.l.annotations IS NOT UNKNOWN
SELECT DISTINCT
gi.l.span.name,
gi.l.annotations
)
SELECT
sid AS sid,
cid AS cid,
root AS root,
content AS content,
content[0].timestamp AS start_t,
annotations AS ann
ORDER BY
STR_TO_MILLIS(start_t) ASC;
Then, run the following query to return 10 Sessions records:
FROM
`[DATABASE_NAME]`.`[SCOPE_NAME]`.Sessions s
SELECT
s.sid,
s.cid,
s.root,
s.start_t,
s.content,
s.ann
LIMIT 10;
If you want to specifically filter for agent handoff messages in the Sessions view, add a WHERE clause to your query for kind = "edge":
FROM
`[DATABASE_NAME]`.`[SCOPE_NAME]`.Sessions s
SELECT
s.sid,
s.cid,
s.root,
s.start_t,
s.content,
s.ann
WHERE kind = "edge"
LIMIT 10;
The records in the Sessions view contain the following information:
| Key | Description |
|---|---|
|
The session ID value. Set a |
|
The specific catalog version. |
|
The name of the root span, as configured in Add a Root Span to Your Agentic App. |
|
The start time of the session. |
|
The events that occurred during the session, such as user messages, LLM responses, or internal agent thinking. |
|
Any custom tags added to the messages or the span. |
Query the Exchanges View
The following example queries use a generated data view called Exchanges to return data on specific exchanges, or the events between a user’s input and the agent’s response.
-
Query Service
-
Capella Analytics
Copy and paste the following query into the Query Service’s Query Workbench, replacing agent-catalog and agent-activity with the bucket and scope for your Agent Catalog activity logs:
FROM
`[BUCKET_NAME]`.`[SCOPE_NAME]`.Exchanges() e
SELECT
e.sid,
e.root,
e.input,
e.output,
e.content
ORDER BY
e.output.timestamp DESC
LIMIT 1;
Copy and paste the following query into the Capella Analytics workbench.
Replace the placeholders with the database, scope, and collection link name from your Analytics cluster remote link to your Agent Catalog activity logs.
This query creates the Exchanges data view:
CREATE OR REPLACE ANALYTICS VIEW `[BUCKET_NAME]`.`[SCOPE_NAME]`.Exchanges AS
WITH
RowOrderedLogs AS (
FROM
`[BUCKET_NAME]`.`[SCOPE_NAME]`.`[LOG_COLLECTION_NAME]` AS l
SELECT
l.content.kind AS kind,
l.span.session AS sid,
l.*,
ROW_NUMBER()
OVER (
PARTITION BY
sid
ORDER BY
STR_TO_MILLIS(l.timestamp) ASC
) AS rn
),
UserToAssistantRows AS (
FROM
RowOrderedLogs rol
GROUP BY
rol.sid
GROUP AS g
LETTING
input_rows = (
FROM
g AS gi
WHERE
gi.rol.kind = "user"
SELECT VALUE
gi.rol.rn
ORDER BY
gi.rol.rn ASC
),
output_rows = (
FROM
g AS gi
WHERE
gi.rol.kind = "assistant"
SELECT VALUE
gi.rol.rn
ORDER BY
gi.rol.rn ASC
),
-- We are looking for the row numbers corresponding to user -- assistant pairs here.
input_output_pairs = (
FROM
input_rows AS iro,
output_rows AS oro
WHERE
iro < oro
GROUP BY
iro
GROUP AS gi
-- We are interested in the closest assistant message to the user message.
LETTING
ordered_output = (
FROM
gi AS gii
SELECT VALUE
gii.oro
ORDER BY
gii.oro ASC
)
SELECT
iro AS input_row,
ordered_output[0] AS output_row
)
SELECT
rol.sid AS sid,
input_output_pairs AS pairs
),
UserToAssistantUnnested AS (
FROM
UserToAssistantRows AS u2a,
u2a.pairs AS p
SELECT
u2a.sid AS sid,
p.input_row AS inp_rn,
p.output_row AS out_rn
)
FROM
UserToAssistantUnnested AS u2au,
RowOrderedLogs AS rol
WHERE
rol.sid = u2au.sid AND
rol.rn >= u2au.inp_rn AND
rol.rn <= u2au.out_rn
GROUP BY
rol.sid AS sid,
rol.span.name[0] AS root,
u2au.inp_rn AS inp_rn,
u2au.out_rn AS out_rn
GROUP AS g
LETTING
content = (
FROM
g AS gi
SELECT VALUE
OBJECT_REMOVE(gi.rol, "rn")
ORDER BY
gi.rol.timestamp ASC
),
input_content = (
FROM
g AS gi
WHERE
gi.rol.rn = inp_rn
SELECT VALUE
OBJECT_REMOVE(gi.rol, "rn")
LIMIT 1
)[0],
output_content = (
FROM
g AS gi
WHERE
gi.rol.rn = out_rn
SELECT VALUE
OBJECT_REMOVE(gi.rol, "rn")
LIMIT 1
)[0]
SELECT
sid AS sid,
root AS root,
input_content AS `input`,
output_content AS `out`,
content AS content;
Then, run the following query to return the most recent exchange record:
FROM
`[DATABASE_NAME]`.`[SCOPE_NAME]`.Exchanges e
SELECT
e.sid,
e.root,
e.input,
e.out,
e.content
ORDER BY e.out.timestamp DESC
LIMIT 1;
The records in the Exchanges view contain the following information:
| Key | Description |
|---|---|
|
The session ID value. Set a |
|
The name of the root span, as configured in Add a Root Span to Your Agentic App. |
|
The user’s input to the agent app. |
|
The assistant’s response to the user’s input. |
|
All intermediate content logs between the |
Query the ToolInvocations View
The following example queries use a generated data view called ToolInvocations to return data on tool calls and tool results.
-
Query Service
-
Capella Analytics
Copy and paste the following query into the Query Service’s Query Workbench, replacing agent-catalog and agent-activity with the bucket and scope for your Agent Catalog activity logs:
FROM
`[BUCKET_NAME]`.`[SCOPE_NAME]`.ToolInvocations() ti
SELECT
ti.sid,
ti.root,
ti.tool_call,
ti.tool_result
ORDER BY
ti.tool_result.timestamp DESC
LIMIT 1;
Copy and paste the following query into the Capella Analytics workbench.
Replace the placeholders with the database, scope, and collection link name from your Analytics cluster remote link to your Agent Catalog activity logs.
This query creates the ToolInvocations data view:
CREATE OR REPLACE ANALYTICS VIEW `[BUCKET_NAME]`.`[SCOPE_NAME]`.ToolInvocations AS
FROM
(
WITH
RowOrderedToolLogs AS (
FROM
`[BUCKET_NAME]`.`[SCOPE_NAME]`.`[LOG_COLLECTION_NAME]` AS l
WHERE
l.content.kind = "tool-call" OR
l.content.kind = "tool-result"
SELECT
l.content.kind AS kind,
l.span.session AS sid,
l.*,
ROW_NUMBER()
OVER (
PARTITION BY
sid
ORDER BY
STR_TO_MILLIS(l.timestamp) ASC
) AS rn
),
CallToResultRows AS (
FROM
RowOrderedToolLogs rol
GROUP BY
rol.sid
GROUP AS g
LETTING
input_rows = (
FROM
g AS gi
WHERE
gi.rol.kind = "tool-call"
SELECT VALUE
gi.rol.rn
ORDER BY
gi.rol.rn ASC
),
output_rows = (
FROM
g AS gi
WHERE
gi.rol.kind = "tool-result"
SELECT VALUE
gi.rol.rn
ORDER BY
gi.rol.rn ASC
),
input_output_pairs = (
FROM
input_rows AS iro,
output_rows AS oro
WHERE
iro < oro
GROUP BY
iro
GROUP AS gi
LETTING
ordered_output = (
FROM
gi AS gii
SELECT VALUE
gii.oro
ORDER BY
gii.oro ASC
)
SELECT
iro AS input_row,
ordered_output[0] AS output_row
)
SELECT
rol.sid AS sid,
input_output_pairs AS pairs
),
CallToResultRowsUnnested AS (
FROM
CallToResultRows AS c2r,
c2r.pairs AS p
SELECT
c2r.sid AS sid,
p.input_row AS inp_rn,
p.output_row AS out_rn
),
ToolCalls AS (
FROM
`[BUCKET_NAME]`.`[SCOPE_NAME]`.`[LOG_COLLECTION_NAME]` AS l
WHERE
l.content.kind = "tool-call"
SELECT VALUE
l
),
ToolResults AS (
FROM
`[BUCKET_NAME]`.`[SCOPE_NAME]`.`[LOG_COLLECTION_NAME]` AS l
WHERE
l.content.kind = "tool-result"
SELECT VALUE
l
)
FROM
CallToResultRowsUnnested AS c2ru,
RowOrderedToolLogs AS rol1,
RowOrderedToolLogs AS rol2
LETTING
tool_call = OBJECT_REMOVE(rol1, "rn"),
tool_result = OBJECT_REMOVE(rol2, "rn")
WHERE
rol1.rn = c2ru.inp_rn AND
rol2.rn = c2ru.out_rn
SELECT
c2ru.sid AS sid,
c2ru.span.name AS root,
tool_call AS tool_call,
tool_result AS tool_result
UNION ALL
FROM
ToolCalls AS tc,
ToolResults AS tr
WHERE
tc.content.tool_call_id = tr.content.tool_call_id
SELECT
tc.span.session AS sid,
tc.span.name AS root,
tc AS tool_call,
tr AS tool_result
) AS ti
GROUP BY
tc.identifier
GROUP AS g
SELECT VALUE
g[0].ti;
Then, run the following query to return the most recent tool invocation record:
FROM
`[BUCKET_NAME]`.`[SCOPE_NAME]`.ToolInvocations ti
SELECT
ti.sid,
ti.root,
ti.tool_call,
ti.tool_result
ORDER BY
ti.tool_result.timestamp DESC
LIMIT 1;
The records in the ToolInvocations view contain the following information:
| Key | Description |
|---|---|
|
The session ID value. Set a |
|
The name of the root span, as configured in Add a Root Span to Your Agentic App. |
|
The tool call from your agent application. |
|
The results returned by the tool call. |
Next Steps
To view traces in the Agent Tracer UI, see View Traces in Agent Tracer.
To view details about specific tools and prompts published to Agent Catalog from your project, see Use the Agent Catalog Tools and Prompts Hub.