Data model
Workspaces, projects, environments, runs, spans, sessions, prompts and scores, and how they nest.
On this page
Everything in Tracehatch hangs off a run. Understanding five nouns is enough to read any screen.
Tenancy
- Workspace
- Billing and membership. Owns projects.
- Project
- One agent or product surface. Owns keys and runs.
- Environment
- production · staging · development
- Ingest key
- Selects one project and one environment
A workspace is the boundary for members, roles and the plan. It is created with your account.
A project is one agent or product surface — "Support Agent", "Docs RAG". It owns its environments, ingest keys, runs and settings. The Free plan allows three active projects; sample projects do not count.
Every project is created with three environments: production (the
default), staging and development. Every run belongs to exactly one. Custom
environments are not available yet.
An ingest key selects the project and the environment, which is why there
is no environment setting in the SDK: change the key, change where runs land.
Production keys start with th_live_, every other environment th_test_.
Runs and spans
A run — called a trace in the API and a run in the UI — is one end-to-end execution of your agent: a tree of spans with a status, duration, reported token totals and cost.
A span is one step inside a run. Each span has a kind:
| Kind | What it is |
|---|---|
agent | A logical stage of the agent's work. |
generation | A model call. Carries the model, provider, usage, finish reason and bodies. |
tool | A function or external API the agent invoked, with arguments and output. |
retrieval | A lookup against a store or index. |
embedding | An embedding request. |
guardrail | A safety or validation check. |
custom | Anything else you want on the timeline. |
Runs and spans share a status: pending, ok, error or cancelled. A run is
marked failed when its handler answered with a 5xx, when a span failed, or when
the explicit trace() callback threw.
Ids are prefixed and sortable: run_01j9xk3m4np6q7r8s9t0v1w2x3, span_…,
sess_…, proj_…. Pasting a full trace id into the command palette opens it.
Sessions and end users
A session is a sequence of runs belonging to one conversation. A run joins a
session automatically — from the x-tracehatch-session-id header, an explicit
setSession(), the provider's own conversation id, or a fingerprint of the
system prompt and first user message that every later turn resends. Derived ids
look like auto- followed by 32 hex characters and are identical across
processes, restarts and the gateway.
An end user is whoever the conversation belongs to: the
x-tracehatch-user-id header, setUser(), the OpenAI user field or Anthropic
metadata.user_id. A recorded user gets a page with their sessions, lifetime
runs, failure rate and recorded cost.
Neither is a Tracehatch account. See Sessions and end users.
Prompts and versions
A prompt is the system prompt a model call carried, identified by its opening line. Each distinct text below that line is a version, hashed after line endings, surrounding whitespace, timestamps and ids are normalised — so an interpolated date does not make every call its own version.
Only the two hashes and the opening line travel on the span, so prompts, versions, usage and cost exist even with body capture off; there is simply no text to show or diff. A prompt that still changes on every call is marked dynamic at 50 versions.
Agents and releases
An agent is a named actor inside a project, taken from the nearest
package.json name or TRACEHATCH_AGENT. A release is the deployment's
commit, from platform variables, git HEAD, or TRACEHATCH_RELEASE. Both sit
on the run, so the dashboard can compare agents and you can tell which build
produced a failure.
Scores and comments
A score is feedback on a run or one of its spans. It comes from a person
(thumbs up or down with an optional comment, in the trace view) or from your
code (score(), numeric or categorical). Both are private
to project members and follow the run's retention.
A comment is a private note a teammate leaves on one span. Scores and comments never appear on a public share link.
Cost
Cost is computed per span from the model, the provider and the reported token usage, including cached and reasoning tokens where the provider reports them. A model without price coverage is still counted and timed; it simply contributes no recorded USD, and the UI says so rather than showing a zero as if it were free.