What Otis records
Spans
The unit of telemetry that Otis receives from your app, what a span holds, and what happens to it on the way in.
A span is one recorded operation in your app, such as an AI call, a tool call, a traced function or a custom event. Each span has a name, a start time, a duration, a status and a set of attributes. Otis stores every span it accepts, and builds everything else from them: tasks, sessions, signals and the numbers in an insight.
This page is a short reference for what a span holds and what Otis does to it before storing it. The SDK guides cover how your app produces spans.
Kinds of span
| Kind | Produced by | How Otis recognizes it |
|---|---|---|
| AI call | Wrapping your AI client, including a decision model call, or a GenAI instrumentation | A wrapper's span name, such as openai.responses.create or openrouter.chat.send, or a gen_ai.operation.name such as chat |
| Tool call | A tool your AI calls, or an instrumented MCP server or command-line tool | ai.tool.<name>, mcp.tool.<name> or cli.tool.<name>, or gen_ai.operation.name execute_tool |
| Agent | The span around one execution of an agent, such as a Vercel AI SDK generateText call, a ToolLoopAgent or a Claude Agent SDK query() | A wrapper's span name, or gen_ai.operation.name invoke_agent |
| Traced function | traced() | The name you give, or the function's own name |
| Custom event | sendEvent() | The name you give. An event has no duration. |
| Feedback | sendFeedbackSignal() | feedback.<name> |
| Reported exception | sendException() | otis_exception |
Otis reads the OpenTelemetry GenAI conventions as well as the SDK's own span names, so AI calls, tool calls and agents from a GenAI instrumentation are recognized too. Otis groups the spans of one agent's execution into an , which Agent runs describes.
Calls that describe a user or a group, such as identifyUser and setUserProperties, are not stored as spans. Otis stores what they declare as properties.
Span contents
- Where it belongs. The user, session, chat, document and surface that the operation belongs to, and the agent if your app names one. Your app sets these, and the SDK carries them onto each span.
- Trace. The trace ID that links the span to the other spans recorded for the same request, as OpenTelemetry defines a .
- Messages. For an AI call, the user's message and the AI's response.
- Tool input and output. For a tool call, what was passed in and what came back. Otis keeps these apart from messages and never reads them as conversation.
- Model and usage. For an AI call, the model, the provider, the input and output tokens, and how quickly the response arrived.
- Status and cause. Whether the operation succeeded, and the cause if it failed.
- Attributes. Everything else your app attached, such as the properties of a custom event.
Ingest handling
- User and session IDs are hashed. By default the SDK hashes them before they leave your app, and Otis hashes them again with a secret that belongs to your project. Otis stores the hashed values. Users, groups and accounts covers this in more detail.
- Personal data is redacted. The SDK redacts text in your app, and Otis redacts again when it receives the span. Both are on by default. Privacy describes what is scanned.
- Long values are cut. A single attribute value is cut at 64 KiB. A conversation history longer than that keeps its most recent messages whole and drops the oldest, and its first entry says that earlier messages were removed. A model's output keeps its first choices and says at the end that later ones were removed. A single message longer than the limit is cut, and its text ends with
…[otis:truncated]. - Spans with an implausible time are rejected. Otis rejects a span that started more than 48 hours in the past or more than one hour in the future.
- Only production spans are analyzed. Spans sent with a development Ingest Key, or from an environment your project has excluded, are kept for 24 hours and are left out of all analysis.
Otis keeps every production span it accepts. It doesn't sample them.
Retention
Otis keeps a production span for 90 days. The records it builds from spans last for different periods: tasks and agent runs are kept for 90 days, and session summaries are kept for 365 days.
Spans in Otis
The data browser has a list of spans that shows each span's type, status, error cause, model, surface, agent and signals. You can filter the list, for example by surface, agent, error cause or signal. Opening a span shows its details, with a separate tab for its attributes.
A sender that doesn't use the Otis SDK usually names the agent only on the agent's own span. Filtering by agent then finds that span and not the AI calls and tool calls under it.
Related
- Tracing covers AI calls, traced functions and how context is carried onto each span.
- Custom events covers recording actions that involve no AI call.
- Privacy covers hashing and redaction in detail.
- Tasks covers how Otis groups the spans in a session into units of work.