Run reports

The report sent for an assistant response, its limits and outcomes, and how it becomes a run in Assistant Cloud.

Every persisted assistant response can send one run report to Assistant Cloud. The report records the response, model work, tools, timing, deployment dimensions, and errors. A report the SDK builds carries the assistant's text and the tool arguments and results, never the user's messages. A report you send yourself can add steps[].input, which stores whatever you put there, a user's prompt included. The dashboard turns that record into the Runs, Models, Users, and Overview views.

Reports can contain assistant text, tool arguments and results, step input and error text, and tool arguments often quote the user. Use beforeReport to remove or redact those values before they leave the app, or turn telemetry off when the project should store threads and messages without reports or engagement events.

What a report accepts

cloud.runs.report() sends POST /v1/runs. thread_id and status are required. Every other field is optional, but the endpoint validates its type and bound before it writes the run.

FieldType and boundMeaning
thread_idstring, 1 to 255 charactersThe cloud thread the run belongs to.
statuscompleted, incomplete, or errorThe terminal state of the response.
message_idstring, 1 to 48 charactersThe persisted assistant message that produced the run.
outcome_typerate_limited, validation_failed, provider_error, server_error, budget_denied, persistence_error, aborted, timeout, disconnected, length, or content_filterThe more specific reason for a noncompleted response.
error_codestring, 1 to 64 charactersA machine readable failure code.
errorstring, 1 to 2,048 charactersThe failure message.
tagsUp to 20 distinct nonempty strings, each trimmed to 1 to 64 charactersLabels for filtering runs.
environmentstring, 1 to 64 charactersThe deployment environment.
releasestring, 1 to 255 charactersThe application release.
total_stepsinteger, 0 or moreThe number of model steps when steps is not supplied.
stepsArray of up to 1,000 step objectsThe model steps in the response. Step fields defines each object.
tool_callsArray of up to 1,000 tool call objectsTool invocations outside a step, with optional nested sampling calls. Tool call fields defines each object.
input_tokens, output_tokens, reasoning_tokens, cached_input_tokensInteger from 0 to 100,000,000Whole run usage.
model_idstring, 1 to 255 charactersThe model identifier reported by the producer.
providerstring, 1 to 255 charactersThe provider that served the model.
provider_typestring, 1 to 255 charactersLegacy alias for provider. It becomes provider only when provider is absent, then is removed.
duration_ms, first_token_msInteger, 0 or moreElapsed time to completion and to the first token.
cost_detailsObject with optional finite, nonnegative input, input_cached_tokens, output, and total numbersCaller supplied cost components.
cost_usdFinite number, 0 or moreCaller supplied total cost. It takes precedence over catalog pricing.
output_textstring, up to 50,000 charactersThe assistant text shown with the run.
metadataRecord with string keys and values of any typeLegacy alias for attributes.
attributesRecord with string keys and values of any typeRun attributes shown in the run detail view.
trace_idstring, 1 to 48 charactersA trace identifier. A valid W3C value merges the report with server spans that share it.
root_span_id16 lowercase hexadecimal charactersThe root span identifier when the caller has one.

Step fields

Each steps item may include the following fields. Step usage has the same integer 0 to 100,000,000 bound as run usage.

FieldType and boundMeaning
input_tokens, output_tokens, reasoning_tokens, cached_input_tokensInteger from 0 to 100,000,000Usage for that model step.
tool_callsArray of up to 1,000 tool call objectsThe tool calls made in the step; Tool call fields defines each object.
start_ms, end_msInteger, 0 or moreThe step offsets from the start of the run.
finish_reasonstring, up to 32 charactersThe model's finish reason for that step.
inputstring, up to 50,000 charactersThe model input captured for the step.

Tool call fields

Each tool_calls item has a required name. The service generates tool_call_id when it is omitted.

FieldType and boundMeaning
tool_namestring, 1 to 255 charactersThe invoked tool.
tool_call_idstring, 1 to 255 charactersThe tool invocation id.
tool_args, tool_resultstring, each up to 50,000 charactersThe tool arguments and returned value. The SDK serializes them as JSON and truncates them at the limit.
tool_sourcemcp, frontend, or backendWhere the tool was provided.
start_ms, end_msInteger, 0 or moreThe tool offsets from the start of the run.
sampling_callsArray of up to 1,000 sampling call objectsNested model calls made by this tool.

Each sampling_calls item may have model_id of up to 255 characters, the four usage counters from 0 to 100,000,000, and duration_ms as an integer of 0 or more.

Attributes and size limits

The service combines metadata, unknown top level keys, and attributes in that order. Later attributes values win. The resulting attributes JSON must be at most 16,384 bytes. Unknown top level keys are kept as attributes instead of being rejected, so a newer SDK can send fields an older project does not yet recognize.

The route rejects invalid input with the validation response shape { "success": false, "error": "…" }. It also returns { "error": "message_id must belong to thread_id" } when the message is not in the named thread, and { "error": "Thread not found" } when the thread is not visible to the caller.

