> ## 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.

# Follow an investigation

> Explain an incorrect checkout total using recorded calls, values, source and a regression test.

A checkout completes successfully but charges a loyalty customer 3564 cents. The expected
total is 3208 cents. This walkthrough follows the actual recording to the calculation that
produced the difference, then verifies a source correction.

The example has two order lines: two notebooks at 1200 cents each and three pens at 300 cents
each. Its business rule applies a 10% loyalty discount, then 8% tax on the discounted subtotal,
rounded to the nearest cent. Customer, catalog, inventory and payment responses are fixed local
data; no payment is sent or inventory changed.

The recording has fourteen call nodes and fifteen attempts. The two payment invocations are
recorded as attempts of one call. It includes a recovered payment error,
but the failed call is not the cause of the incorrect total.
Use fully qualified names in queries, such as `__main__.discount_for`.

The example records values with capture enabled and `value_sample_rate=1.0`. Available values
in your deployment depend on [capture controls](https://docs.vexlo.ai/instrumentation/capture.md) and retention.

Follow the same investigation with an identifier from your own service. To reproduce this
specific case, run the supplied local example first; it is separate from Quickstart's order
check and from the correctly priced graph in [The execution graph](https://docs.vexlo.ai/concepts.md).

## Record the example (optional)

Use the installed SDK and running server/relay from [Quickstart](https://docs.vexlo.ai/quickstart.md).
Set the queue directory in this terminal, replacing the path with the relay's absolute path:

```sh theme={"system"}
export VEXLO_SPOOL_DIR="/absolute/path/to/vexlo-spool"
```

The application and relay must access that same directory.

Open the [example sources](https://docs.vexlo.ai/examples/checkout.md#incorrect-and-corrected-checkout) and save
`checkout_service.before.py` and `checkout_service.after.py` in the directory containing `.venv`.

Run the original pricing implementation with its source fingerprint attached to the recording:

```sh theme={"system"}
cp checkout_service.before.py checkout_service.py
export APP_REVISION=$(.venv/bin/python -c \
  'import hashlib; print("sha256:" + hashlib.sha256(open("checkout_service.py", "rb").read()).hexdigest())')
VEXLO_ENABLED=1 VEXLO_CAPTURE_VALUES=1 VEXLO_VALUE_SAMPLE_RATE=1 \
  VEXLO_CAPTURE_ERROR_MESSAGE=1 .venv/bin/python checkout_service.py
```

Keep `APP_REVISION` when selecting this recording. After the correction below, run the corrected
source to produce a second revision of the same order.

## Find the request

With read access to an instance containing the execution, enter its order identifier in the
UI's home search. For this example, enter `order-1042` and submit **Search**. On the results
page, narrow **Service** to `checkout-investigation`. Distinguish the original and corrected
runs by their timestamp and `app_revision` tag. See [Search traces](https://docs.vexlo.ai/guides/search.md) for scope and
time controls.

Open the matching trace. Check the service, identifier, timestamp and application revision
before relating it to source code. In this capture, `app_revision` is a declared trace tag
containing a SHA-256 fingerprint of the application file. The entry point accepts that value
as an argument, declared through `tag_keys=["order_id", "app_revision"]`; see
[searchable identifiers](https://docs.vexlo.ai/instrumentation/python.md#add-searchable-identifiers).

The root status is `ok` and recording completeness is `complete`. The order handler returned
normally; neither field establishes that it calculated the intended price.

## Follow the calculation

Start with the graph. `checkout` calls `price_order`, which calls `price_lines`, `discount_for`
and `tax_for`. The line-pricing branch descends through two `line_total` calls, each with a
`unit_price` lookup. The later payment call consumes the price already calculated.

In the UI, select `price_order`, open **Output** and choose **fetch full value**. This read
returned:

```json theme={"system"}
{
  "discount_cents": 0,
  "subtotal_cents": 3300,
  "tax_cents": 264,
  "total_cents": 3564
}
```

The subtotal is consistent with the order: 2400 cents for notebooks and 900 for pens. The
unexpected field is `discount_cents: 0`. Inspect that calculation before attributing the total
to the payment retry.

## Inspect the successful call

Select `discount_for`. Its attempt status is `ok`. Read **Input** and **Output**.
Selected input and output from `discount_for`:

```json theme={"system"}
{
  "input": {
    "customer": {
      "customer_id": "customer-17",
      "loyalty_member": true
    },
    "subtotal_cents": 3300
  },
  "output": 0
}
```

The actual input contains `loyalty_member: true`; the function still returned zero. The
recording establishes that the flag reached this call. It also shows `tax_for` receiving
3300 cents and returning 264, which explains the final total of 3564.

This narrows the source inspection to the discount calculation. Successful completion is
compatible with an incorrect result, so restricting the investigation to error nodes would
miss the relevant call.

## Match the recording to source

At the captured application revision, the discount helper was:

```python theme={"system"}
def discount_for(customer, subtotal_cents):
    return subtotal_cents // 10 if customer.get("is_member", False) else 0
```

It checks `is_member`, while the actual customer has `loyalty_member`. The absent key falls
back to false, producing the recorded zero discount. The mismatch is in the calculation;
the customer lookup supplied the expected membership field.

Use the source revision associated with the recording. A file and line number from a captured
stack does not identify a deployment revision, and the SDK version is a different field.

## Verify the correction

The correction uses the field supplied by the customer record:

```python theme={"system"}
def discount_for(customer, subtotal_cents):
    return subtotal_cents // 10 if customer["loyalty_member"] else 0
```

With `discount_for` defined by the helper excerpt above, the regression assertion was:

```python theme={"system"}
assert discount_for({"customer_id": "customer-17", "loyalty_member": True}, 3300) == 330
```

With the downloaded example, test the original implementation directly:

```sh theme={"system"}
.venv/bin/python -c 'from checkout_service import discount_for; assert discount_for({"customer_id": "customer-17", "loyalty_member": True}, 3300) == 330'
```

The assertion fails against the original implementation. Replace it with the supplied corrected
source and record the same order at its new revision:

```sh theme={"system"}
cp checkout_service.after.py checkout_service.py
export APP_REVISION=$(.venv/bin/python -c \
  'import hashlib; print("sha256:" + hashlib.sha256(open("checkout_service.py", "rb").read()).hexdigest())')
VEXLO_ENABLED=1 VEXLO_CAPTURE_VALUES=1 VEXLO_VALUE_SAMPLE_RATE=1 \
  VEXLO_CAPTURE_ERROR_MESSAGE=1 .venv/bin/python checkout_service.py
```

Run the assertion again; it passes. Find the new recording using its `app_revision` tag.
The before and after recordings show:

| Recording | Root status | Discount (cents) | Tax (cents) | Total (cents) |
| - | - | - | - | - |
| before | ok | 0 | 264 | 3564 |
| after | ok | 330 | 238 | 3208 |

The new graph shows a 330-cent discount, tax calculated on 2970 cents, and a 3208-cent total.
Both entry points completed normally. The differing values explain what changed; the status
badge alone would not.

This verifies the example's input case and source correction. In your service, test the
required customer schemas and other callers as well. Observed callers and one regression case
cannot establish that every possible input remains compatible.

## Use the recording with an agent

An agent can follow the same evidence: find the order, read the graph, then retrieve the
customer and discount values. Give it the expected pricing rule and the matching source
revision so it can relate the recorded behavior to the implementation.

In an MCP session for this example, the agent read those values and the source helper shown
above. Its diagnosis began:

> The discount helper checks the wrong key, so it never applies the discount.

Use the corrected helper and regression test above to verify that conclusion. To repeat the
reads with your agent, [connect an MCP client](https://docs.vexlo.ai/agents/connect.md) and follow
[Use execution data](https://docs.vexlo.ai/agents/use-data.md). The latter explains how to select runtime evidence
for a task and manage the returned data in the agent's context.


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