OtisDocs

What Otis records

Surfaces

What a surface is, how your app names one, and how Otis uses surfaces to keep the parts of your product apart.

A surface is a named part of your product that users work in, such as one copilot, one MCP server or one command-line tool. Your app chooses the names. Otis stores the surface on each span and uses it to keep activity in different parts of your product apart.

This page explains how a surface is set and where it changes what Otis does. A service name says which codebase produced a span. A surface says which part of the product the user was in, and one service often hosts several.

Purpose of surfaces

Many products have more than one place where users work with AI. A chat assistant and an inline editor may live in the same app and share a session, and they succeed or fail for different reasons. Without a surface, their activity runs together. With one, Otis can find tasks in each part separately and report errors against the part where they happened.

Surface assignment

Surface describes the SDK options. In summary:

  • For a whole app. Set surface when you initialize the SDK, and every span from that app carries it.
  • For one flow. Set surface in the context for a flow. This overrides the app's default for the spans in that flow.
  • For an MCP server. Set surface in the server's options. If you leave it out, the app's default applies.
  • For a command-line tool. The surface defaults to the tool's name.

Otis stores the surface exactly as you send it. A span with no surface has an empty one. Choose a small set of stable names, because each distinct name is treated as a separate part of your product.

Effects of a surface

Task detection

Otis finds tasks within each surface separately. How strictly it does so depends on the kind of task:

  • Activity tasks are found per surface. Otis measures idle time within one surface, so activity elsewhere doesn't keep a burst open.
  • Conversation tasks are grouped by chat ID first. A chat stays together even if its messages carry different surfaces. The surface separates only the messages that have no chat ID.
  • Tool tasks are grouped by chat ID and surface together. Calls to two surfaces are separate tasks even inside one chat.

Each task records every surface that its spans carried.

Error reporting

Otis counts failures for each operation on each surface. An insight about a failing operation names the surface, so the same operation in two parts of your product is reported as two findings.

Session descriptions

When Otis writes a narrative for a session, it records the surface of each step and the points where the user moved from one surface to another.

Answers in chat

When you ask Otis to compare parts of your product in chat, it compares by surface.

Reading surfaces

  • Label all of a flow, or none of it. If only some spans in a flow carry a surface, Otis treats the labeled and unlabeled spans as two different surfaces. In a session that mixes conversation and product actions, unlabeled actions then form tasks of their own.
  • An empty surface is a surface. Spans with no surface are grouped together, apart from every named surface.
  • Names are compared exactly. Otis doesn't change the case of a surface or trim it, so Copilot and copilot are different surfaces.

Surfaces in Otis

In the data browser, the span list and the task list each have a Surface column and a filter. Opening a span or a task shows its surface.

  • Surface covers the SDK options in full.
  • Tasks covers how surfaces affect where task boundaries fall.
  • Errors covers how failures are counted for each operation and surface.

On this page