MCP tools
A Pitot instance serves MCP at /mcp. 20 tools are available to an Apps-enabled client. Ordinary clients receive the 17 model-visible tools; the three app-only helpers require Apps negotiation and are never offered to the model.
Every tool is closed-world: it reads or writes what this instance holds and reaches nothing else.
The catalog below includes MCP Apps helpers. App-only helpers are omitted from
ordinary clients and model tool definitions. Interactive view tools return a
PanelFragment: {view, dashboard, results, vars?, trace?}. Results match every
dashboard panel id exactly once. Required view contains kind (preset or
query) and key, a stable SHA-256 hash computed once by Go from the spec,
captured window and variables. Cosmetic titles and IDs do not affect identity.
The agent and host use this key and prefer presets when equivalent views repeat.
Variables retain scalar, $__all, empty-list
and multi-list values. Model text is a deterministic summary of at most 16 KiB;
structured content is the same bounded full fragment persisted for reload, at
most 256 KiB, with visible row truncation. Oversized authored spec/variables
are rejected before execution at 128 KiB rather than changing their semantics.
Trace and dependency results include data, a summary, and provenance with window,
generated_at and complete. Truncation and traversal limits remain in the data.
Storage sources, schema identifiers and query IDs are omitted.
AG-UI mcp-app activity content uses exactly resource_uri, tool_name,
tool_input, tool_result, and is_error. Protocol structuredContent,
resourceUri, toolCallId, threadId, and runId keep their spelling.
| Tool | Changes state |
|---|---|
create_dashboard | Yes — additive |
edit_dashboard | Yes — replaces existing state |
get_dashboard | No — read-only |
get_insights | No — read-only |
get_overview | No — read-only |
get_service_dependencies | No — read-only |
get_service_performance | No — read-only |
get_service_topology | No — read-only |
get_telemetry_schema | No — read-only |
inspect_trace | No — read-only |
list_dashboard_versions | No — read-only |
list_dashboards | No — read-only |
list_panel_exemplars | No — read-only |
preview_panels | No — read-only |
query_panel_fragment | No — read-only |
query_telemetry | No — read-only |
replace_dashboard | Yes — replaces existing state |
resolve_panel_variables | No — read-only |
restore_dashboard_version | Yes — replaces existing state |
search_logs | No — read-only |
create_dashboard
Section titled “create_dashboard”Create dashboard: Create a dashboard for the authenticated user from a complete spec. Read get_telemetry_schema first and preview_panels until every non-text panel returns data. Empty or failing panels return error.code invalid_spec with their path, title and diagnosis, plus structured problems. Successful saves return a receipt for that committed version: base_version, version, changes, layout_changed, dashboard_fields and save_check. Changes describe authored panel fields and position_changed; physical packing is only layout_changed. Order chips mark the minimal moved set. save_check reports checked, reason when unchecked, total elapsed_ms and one status/rows result per saved panel with elapsed_ms when executed. checked means every panel was executed, not that error or empty panels are healthy. Text rows identify nonempty content, not telemetry. Use the structured receipt rather than prose warnings as check evidence. Create receipts list added panels without layout or dashboard edit chips. No-op saves still create a new version with no change chips. Per-panel elapsed_ms is omitted when the panel did not run. A dashboard is {name, description, time:{range}, variables, panels}. Each panel: {id (lowercase), title, viz, width 1-12, query or sql}. viz: stat or gauge (one measure; gauge needs min and max), timeseries (bucket auto, at most one by), bar (one or two by), table (up to three by), text (content in Markdown), heatmap (bucket auto, no by), histogram (at most one by), scatter (exactly two measures in x then y order, one item dimension and an optional colour dimension), state_timeline (one measure, one item dimension, bucket auto and thresholds required). Rollup panel types are service_map (dependency graph) and health (overview metrics, error trend and health distribution). They require query.from=spans, no measures, by, bucket or sort, and only namespace/service equality filters with a literal or single-value variable; explicit casts and values with surrounding whitespace are rejected. Reads default to 400 services/edges and are capped at 400 even when query.limit is larger. Service scope applies before the limit; map nodes carry p95_ms and edges carry average_ms; error_rate is percent. Row panel types are logs, log_patterns and traces. Logs and traces take no measures, by or bucket. Patterns use count() by body_template. Patterns group only by body_template. Severity is the most frequent severity, ties choose the higher severity. Service is the most frequent service, ties choose ascending service name. Both describe the scoped, redacted events, not extra grouping dimensions. Each pattern returns dominant severity, top service, count and a dense trend, computed in the same bounded query after redaction and scoped filters. Redaction applies before filtering, grouping, display and drill-down. Row panels cannot use SQL. “erroring” means slowest erroring traces: filter to erroring traces, then rank by root duration. Trace candidate ranking is approximate when filters exclude the root span, as with exemplars. Categorical charts use fixed-order colour slots. Categorical options.top defaults to 6, maximum 6. Structured panels: the server computes Other; series are chosen worst-first by confidence (Wilson lower bound for error rates; at least 20 samples for latency); the rest fold into Other (N). Count, rate, sum and share rank largest first. Error rates require at least 20 requests for eligible Wilson ranking (z=1.96). Percentiles, quantile, avg, max and min require at least 20 non-null numeric samples for eligible value ranking and use better (explicit or inferred). Ineligible series follow eligible ones by sample count descending. Ties use sample count descending, then name ascending. SQL panels: series past six are left out, with a note. state_timeline defaults to 8 rows, maximum 20; other noncategorical panels use the same limits. Scatter supports options.x_scale and options.y_scale (log or linear), with distinct x_unit for x and unit for y, each inferred independently when omitted. Rows returned use the count unit. State timelines preserve null and absent buckets as unknown and keep the top items without merging them into Other. Scatter requires a structured query. SQL state_timeline requires timestamp time, a string item, one numeric measure and optional string state; its interval is one minute and thresholds are required. Items rank by volume (row count) for top N. Previous-period comparison is not drawn for scatter or state_timeline. Distribution panels use a structured query with one count() measure and histogram: {field: duration_ms, buckets: log2} for spans or {field: value, buckets: explicit} for metrics. Negative span durations clamp to [0,1); +Inf goes to overflow; NaN is excluded because it is not a measurement. Metric histograms use stored temporality and shared per-series increases; resets contribute current counts. Delta histograms sum observation weights. query: {from: spans|logs|metrics, where: [filter expressions], measures: [fn(field) as alias], by: [fields], bucket, sort, limit}. Measures: count(), rate() per second, error_rate() percent, share() percent, avg/min/max/sum(field), last(value) for metrics, p50/p75/p90/p95/p99(field), quantile(field, 0.999), count_distinct(field). Spans and logs aggregate panels also support count_if(SQL filter) and + - * / with constants and parentheses; arithmetic requires as alias and at least one aggregate, variables are not allowed inside count_if, share() stands alone, and division by zero returns null. Measures are bounded to 256 tokens, 64 nodes, depth 8 and 8 aggregates each, and 256 nodes and 24 aggregates together. Metrics do not support arithmetic. Fields are columns from get_telemetry_schema or attributes[‘key’] / resource[‘key’] with the key written literally. Standard OpenTelemetry keys that get_telemetry_schema marks indexed, such as http.response.status_code and k8s.pod.name, read typed: ingest converts a value sent in another type, so “200” reads as the number 200, and they need no cast. Other keys read as sent. Filters are SQL boolean expressions: service = $service, kind = ‘SPAN_KIND_SERVER’, status = ‘STATUS_CODE_ERROR’, attributes[‘http.route’] IN $routes, attributes[‘http.response.status_code’] >= 500. Variables: {name, kind: query|custom|constant|text, from, field, default, include_all}; $__all selects All and removes filters that use the variable. sql: one SELECT over spans, logs, metrics, service_rollup, span_rollup, edge_rollup or resource_inventory that filters time with $__window(column). Compare time columns with TIMESTAMP ‘YYYY-MM-DD HH:MM:SS’ (UTC), or cast TIMESTAMPTZ literals with ::TIMESTAMPTZ_NS. Use values exactly as get_telemetry_schema lists them. Example panel: {“id”:“latency”,“title”:“Checkout latency”,“viz”:“timeseries”,“width”:8,“query”:{“from”:“spans”,“where”:[“service = ‘checkout’”,“kind = ‘SPAN_KIND_SERVER’”],“measures”:[“p50(duration_ms)”,“p95(duration_ms)”,“p99(duration_ms)”],“bucket”:“auto”},“unit”:“ms”,“thresholds”:[{“value”:1500,“status”:“bad”}]}. Structured spans aggregate panels restricted to namespace/service/kind/status and count/rate/error_rate/share or duration aggregates use span_rollup at minute resolution. Percentiles are approximate (one exponential bucket, 9.05%); fresh_to_ms is the ingest horizon. Other structured queries stay raw. Metrics: gauge/updown | counter | histogram. count(): points; count_distinct(): distinct. rate(): undefined | series increase/elapsed summed | count rate summed. sum(value): series means summed | increases | sum increases. avg(value): mean series means | undefined | sum/count increases. Gauge/updown sum/avg carry earlier points within 5m. Deltas spread across covered buckets; rate alone carries within 5m. rate() is per-second increase over covered elapsed time; auto >=1m. min/max: points | points | undefined. last(value): latest strictly before bucket/window end, reported within 5m, summed | same | undefined. pNN/quantile: points | undefined | interpolated bucket increases. summary: no value aggregates. Undefined: NULL. Fix name in its own where entry: one literal or single-value variable without All or multi-value; or name in by. Read type/temporality from get_telemetry_schema. Panel SQL also supports resource_inventory: signal, namespace, service, full typed resource, first_seen and last_seen. One row per distinct full resource per signal/namespace/service observed inside the logical panel window; first_seen/last_seen are actual in-window event times. Select signal=‘spans’, ‘logs’ or ‘metrics’ and use resource[‘key’] with literal dotted keys. count(*) counts resource identities per signal, not events or instances. Declare $__window(first_seen). This relation is SQL-only: query.from and variables remain spans|logs|metrics; unscoped SQL cannot read it. state_timeline needs at least one threshold marked warn or bad, rather than only ok. Annotations attach only to timeseries, heatmap and state_timeline panels, scoped by service and namespace filters. drill: logs needs query.from=logs. Drill is not available on metrics. Every table format’s field must exist in the returned frame; formatting cannot reference an absent column. A structured-table sparkline field must be a measure alias from that table’s query. service_link needs variable to name the query or custom variable selected by the link. highlight applies to logs and log_patterns, at most 200 characters. split: deploy needs a service equality filter, as a literal or a single-value variable; other filters are allowed. When the service is All, a split: deploy panel shows the plain bar with a note explaining the missing service scope. Use service_map for dependency context, health for service health; neither proves causality. Example 1: Reference shapes; use only the types the question needs. {“name”:“Investigation shapes”,“annotations”:{“deploys”:true,“anomalies”:true},“variables”:[{“name”:“service”,“kind”:“query”,“from”:“spans”,“field”:“service”}],“panels”:[{“id”:“latency_heat”,“title”:“Latency over time”,“viz”:“heatmap”,“query”:{“from”:“spans”,“where”:[“service = $service”],“measures”:[“count()”],“bucket”:“auto”,“histogram”:{“field”:“duration_ms”,“buckets”:“log2”}},“drill”:“traces”},{“id”:“latency_hist”,“title”:“Latency by operation”,“viz”:“histogram”,“query”:{“from”:“spans”,“where”:[“service = $service”],“measures”:[“count()”],“by”:[“operation”],“histogram”:{“field”:“duration_ms”,“buckets”:“log2”}},“drill”:“traces”},{“id”:“items”,“title”:“Calls versus tail latency”,“viz”:“scatter”,“query”:{“from”:“spans”,“where”:[“service = $service”],“measures”:[“count() as rows”,“p95(duration_ms) as tail_latency”],“by”:[“operation”]},“drill”:“traces”},{“id”:“states”,“title”:“Error states”,“viz”:“state_timeline”,“query”:{“from”:“spans”,“where”:[“service = $service”],“measures”:[“error_rate()”],“by”:[“operation”],“bucket”:“auto”},“thresholds”:[{“value”:5,“status”:“bad”}],“drill”:“traces”},{“id”:“log_rows”,“title”:“Recent logs”,“viz”:“logs”,“query”:{“from”:“logs”,“where”:[“service = $service”],“sort”:“time”,“limit”:100},“drill”:“logs”},{“id”:“patterns”,“title”:“Repeated log patterns”,“viz”:“log_patterns”,“query”:{“from”:“logs”,“where”:[“service = $service”],“measures”:[“count()”],“by”:[“body_template”],“bucket”:“auto”,“limit”:50},“drill”:“logs”},{“id”:“trace_rows”,“title”:“Slow traces”,“viz”:“traces”,“query”:{“from”:“spans”,“where”:[“service = $service”],“sort”:“duration_ms”,“limit”:20},“drill”:“traces”},{“id”:“map”,“title”:“Service calls”,“viz”:“service_map”,“query”:{“from”:“spans”}},{“id”:“health”,“title”:“Service health”,“viz”:“health”,“query”:{“from”:“spans”}}]} Example 2: Reference shapes; use only the types the question needs. {“name”:“Interaction shapes”,“variables”:[{“name”:“service”,“kind”:“query”,“from”:“spans”,“field”:“service”}],“panels”:[{“id”:“hist”,“title”:“Metric distribution”,“viz”:“histogram”,“query”:{“from”:“metrics”,“where”:[“service = $service”],“measures”:[“count()”],“histogram”:{“field”:“value”,“buckets”:“explicit”}}},{“id”:“table”,“title”:“Service calls and trends”,“viz”:“table”,“query”:{“from”:“spans”,“measures”:[“count() as calls”],“by”:[“service”]},“options”:{“columns”:[{“field”:“service”,“format”:“service_link”,“variable”:“service”},{“field”:“calls”,“format”:“sparkline”}]}},{“id”:“prior”,“title”:“Service calls one day earlier”,“viz”:“bar”,“query”:{“from”:“spans”,“measures”:[“count()”],“by”:[“service”]},“click”:{“set_variable”:“service”},“time”:{“shift”:“1d”}}]} Metric examples; use when the discovered type fits. {“name”:“Metric measures”,“panels”:[{“id”:“network”,“title”:“Network bytes per second”,“viz”:“timeseries”,“query”:{“from”:“metrics”,“where”:[“name = ‘system.network.io’”],“measures”:[“rate()”],“by”:[“attributes[‘direction’]”],“bucket”:“auto”}},{“id”:“duration”,“title”:“Request duration p95”,“viz”:“timeseries”,“query”:{“from”:“metrics”,“where”:[“name = ‘http.server.request.duration’”],“measures”:[“p95(value)”],“bucket”:“auto”},“unit”:“s”}]} Observed-resource SQL example. {“name”:“Observed resources”,“panels”:[{“id”:“resources”,“title”:“Span resources observed in this window”,“viz”:“table”,“sql”:“SELECT namespace,service,resource[‘service.version’]::VARCHAR AS version,first_seen,last_seen FROM resource_inventory WHERE signal=‘spans’ AND $__window(first_seen) ORDER BY namespace,service,version,first_seen,last_seen”}]}
Additive. It creates something new and alters nothing that exists.
| Input | Type | Required | Means |
|---|---|---|---|
dashboard | object | yes | Complete v1 dashboard spec |
edit_dashboard
Section titled “edit_dashboard”Edit dashboard: Every non-text panel must return data in the preview or the save returns error.code invalid_spec with the panel path, title and diagnosis, plus structured problems. A stale base_version returns error.code dashboard_version_conflict. Change a dashboard with typed operations, applied in order and saved as one version: add_panel, update_panel (set replaces the named fields), remove_panel, move_panel, set_variable, remove_variable, set_time, rename. Panels not named are left unchanged. Only edit when the user asks to change that dashboard. Successful saves return a receipt for that committed version: base_version, version, changes, layout_changed, dashboard_fields and save_check. Changes describe authored panel fields and position_changed; physical packing is only layout_changed. Order chips mark the minimal moved set. save_check reports checked, reason when unchecked, total elapsed_ms and one status/rows result per saved panel with elapsed_ms when executed. checked means every panel was executed, not that error or empty panels are healthy. Text rows identify nonempty content, not telemetry. Use the structured receipt rather than prose warnings as check evidence. Create receipts list added panels without layout or dashboard edit chips. No-op saves still create a new version with no change chips. Per-panel elapsed_ms is omitted when the panel did not run. See create_dashboard for the spec guide.
Replaces existing state.
| Input | Type | Required | Means |
|---|---|---|---|
id | string | yes | Dashboard ID |
operations | array | yes | Edits applied in order, atomically |
base_version | integer | no | Version you read; the call fails if someone saved since |
message | string | no | One line describing the change, shown in history |
get_dashboard
Section titled “get_dashboard”Get dashboard: Read one dashboard’s complete spec and version. Read it before editing so operations name real panel ids. See create_dashboard for the spec guide.
Read-only.
| Input | Type | Required | Means |
|---|---|---|---|
id | string | yes | Dashboard ID returned by list_dashboards or create_dashboard |
get_insights
Section titled “get_insights”Latest detected anomalies: Return the latest precomputed system findings: health score, anomalies, insights, recurring log patterns, summary, generation time, and evaluated timeframe.
Read-only.
Takes no arguments.
get_overview
Section titled “get_overview”System health overview: Summarize service health for a bounded telemetry window. Start here for incident triage. All-empty results return no_data guidance instead of a view. State no matching data findings in the answer and prefer signals the service actually has.
Read-only.
View resource: ui://pitot/panels.html (model and app visible).
| Input | Type | Required | Means |
|---|---|---|---|
from | string | no | Absolute start, RFC3339Nano; requires to and excludes window |
limit | integer | no | Maximum services or edges to return, from 1 to 500 |
namespace | string | no | OpenTelemetry service namespace; empty queries all namespaces |
to | string | no | Absolute end, RFC3339Nano; requires from and excludes window |
window | string | no | Time window such as 15m, 1h, 24h, 168h, or 720h; defaults to 1h |
get_service_dependencies
Section titled “get_service_dependencies”Service dependency traversal: Find upstream or downstream dependencies of one service with minimum hop counts. Uses the full scoped edge rollup, handles cycles, and reports truncation from depth or node limits.
Read-only.
| Input | Type | Required | Means |
|---|---|---|---|
service | string | yes | Root service name |
direction | string | no | upstream or downstream; defaults to downstream |
max_depth | integer | no | Maximum hops from 1 to 32; defaults to 8 |
max_nodes | integer | no | Maximum accumulated nodes from 1 to 500 including roots; defaults to 100 |
namespace | string | no | Filter by namespace; traversal always keeps namespaces separate |
window | string | no | Bounded telemetry window, defaults to 1h |
get_service_performance
Section titled “get_service_performance”Service performance explorer: Display separate latency, error rate and request rate panels plus a Slow operations table showing p95 duration grouped by operation over server and consumer spans, covering HTTP, gRPC and message consumers, for one service or the system. All-empty results return no_data guidance instead of a view. State no matching data findings in the answer and prefer signals the service actually has.
Read-only.
View resource: ui://pitot/panels.html (model and app visible).
| Input | Type | Required | Means |
|---|---|---|---|
from | string | no | Absolute start, RFC3339Nano; requires to and excludes window |
limit | integer | no | Maximum operations to return, from 1 to 500 |
namespace | string | no | OpenTelemetry service namespace; empty queries all namespaces |
service | string | no | Optional exact OpenTelemetry service name; omit for the whole system |
to | string | no | Absolute end, RFC3339Nano; requires from and excludes window |
window | string | no | Time window such as 15m, 1h, 24h, 168h, or 720h; defaults to 1h |
get_service_topology
Section titled “get_service_topology”Service dependency topology: Return services and observed dependency edges with health, traffic, latency, and error data. All-empty results return no_data guidance instead of a view. State no matching data findings in the answer and prefer signals the service actually has.
Read-only.
View resource: ui://pitot/panels.html (model and app visible).
| Input | Type | Required | Means |
|---|---|---|---|
from | string | no | Absolute start, RFC3339Nano; requires to and excludes window |
limit | integer | no | Maximum services or edges to return, from 1 to 500 |
namespace | string | no | OpenTelemetry service namespace; empty queries all namespaces |
to | string | no | Absolute end, RFC3339Nano; requires from and excludes window |
window | string | no | Time window such as 15m, 1h, 24h, 168h, or 720h; defaults to 1h |
get_telemetry_schema
Section titled “get_telemetry_schema”Telemetry schema: List the signals, columns with their common values, attribute keys seen per service, metric names, services, measure functions, units and SQL-only relations in sql_relations. Read this before drafting panels so filters use values that exist. Compare time columns with TIMESTAMP ‘YYYY-MM-DD HH:MM:SS’ (UTC), or cast TIMESTAMPTZ literals with ::TIMESTAMPTZ_NS. See create_dashboard for the spec guide.
Read-only.
| Input | Type | Required | Means |
|---|---|---|---|
namespace | string | no | Limit discovery to one service namespace |
window | string | no | 5m, 15m, 1h, 3h, 6h, 12h or 24h; default 1h |
inspect_trace
Section titled “inspect_trace”Trace detail: Inspect an exact trace, or select the most relevant recent error or slow trace, with spans, waterfall, flame graph, and correlated logs. All-empty results return no_data guidance instead of a view. State no matching data findings in the answer and prefer signals the service actually has.
Read-only.
View resource: ui://pitot/panels.html (model and app visible).
| Input | Type | Required | Means |
|---|---|---|---|
from | string | no | Absolute start, RFC3339Nano; requires to and excludes window |
limit | integer | no | Maximum spans and correlated logs to return, from 1 to 500 |
namespace | string | no | OpenTelemetry service namespace; empty queries all namespaces |
service | string | no | Optional service filter when choosing a recent trace |
to | string | no | Absolute end, RFC3339Nano; requires from and excludes window |
trace_id | string | no | Exact trace ID; omit to inspect the most relevant recent error or slow trace |
window | string | no | Trace lookup window such as 1h, 24h, 168h, or 720h; defaults to 1h |
list_dashboard_versions
Section titled “list_dashboard_versions”List dashboard versions: List the authenticated user’s saved versions of one dashboard, newest first, with author and message. The historical version identifies a restore target; restore_dashboard_version saves it as a new version.
Read-only.
| Input | Type | Required | Means |
|---|---|---|---|
id | string | yes | Dashboard ID returned by list_dashboards or create_dashboard |
list_dashboards
Section titled “list_dashboards”List dashboards: List the authenticated user’s dashboards with panel counts and versions. See create_dashboard for the spec guide.
Read-only.
Takes no arguments.
list_panel_exemplars
Section titled “list_panel_exemplars”Panel exemplars: Find bounded traces for a panel selection.
Read-only.
Visibility: app only; no resource attachment.
| Input | Type | Required | Means |
|---|---|---|---|
dashboard | object | yes | Complete v1 dashboard specification; every panel is executed |
from | string | yes | Selection start as an RFC3339Nano UTC timestamp |
panel_id | string | yes | ID of the selected panel in dashboard |
to | string | yes | Selection end as an RFC3339Nano UTC timestamp, after from |
bucket | object | no | Optional selected bucket with its exact bounds |
dimensions | object | no | Exact dimension values of the selected series or row |
kind | string | no | Selection signal: traces or logs; defaults from the selected panel |
time | object | no | Optional dashboard time override: exact from/to or a relative range |
vars | object | no | Resolved variable values: strings or lists; preserves $__all and empty lists |
preview_panels
Section titled “preview_panels”Preview panels: Check and run panels without saving them. Each panel reports ok with rows and a sample, empty with the reason, error, or invalid with the exact field and a suggestion. The result includes total elapsed_ms and executed per-panel elapsed_ms; invalid and not_run panels omit elapsed_ms because they were not executed. Fix every invalid panel and replace or drop every empty one before saving. Spec guide: see create_dashboard.
Read-only.
| Input | Type | Required | Means |
|---|---|---|---|
panels | array | yes | Panels to check and run, in the same format as dashboard panels |
time | object | no | Time range; default the last hour |
variables | array | no | Variables the panels reference |
vars | object | no | Variable values to preview with; $__all selects All |
query_panel_fragment
Section titled “query_panel_fragment”Refresh telemetry panels: Run every panel in a dashboard fragment; panel subsets are forbidden. All-empty results return no_data guidance instead of a view. State no matching data findings in the answer and prefer signals the service actually has.
Read-only.
Visibility: app only; no resource attachment.
| Input | Type | Required | Means |
|---|---|---|---|
dashboard | object | yes | Complete v1 dashboard specification; every panel is executed |
compare | boolean | no | Override previous-period comparison for the complete fragment |
time | object | no | Optional dashboard time override: exact from/to or a relative range |
vars | object | no | Resolved variable values: strings or lists; preserves $__all and empty lists |
widths | object | no | Optional panel widths in pixels, keyed by panel ID |
query_telemetry
Section titled “query_telemetry”Telemetry panel: Display one v1 panel in chat as an executable dashboard fragment. Use get_telemetry_schema to discover fields; see create_dashboard for the spec guide. The authored spec plus vars must fit 128 KiB (131072 serialized JSON bytes); larger inputs are rejected with their actual size. Agents: write panel.query (structured JSON) first, or panel.sql for complex work; text accepts FanQL: source [where] filters | measures by fields every bucket sort key limit n. Examples: spans where status:error | count() by service; logs where severity>=warn | count() by service every 1m. See pitot://fanql/reference for fields, operators and variables. All-empty results return no_data guidance instead of a view. State no matching data findings in the answer and prefer signals the service actually has.
Read-only.
View resource: ui://pitot/panels.html (model and app visible).
| Input | Type | Required | Means |
|---|---|---|---|
panel | object | yes | One v1 panel to display in the answer |
text | string | no | FanQL text that becomes panel.query; prefer panel.query (structured) or panel.sql; see pitot://fanql/reference |
time | object | no | Optional dashboard time override: exact from/to or a relative range |
variables | array | no | Optional v1 variable definitions used by this panel |
vars | object | no | Resolved variable values: strings or lists; preserves $__all and empty lists |
replace_dashboard
Section titled “replace_dashboard”Replace dashboard: Every non-text panel must return data in the preview or the save returns error.code invalid_spec with the panel path, title and diagnosis, plus structured problems. A stale base_version returns error.code dashboard_version_conflict. Replace a dashboard’s whole spec; omitted panels are removed. Use only for a redesign the user asked for; use edit_dashboard to change a few panels. Successful saves return a receipt for that committed version: base_version, version, changes, layout_changed, dashboard_fields and save_check. Changes describe authored panel fields and position_changed; physical packing is only layout_changed. Order chips mark the minimal moved set. save_check reports checked, reason when unchecked, total elapsed_ms and one status/rows result per saved panel with elapsed_ms when executed. checked means every panel was executed, not that error or empty panels are healthy. Text rows identify nonempty content, not telemetry. Use the structured receipt rather than prose warnings as check evidence. Create receipts list added panels without layout or dashboard edit chips. No-op saves still create a new version with no change chips. Per-panel elapsed_ms is omitted when the panel did not run. See create_dashboard for the spec guide.
Replaces existing state.
| Input | Type | Required | Means |
|---|---|---|---|
dashboard | object | yes | Complete replacement spec; omitted panels are removed |
id | string | yes | Dashboard ID |
base_version | integer | no | Version you read; the call fails if someone saved since |
message | string | no | One line describing the change, shown in history |
resolve_panel_variables
Section titled “resolve_panel_variables”Panel variable options: Resolve variable options within a dashboard fragment window.
Read-only.
Visibility: app only; no resource attachment.
| Input | Type | Required | Means |
|---|---|---|---|
dashboard | object | yes | Complete v1 dashboard specification; every panel is executed |
time | object | no | Optional dashboard time override: exact from/to or a relative range |
vars | object | no | Resolved variable values: strings or lists; preserves $__all and empty lists |
restore_dashboard_version
Section titled “restore_dashboard_version”Restore dashboard version: Restore a saved historical version of the authenticated user’s dashboard only on an explicit user request. The input version selects the historical spec; the result’s version is the newly saved version. Every successful call appends another version, even when restoring the latest spec. A missing or pruned target returns error.code dashboard_version_not_found; list_dashboard_versions shows retained versions. Spec validation failures return error.code invalid_spec with the presented problems. Successful saves return a receipt for that committed version: base_version, version, changes, layout_changed, dashboard_fields and save_check. Changes describe authored panel fields and position_changed; physical packing is only layout_changed. Order chips mark the minimal moved set. save_check reports checked, reason when unchecked, total elapsed_ms and one status/rows result per saved panel with elapsed_ms when executed. checked means every panel was executed, not that error or empty panels are healthy. Text rows identify nonempty content, not telemetry. Use the structured receipt rather than prose warnings as check evidence. Create receipts list added panels without layout or dashboard edit chips. No-op saves still create a new version with no change chips. Per-panel elapsed_ms is omitted when the panel did not run.
Replaces existing state.
| Input | Type | Required | Means |
|---|---|---|---|
id | string | yes | Dashboard ID |
version | integer | yes | Positive stored version to restore; restoring creates a new version |
search_logs
Section titled “search_logs”Log explorer: Search and filter logs with a severity timeline and links back to correlated traces. All-empty results return no_data guidance instead of a view. State no matching data findings in the answer and prefer signals the service actually has.
Read-only.
View resource: ui://pitot/panels.html (model and app visible).
| Input | Type | Required | Means |
|---|---|---|---|
from | string | no | Absolute start, RFC3339Nano; requires to and excludes window |
limit | integer | no | Maximum log entries to return, from 1 to 500 |
namespace | string | no | OpenTelemetry service namespace; empty queries all namespaces |
search | string | no | Optional case-insensitive text contained in the log body, at most 200 characters |
service | string | no | Optional exact OpenTelemetry service name |
severity | string | no | Optional exact severity such as ERROR, WARN, or INFO |
to | string | no | Absolute end, RFC3339Nano; requires from and excludes window |
window | string | no | Time window such as 15m, 1h, 24h, 168h, or 720h; defaults to 1h |
Panel SQL relations
Section titled “Panel SQL relations”edge_rollup
Section titled “edge_rollup”Dependency analytical rollup by namespace, time bucket, caller, callee and edge type. Panel SQL only; filter bucket with $__window(bucket).
| Column | SQL type | Means |
|---|---|---|
namespace | VARCHAR | OpenTelemetry service namespace |
bucket | TIMESTAMP | Rollup time bucket |
caller | VARCHAR | Calling service |
callee | VARCHAR | Called service |
calls | BIGINT | Calls between services |
avg_ms | DOUBLE | Average call duration |
error_rate | DOUBLE | Error rate |
edge_type | VARCHAR | call, messaging or peer |
p50_ms | DOUBLE | Peer minute median duration; call-weighted across buckets |
p95_ms | DOUBLE | Peer minute 95th percentile duration; call-weighted across buckets |
endpoint_rollup
Section titled “endpoint_rollup”Per-minute nonempty HTTP routes by namespace, service, kind and status. Retains the 128 most frequent routes per service-minute (lexical ties); all others merge into Other routes (overflow), flagged by overflow. Named routes can be partial across minutes; route-value filters stay raw. Counts and histograms include the overflow population. Percentiles and freshness follow span_rollup.
| Column | SQL type | Means |
|---|---|---|
namespace | VARCHAR | Service namespace |
bucket | TIMESTAMP_NS | UTC minute bucket |
service | VARCHAR | Service name |
kind | VARCHAR | Span kind |
status | VARCHAR | Span status |
route | VARCHAR | HTTP route or overflow label |
overflow | BOOLEAN | Combined routes beyond the minute cap |
spans | BIGINT | Span count |
duration_sum | DOUBLE | Sum of span durations |
duration_min | DOUBLE | Minimum span duration |
duration_max | DOUBLE | Maximum span duration |
hist | MAP(INTEGER, UBIGINT) | Scale-3 duration histogram, as span_rollup |
log_rollup
Section titled “log_rollup”Per-minute log counts by namespace, service and severity. Structured count, rate and share queries route here at minute precision; fresh_to_ms shares the service ingest horizon.
| Column | SQL type | Means |
|---|---|---|
namespace | VARCHAR | Service namespace |
bucket | TIMESTAMP_NS | UTC minute bucket |
service | VARCHAR | Service name |
severity | VARCHAR | Log severity text |
logs | BIGINT | Log events |
receiver_entity_rollup
Section titled “receiver_entity_rollup”Per-minute reporting witnesses collapsed across CPUs, states, mounts and HTTP status classes. Readers bridge adjacent minutes for cadence; only the affected minute needs invalidation. Analytical minute summaries share the service rollup affected-key, late-arrival and retention lifecycle. fresh_to_ms reports the ingest horizon. No raw boundary reads. Window boundaries have minute precision; counter overlap within a boundary minute is proportional to covered time.
| Column | SQL type | Means |
|---|---|---|
namespace | VARCHAR | Service namespace |
bucket | TIMESTAMP_NS | UTC minute bucket; filter with $__window(bucket) |
service | VARCHAR | Service name |
receiver | VARCHAR | Fixed receiver entity/family dimension |
family | VARCHAR | Fixed receiver entity/family dimension |
entity | VARCHAR | Fixed receiver entity/family dimension |
host | VARCHAR | Fixed receiver entity/family dimension |
container_id | VARCHAR | Fixed receiver entity/family dimension |
container_name | VARCHAR | Fixed receiver entity/family dimension |
endpoint_from | VARCHAR | Fixed receiver entity/family dimension |
first_observation | STRUCT(time TIMESTAMPTZ_NS, flag INTEGER) | First or last two distinct reporting times in this minute; check flag 2 is unsupported metadata, 1 success, 0 failure |
previous_observation | STRUCT(time TIMESTAMPTZ_NS, flag INTEGER) | First or last two distinct reporting times in this minute; check flag 2 is unsupported metadata, 1 success, 0 failure |
last_observation | STRUCT(time TIMESTAMPTZ_NS, flag INTEGER) | First or last two distinct reporting times in this minute; check flag 2 is unsupported metadata, 1 success, 0 failure |
receiver_points
Section titled “receiver_points”First and last two distinct finite witnesses per receiver series-minute; httpcheck.status preserves nonfinite observations for metadata diagnosis. Raw cadence witnesses remain in receiver_rollup. Intermediate scrapes are summarized; these are not raw metric points. Analytical minute summaries share the service rollup affected-key, late-arrival and retention lifecycle. fresh_to_ms reports the ingest horizon. No raw boundary reads. Window boundaries have minute precision; counter overlap within a boundary minute is proportional to covered time.
| Column | SQL type | Means |
|---|---|---|
namespace | VARCHAR | Service namespace |
bucket | TIMESTAMP_NS | UTC minute bucket; filter with $__window(bucket) |
service | VARCHAR | Service name |
series_id | VARCHAR | Identity of the fixed receiver dimensions, independent of other OTLP labels |
name | VARCHAR | Metric name |
type | VARCHAR | Metric type |
temporality | VARCHAR | Metric temporality |
unit | VARCHAR | Metric unit |
scope_name | VARCHAR | Metric scope_name |
resource | VARIANT | host.name and container.id/name only |
attributes | VARIANT | state, cpu, mountpoint, device, http.url/method/status_class/status_code only |
host | VARCHAR | Projected receiver dimension |
container_id | VARCHAR | Projected receiver dimension |
container_name | VARCHAR | Projected receiver dimension |
state | VARCHAR | Projected receiver dimension |
cpu | VARCHAR | Projected receiver dimension |
mountpoint | VARCHAR | Projected receiver dimension |
device | VARCHAR | Projected receiver dimension |
url | VARCHAR | Projected receiver dimension |
method | VARCHAR | Projected receiver dimension |
class | VARCHAR | Projected receiver dimension |
code | VARCHAR | Projected receiver dimension |
time | TIMESTAMPTZ_NS | Actual witness event time |
value | DOUBLE | Metric value |
start_time | TIMESTAMPTZ_NS | Counter interval start |
ingested_unix_nano | BIGINT | Retry ordering |
receiver_rollup
Section titled “receiver_rollup”Fixed-dimension summaries for httpcheck, hostmetrics and docker_stats. Retains first and last two witnesses (all and finite) per minute plus reset-aware counter totals. Analytical minute summaries share the service rollup affected-key, late-arrival and retention lifecycle. fresh_to_ms reports the ingest horizon. No raw boundary reads. Window boundaries have minute precision; counter overlap within a boundary minute is proportional to covered time.
| Column | SQL type | Means |
|---|---|---|
namespace | VARCHAR | Service namespace |
bucket | TIMESTAMP_NS | UTC minute bucket; filter with $__window(bucket) |
service | VARCHAR | Service name |
series_id | VARCHAR | Identity of the fixed receiver dimensions, independent of other OTLP labels |
name | VARCHAR | Metric name |
type | VARCHAR | Metric type |
temporality | VARCHAR | Metric temporality |
unit | VARCHAR | Metric unit |
scope_name | VARCHAR | Metric scope_name |
resource | VARIANT | host.name and container.id/name only |
attributes | VARIANT | state, cpu, mountpoint, device, http.url/method/status_class/status_code only |
host | VARCHAR | Projected receiver dimension |
container_id | VARCHAR | Projected receiver dimension |
container_name | VARCHAR | Projected receiver dimension |
state | VARCHAR | Projected receiver dimension |
cpu | VARCHAR | Projected receiver dimension |
mountpoint | VARCHAR | Projected receiver dimension |
device | VARCHAR | Projected receiver dimension |
url | VARCHAR | Projected receiver dimension |
method | VARCHAR | Projected receiver dimension |
class | VARCHAR | Projected receiver dimension |
code | VARCHAR | Projected receiver dimension |
first_point | STRUCT(time TIMESTAMPTZ_NS, value DOUBLE, start_time TIMESTAMPTZ_NS, ingested_unix_nano BIGINT) | Time, value, start_time and ingested_unix_nano of the retry-deduplicated witness |
last_point | STRUCT(time TIMESTAMPTZ_NS, value DOUBLE, start_time TIMESTAMPTZ_NS, ingested_unix_nano BIGINT) | Time, value, start_time and ingested_unix_nano of the retry-deduplicated witness |
previous_point | STRUCT(time TIMESTAMPTZ_NS, value DOUBLE, start_time TIMESTAMPTZ_NS, ingested_unix_nano BIGINT) | Time, value, start_time and ingested_unix_nano of the retry-deduplicated witness |
first_finite_point | STRUCT(time TIMESTAMPTZ_NS, value DOUBLE, start_time TIMESTAMPTZ_NS, ingested_unix_nano BIGINT) | Time, value, start_time and ingested_unix_nano of the retry-deduplicated witness |
last_finite_point | STRUCT(time TIMESTAMPTZ_NS, value DOUBLE, start_time TIMESTAMPTZ_NS, ingested_unix_nano BIGINT) | Time, value, start_time and ingested_unix_nano of the retry-deduplicated witness |
previous_finite_point | STRUCT(time TIMESTAMPTZ_NS, value DOUBLE, start_time TIMESTAMPTZ_NS, ingested_unix_nano BIGINT) | Time, value, start_time and ingested_unix_nano of the retry-deduplicated witness |
counter_increase | DOUBLE | Reset-aware increase within the minute; first point bridges the prior minute |
counter_seconds | DOUBLE | Covered counter intervals within the minute |
resource_inventory
Section titled “resource_inventory”Distinct full resource identities per signal, namespace and service observed inside the logical panel window [start,end). Panel SQL only; unavailable to structured query.from, variables and unscoped SQL. count(*) counts resource identities per signal, not events or instances. Resource extrema describe actual observations inside the selected window. Uncached interior batches are omitted; fresh_to_ms discloses the complete ingest horizon. Complete cached seconds summarize boundary files; only partial-second observations read raw Parquet.
| Column | SQL type | Means |
|---|---|---|
signal | VARCHAR | spans, logs or metrics; select the required signal |
namespace | VARCHAR | Original resource namespace, preserving NULL and empty values |
service | VARCHAR | Original service name, preserving NULL and empty values |
resource | VARIANT | Complete typed resource; use resource[‘key’], with dotted keys written literally |
first_seen | TIMESTAMPTZ_NS | Earliest actual event observation inside the selected panel window |
last_seen | TIMESTAMPTZ_NS | Latest actual event observation inside the selected panel window |
resource_rollup
Section titled “resource_rollup”Resource version/SDK/runtime and host tuples at minute precision. Filter bucket with $__window(bucket). Exact inventory remains available through resource_inventory. Analytical minute summaries share the service rollup affected-key, late-arrival and retention lifecycle. fresh_to_ms reports the ingest horizon. No raw boundary reads. Window boundaries have minute precision; counter overlap within a boundary minute is proportional to covered time.
| Column | SQL type | Means |
|---|---|---|
namespace | VARCHAR | Service namespace |
bucket | TIMESTAMP_NS | UTC minute bucket; filter with $__window(bucket) |
service | VARCHAR | Service name |
signal | VARCHAR | spans, logs or metrics |
resource | VARIANT | host.name, service.version, process.runtime.name/version, telemetry.sdk.language/version only |
first_seen | TIMESTAMPTZ_NS | First actual observation in the minute |
last_seen | TIMESTAMPTZ_NS | Last actual observation in the minute |
service_rollup
Section titled “service_rollup”Per-service analytical rollup by namespace and time bucket. Panel SQL only; filter bucket with $__window(bucket).
| Column | SQL type | Means |
|---|---|---|
namespace | VARCHAR | OpenTelemetry service namespace |
bucket | TIMESTAMP | Rollup time bucket |
service | VARCHAR | Service name |
spans | BIGINT | Total spans |
served_spans | BIGINT | Spans describing work performed by this service |
p50_ms | DOUBLE | Median service latency |
p95_ms | DOUBLE | 95th percentile service latency |
error_rate | DOUBLE | Error rate |
log_count | BIGINT | Log events |
metric_count | BIGINT | Metric data points |
span_rollup
Section titled “span_rollup”Per-minute spans by namespace, service, kind and status. Panel SQL only; filter bucket with $__window(bucket). Counts and duration aggregates merge across rows. Percentiles interpolate merged fixed-scale-3 OpenTelemetry exponential histograms and are approximate within one positive bucket (9.05%). Structured RED panels route here at minute resolution; fresh_to_ms reports the ingest horizon, usually 1–1.5 minutes behind ingestion. Window boundaries have minute precision.
| Column | SQL type | Means |
|---|---|---|
namespace | VARCHAR | OpenTelemetry service namespace |
bucket | TIMESTAMP_NS | UTC minute bucket |
service | VARCHAR | Service name |
kind | VARCHAR | Span kind |
status | VARCHAR | Span status |
spans | BIGINT | Span count |
duration_sum | DOUBLE | Sum of span durations |
duration_min | DOUBLE | Minimum span duration |
duration_max | DOUBLE | Maximum span duration |
hist | MAP(INTEGER, UBIGINT) | Duration bucket counts: ceil(log2(duration_ms)*8); -2147483648 represents zero or negative durations |
Authentication
Section titled “Authentication”MCP uses OAuth tokens bound to the instance’s resource URI.
Connect an agent documents protocol
requirements and delegated scopes. Dashboard tools operate on the authenticated
user’s own dashboards and require the account capability
dashboards:manage-own; see roles.
Other interfaces
Section titled “Other interfaces”Use OTLP to write telemetry. Configuration uses environment variables, and user and alert management use the HTTP API.