How the SDK builds a report

The thread history adapter reports a terminal assistant message after persistence. It combines the message derived state with the extracted format data, resolves the remote message id, and sends the resulting report. A message derived status and outcome take precedence over values extracted from the stored format.

IntegrationWhat it reportsWhat it cannot supply by itself
Local runtime with aui/v0Status, outcome, error, client duration and first token time, step timing, text, tool calls, and metadata based usage, model, provider, and trace id. Tool calls have no tool_source.Server model, provider, usage, and trace values unless the adapter places them in metadata.custom.
AI SDK runtime with ai-sdk/v6The same message state and timing, text across assistant messages, steps, tool calls, sampling calls, and usage. Static tools are frontend, dynamic tools are mcp, and a step that calls a tool is marked tool-calls.The provider finish reason for each step. It only observes the stored message.
LangGraph, LangChain, and Google ADKThe cloud thread list, titles, attachments, feedback, and engagement surface when configured with a cloud client.Messages and run reports, because these runtimes retain their own transcript. Send traces for their model work.

For both message formats, report construction reads only assistant messages. A message waiting for tool approval is not reported, so a paused run is not counted as completed or reported twice.

messageMetadata values

An AI SDK route must return server values through messageMetadata. The client cannot infer model, provider, usage, or trace id from the browser stream. The whole route, with the callback that fills the report:

app/api/chat/route.ts
import { convertToModelMessages, streamText } from "ai";
import { openai } from "@ai-sdk/openai";

export async function POST(req: Request) {
  const { messages } = await req.json();
  const model = openai("gpt-5.6-luna");
  const result = streamText({
    model,
    messages: await convertToModelMessages(messages),
  });

  return result.toUIMessageStreamResponse({
    messageMetadata: ({ part }) => {
      if (part.type === "finish") {
        return { usage: part.totalUsage, finishReason: part.finishReason };
      }
      if (part.type === "finish-step") {
        return { modelId: part.response.modelId, provider: model.provider };
      }
      return undefined;
    },
  });
}

Each key the callback returns maps to a report field:

Metadata keySDK behavior
usageBecomes the four run usage counters. It reads inputTokens or promptTokens, outputTokens or completionTokens, reasoningTokens or outputTokenDetails.reasoningTokens, and cachedInputTokens or inputTokenDetails.cacheReadTokens. When usage is absent, the SDK sums steps[].usage.
stepsSupplies per step usage for the AI SDK extractor.
modelIdBecomes model_id. A route can return it for a finished step.
providerBecomes provider.
finishReasonSupplies the outcome derivation unless the assistant message is already incomplete.
traceIdBecomes trace_id. For aui/v0, put it in metadata.custom.traceId; for ai-sdk/v6, put it in metadata.traceId.
samplingCallsA record keyed by tool call id. Each value becomes the matching tool call's sampling_calls.

The docs chat route illustrates the handoff. It adds modelId at finish-step, adds usage at finish, and wraps that callback with withAssistantCloudTraceMetadata so the start part carries traceId.

How status and outcome are derived

The SDK derives a status before it creates the report. The first matching input wins: isError, then isAbort, then isDisconnect, then finishReason. With no matching input, the fallback status is completed.

Input or outcome_typeResulting statusProduced today
isError: true, or finishReason: "error"error, with no outcome typeThe SDK when the persisted message is incomplete for error.
isAbort: true, finishReason: "cancelled", or abortedincompleteThe SDK.
isDisconnect: true or disconnectedincompleteNo shipped integration produces it today. The core runtimes do not observe the live connection.
lengthincompleteThe SDK from a message finish reason, and server spans.
content_filterincompleteThe SDK from content-filter or content_filter, and server spans.
timeout, rate_limited, provider_error, or server_errorerrorOnly runs executed by an Assistant Cloud assistant.
validation_failed, budget_denied, or persistence_errorerrorNo integration produces these values today. They remain valid filter vocabulary.

The Overview outcome chart groups values differently from the report vocabulary: completed, stopped for aborted, disconnected, truncated for length or content_filter, failed for every other outcome type, and unknown when there is no outcome type.

Normalization and delivery

createRunReport converts the runtime shaped input into the wire shape. It lowercases traceId and keeps it only when it is exactly 32 lowercase hexadecimal characters. It writes the provider to both provider and the legacy provider_type field, converts camel case fields to their wire names, makes total_steps equal steps.length when steps are present, and rounds finite timing values to the nearest nonnegative integer. Nonfinite timing values are omitted.

outputText is truncated at 50,000 characters. A message derived error is truncated at 2,048 characters and its code at 64 characters. A directly supplied report must still meet the route's 2,048 character error bound. Tags are trimmed, limited to 64 characters, deduplicated, and capped at 20. Empty usage stays absent rather than becoming four zeroes.

