> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vexlo.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# The execution graph

> Understand recorded calls, their relationships, captured data, timing and completeness.

Vexlo records executions of instrumented entry points, such as request handlers or background
tasks. A recording combines the calls that ran, their relationships and the data captured for
each call. It describes one observed execution rather than all behavior possible in the code.## From an execution to a graphConsider a checkout that calculates the price of two line items, applies a discount and adds
tax. This recording captures the entry point and five functions involved in that calculation.
One function runs twice, producing seven recorded calls:<picture><source media="(max-width: 600px)" />
    ![Complete checkout recording: seven calls across four levels, with two line totals, a discount, tax and the final total.](https://docs.vexlo.ai/images/overview-execution.svg)</picture>`checkout` is the **root call**, the entry point at the top of the graph. `price_order` is its
recorded child. Below that, `price_lines` calls `line_total` for each order item, while
`discount_for` and `tax_for` calculate the adjustments to the subtotal.Calls sharing the same recorded parent are siblings. That relationship alone does not imply
that they ran simultaneously or in completion order.An edge connects a call to its nearest recorded parent. It does not prove that the parent
called it directly in the source. In another captured execution, an instrumented `operation`
called an uninstrumented helper, which called instrumented `read_part`. The recording contains
`operation` and `read_part`, with the latter directly beneath the root. The helper still ran;
it was outside the instrumentation boundary.This is an observed execution graph. A static call graph describes relationships inferred
from code, including paths that a particular request did not take. Vexlo's recordings provide
the complementary evidence of instrumented paths that executed and the values they saw.## Traces, recorded calls and call identityA **trace** is the recording of one instrumented entry-point execution. Its identifier,
`trace_id`, lets a reader find the same recording through the UI, HTTP API or MCP. A **step**
is a recorded function call within that trace. Its `path` identifies the call, and
`parent_path` identifies the recorded parent. The root has no parent, and its own `path` is
the empty string.The checkout recording contains two `line_total` steps. They have the same function name but
different paths because the application invoked the function for two line items. A function
name identifies the function within its service; a step path identifies a call in this execution.
Recorded names are module-qualified, such as `order_service.line_total`. Copy the full `name`
when querying a function.Paths are opaque. Use them unchanged to select values or relate a child to its parent; do not
decode them to infer order, source locations or function identity. Structural tree order helps
navigate a recording, while timestamps describe when its calls ran.An entry-point marker inside an existing trace adds a step to that recording instead of
starting another trace. A step marker outside an active trace does not start a recording.## The data attached to a callEach completed attempt can have captured **inputs**, **output**, **error** and **logs**.
Inputs describe arguments received by the function. Output describes its return value. Error
data describes an exception, while log entries belong to the attempt during which they were
captured. Log capture is opt-in.In this recording, `price_order` received these arguments, decoded from its recorded
JSON input:```json theme={"system"}
{
  "customer": {
    "customer_id": "customer-17",
    "loyalty_member": true
  },
  "lines": [
    {
      "quantity": 2,
      "sku": "notebook"
    },
    {
      "quantity": 3,
      "sku": "pen"
    }
  ]
}
```It returned:```json theme={"system"}
{
  "discount_cents": 330,
  "subtotal_cents": 3300,
  "tax_cents": 238,
  "total_cents": 3208
}
```The output explains the final checkout amount: the two line totals produced the subtotal,
then discount and tax produced the final total. Reading successful calls is useful for
understanding calculations and data transformations, independently of failures.Captured data is a bounded representation of what the function saw. Supported adapters can
convert objects into mappings; unsupported types can appear as type descriptions, and capture
limits can truncate values. A recorded representation is not a promise that the original
object, its identity or its external dependencies can be reconstructed automatically.When using captured inputs for a test, select data whose representation is understood, check
availability and truncation, and construct the application types and fixtures the test needs.
See [Capture controls](https://docs.vexlo.ai/instrumentation/capture.md) and [Python API](https://docs.vexlo.ai/reference/python.md) for the
capture behavior and limits.## Attempts and retriesAn **attempt** is one execution of a recorded call. A retrying call has several attempts,
each with its own status, timing and capture metadata. A more extensively instrumented
checkout recording also captures payment. That call failed on the primary processor and
succeeded on the backup processor:| Attempt | Status | Error class | Duration (µs) |
| - | - | - | - |
| `0` | `error` | order\_service.PaymentGatewayUnavailable | 62 |
| `1` | `ok` | (absent) | 8 |The application performs retries. Vexlo records and groups them. The SDK supports declared
retry grouping and inference from qualifying repeated calls; the exact matching rules are in
[Python API](https://docs.vexlo.ai/reference/python.md#markers-and-callable-behavior). Declaring a retry does not cause the
SDK to rerun a function after an error.The two successful `line_total` calls remain separate steps. The two executions of
`authorize_payment` appear as attempts of one step. This preserves the distinction between
repeated work for different items and repeated attempts to complete a logical operation.
A successful recovery does not erase the earlier failure.Per-attempt previews, status and timing retain attempt identity. The trace-values route,
`/v1/traces/{id}/values`, selects paths and slots without an attempt selector or attempt
identity in its results. Do not assign an arbitrary returned value to a numbered retry
attempt. The [recorded-values guide](https://docs.vexlo.ai/guides/values.md) explains this current interface limitation.## Timing and concurrent workEach attempt records a start offset from the trace's start and, when completed, its elapsed
duration. These describe elapsed intervals measured by a monotonic clock, not exclusive CPU
time. A parent can remain active while its children run, and concurrent children can overlap.A separate captured operation started two reads concurrently. The profile read started first,
but the preferences read finished first:| Call | Start offset (µs) | Duration (µs) |
| - | - | - |
| `operation` | 0 | 27668 |
| `read_part: profile` | 713 | 26778 |
| `read_part: preferences` | 829 | 12537 |Adding the two child durations would overstate the operation's elapsed time because part of
their work overlapped. Structural call order is also different from completion order. Use the
[Timeline view](https://docs.vexlo.ai/guides/execution-graphs.md) to inspect intervals and the Table view to examine
individual calls.A step's total duration is the sum of its completed attempts. It excludes unfinished attempts
and does not measure the entire interval between the first attempt's start and a later retry's
completion. For an ongoing retry, that total is a lower bound rather than a final duration.An attempt with no reported completion has no completed duration. It can still be running,
but a lost completion record leaves the same evidence.## Execution status and recording completenessThe entry point's status, a call attempt's status and the recording's completeness answer
different questions. Two captured executions illustrate the distinction:| Execution | Root status | Error steps | Completeness |
| - | - | - | - |
| `failed-root` | `error` | 1 | `complete` |
| `handled-error` | `ok` | 1 | `complete` |In `failed-root`, the entry point raised an error after a successful read. In `handled-error`,
the entry point caught a child's exception and returned a rejection response normally. Both
recordings arrived completely. Neither business success nor failure determines completeness.| Field | Meaning |
| - | - |
| `root_status` | Whether the recorded entry point returned normally (`ok`) or raised an error (`error`). |
| Attempt `status` | Whether that execution completed successfully, failed, or has a reported start without a completion. |
| `completeness` | Whether the root completion and records arrived without reported loss or other completeness conditions. |A running recording has no root completion and has received recent data. An abandoned one
still has no root completion after the inactivity window. A complete recording has a root
completion without reported loss, shedding, truncation or instance mismatch; a partial one has
a root completion and at least one of those conditions. These states are derived when data is
read, so later arrivals can change the result.Completeness does not establish that every possible function was instrumented or that every
branch ran. Inspect completeness and loss information
before interpreting a missing call or unfinished attempt.## Connect recordings to code and other requestsFunction metadata aggregates observed callers, callees and examples across recordings. Use
these relationships to find executions relevant to a function and inspect how it was used.Use application-revision provenance when relating a recording to source or comparing runs
around a change. A user-defined revision tag can identify the application version. The
`sdk_version` field identifies the SDK, not the application's code revision. A captured stack
line does not establish that the reader's current checkout contains the same code at that line.A **tag** is a key/value pair attached to a trace. Shared identifiers, such as an order or
request ID, can find recordings across services. Those recordings remain separate traces.
Sharing a tag relates the records; it does not prove one service called another or supply an
automatic cross-service call edge.## Inspecting calls and dataA recording connects each call with its timing, attempts and captured data. In the UI, follow
the calls first, then select the function whose arguments, return value or error you need.
Previews let you inspect a call before fetching its full value.A preview can remain after full value bytes become unavailable. Fetch the selected value to
check what is readable now. [Inspect recorded values](https://docs.vexlo.ai/guides/values.md) explains capture states,
truncation and unavailable data; [Retention](https://docs.vexlo.ai/deployment/retention.md) explains how long the
recording and its values remain available.For agent queries, [Use execution data](https://docs.vexlo.ai/agents/use-data.md) explains how to choose reads and
manage payloads in the agent's working context.## How recorded data reaches readers```mermaid theme={"system"}
flowchart TD
  A[Application + SDK] --> Q[Local queue]
  Q --> R[Relay on application host]
  R --> S[Vexlo server]
  S --> U[Web UI]
  S --> H[HTTP API]
  H --> M[MCP server]
  M --> C[AI agent]
  classDef component fill:#eff6ff,stroke:#64748b,color:#0f172a,stroke-width:1px;
  class A,Q,R,S,U,H,M,C component;
```The SDK records inside the application and writes locally. A relay on the application host
forwards those records to the server. The server stores the recording and serves it through
the UI and HTTP API. The MCP process reads that API for an AI agent; it does not collect
application execution itself.The SDK's flush operation requests a local drain. It does not confirm disk success or server
ingestion. Relay and server health checks describe their own boundaries; observing a trace
and its values confirms delivery of that recorded execution to the read interface.Continue with [Why execution graphs](https://docs.vexlo.ai/why-execution.md) for the rationale,
[Quickstart](https://docs.vexlo.ai/quickstart.md) for a first execution,
[Explore execution graphs](https://docs.vexlo.ai/guides/execution-graphs.md) for UI navigation, or
[AI agents](https://docs.vexlo.ai/agents.md) for agent access to this data.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.