CloudRunReporter follows one delivery order:

  1. Return when telemetry is disabled or a supplied deduplication key was already sent.
  2. Build and normalize the report with the cloud telemetry configuration.
  3. Call beforeReport last. A returned null skips the request before claiming the deduplication key. A thrown callback is swallowed.
  4. Claim the key, when one was supplied, then send the report.

The reporter swallows send failures. It releases a claimed key only after a 429 response, so a later observation may send that report again. It does not retry any other failure, and the standard thread history path supplies no key.

Deployment dimensions and clients

environment, release, and tags in the telemetry configuration are stamped on each client report. They become Run facets. release is your application version, not an SDK version.

const cloud = new AssistantCloud({
  baseUrl: process.env.NEXT_PUBLIC_ASSISTANT_BASE_URL!,
  anonymous: true,
  telemetry: {
    environment: "production",
    release: "2026.09.1",
    tags: ["web", "eu"],
  },
});

Every request also sends Aui-Sdk. It begins with assistant-cloud/<version>, followed by registered integration identities in registration order. The cloud records at most 8 header tokens, names of at most 214 characters, and versions of at most 64 characters.

Settings › Telemetry on the demo project

Settings › Telemetry lists those client names and versions, newest first, with the last time each was seen. A client entry is recorded at most once in 10 minutes and retained for 180 days. The page also gives the project API URL, the trace receiver URL, and the trace link template that turns a run's trace id into a link to your observability system.

When a client report meets server spans

A report with a valid W3C trace_id locks and merges into the existing run for the same project and trace id. Either side may arrive first.

Field familyMerge rule
message_id and tagsThe client report writes them.
outcome_typeThe client may write only aborted or disconnected.
thread_idThe client writes it only when the server run has no thread.
created_byThe client writes it only when the server run belongs to the unknown telemetry user.
environment and releaseThe client writes each only when the server has no value.
first_token_msThe client writes it only when the server value is absent. The client value is always copied to attributes.client.first_token_ms.
Model, provider, usage, duration, steps, and server span dataThe server keeps these values.

The merge replays the daily run rollup when a changed field affects it.

What the dashboard derives

Runs on the demo project

The Runs page has Status, Source, Reason, Model, Environment, Release, Agent, Service, Tag, Cost, and Duration facets. Its table shows status, model, user, environment, release, tokens, cost, duration, and creation time. The tiles show Runs, Incomplete, Cost, p95 duration, and First token p50. Search matches a run id, thread id, user, error, or error code.

The analysis view applies the same filters to latency percentiles, duration distributions and heatmaps, a run sample, tool statistics, release statistics, and model statistics. The run detail view shows outcome, source, thread, user, message, assistant, deployment fields, timing, usage, attributes, scores, and a span waterfall with the selected span's arguments or prompt.

Models are grouped by catalog model and provider, while retaining the reported model ids as variants. A model row includes runs, sampled runs, incomplete runs, all four token counters, cost, priced and unpriced run counts, and latency percentiles. Its Price section shows the model it was priced as and input, cached input, and output prices. A run with no model_id cannot name a model in this view or be catalog priced.

Redact, drop, or turn telemetry off

beforeReport receives the fully assembled report. Return a replacement report to redact data or add attributes. Return null to skip it.

const cloud = new AssistantCloud({
  baseUrl: process.env.NEXT_PUBLIC_ASSISTANT_BASE_URL!,
  authToken: getToken,
  telemetry: {
    beforeReport: (report) => {
      if (report.thread_id === internalTestThread) return null;
      return { ...report, metadata: { ...report.metadata, plan: "pro" } };
    },
  },
});
ConfigurationEffect
telemetry: falseStops run reports and engagement events. Threads and messages still persist.
telemetry: { events: false }Keeps run reports and stops engagement events.
telemetry: true or omittedEnables reports and engagement events.

Troubleshooting

What you seeWhyWhat to do
No new reports or engagement eventstelemetry is false.Enable telemetry. Use events: false only when reports should continue.
A report does not appear although the response persistedbeforeReport returned null, threw, or the send failed. Report delivery never surfaces an error to the UI.Check the callback result and the request. Only a later observation retries a report released after 429.
Runs are listed under no model and have no priceThe route did not put model, provider, and usage into messageMetadata.Return modelId, provider, and usage from the route.
A client run and server spans remain separateThe report has no valid 32 character hexadecimal trace id, or it does not match the server trace id.Wrap the route metadata with withAssistantCloudTraceMetadata and export the same trace.
The report returns message_id must belong to thread_idThe message id belongs to a different cloud thread.Send the persisted assistant message id for the report's thread.
The report returns Thread not foundThe caller cannot resolve that thread in its scope.Create or select the correct cloud thread before sending the report.
An expected tag, attribute, text, or token value is absentIt exceeded a report bound or was normalized away.Keep tags within 20 distinct 64 character values, attributes within 16,384 bytes, text within 50,000 characters, errors within 2,048 characters, and token counters at or below 100,000,000.