xtrace 0.0.15

An AI observability service for collecting, storing, and querying traces, spans, and metrics across LLM and agent workflows.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
# Trace And Session Design

This document defines a forward-looking design for trace, session, multi-turn conversation, and agent execution in XGateway.

## Background

The current request log and trace pipeline is request-oriented:

- `request_logs` stores one row per upstream request.
- `xtrace` stores one trace per request and one observation per generation.
- OpenAI-compatible chat requests are stateless from the gateway perspective.

This is enough for single-request observability, but it does not reliably answer these questions:

- Which requests belong to the same multi-turn conversation?
- Which model answered each turn when models change between turns?
- Which internal steps belong to the same agent execution?
- How should an interrupted agent run be resumed?

## Goals

- Reliably identify that multiple turns belong to the same conversation.
- Make each user turn correspond to the actual model and provider that produced the answer.
- Support both plain chat and future agent workflows with one unified model.
- Separate business state from observability state.
- Allow progressive rollout without breaking the current API.

## Non-Goals

- Replacing `request_logs` entirely.
- Encoding all conversation state only inside trace records.
- Inferring conversation identity from message similarity or time windows.

## Design Principles

1. Use explicit identifiers instead of heuristics.
2. Separate conversation state from execution logs.
3. Model one user input as one turn.
4. Model agent internals as steps within a run.
5. Treat trace as an observability layer, not as the primary source of business truth.

## Conceptual Model

The recommended model has four layers.

### 1. Session

A session represents one continuous conversation context.

Examples:

- A user chatting with the gateway in a web UI.
- A client application continuing the same support conversation for 30 turns.
- An agent working on a task over several rounds.

Responsibilities:

- Multi-turn grouping.
- Session lifecycle.
- High-level state and metadata.
- Recovery anchor for future agent memory.

### 2. Turn

A turn represents one user input and the system work triggered by that input.

Examples:

- User asks a question and receives one final answer.
- User asks an agent to summarize a CSV and the system performs multiple internal steps.

Responsibilities:

- User-visible unit in the UI.
- Final answer for the turn.
- Final provider and model attribution.
- Turn-level latency and token aggregation.

### 3. Run

A run represents one execution instance for a turn.

This is most relevant for agent mode, retries, resumptions, or alternate execution strategies.

Examples:

- The first attempt of an agent plan.
- A resumed run after a tool timeout.
- A re-run requested by the user.

Responsibilities:

- Execution state machine.
- Retry and resume boundaries.
- Checkpoints and progress tracking.

### 4. Step

A step represents one internal action within a run.

Examples:

- LLM call.
- Tool call.
- Retrieval call.
- Planner step.
- Memory write.

Responsibilities:

- Fine-grained debugging.
- Detailed trace correlation.
- Accurate attribution of provider, model, tokens, and errors.

## Why Session Is Necessary

Without an explicit session identifier, the gateway can only see separate stateless requests. Even if each request includes historical `messages`, that history is only content, not identity.

That means the gateway cannot reliably distinguish between:

- The next turn of an existing conversation.
- A new conversation that happens to include similar context.
- A replayed request from another client.

For this reason, session grouping must be based on an explicit identifier such as `session_id`.

## Recommended Identifiers

### `session_id`

Stable across a multi-turn conversation.

Use cases:

- Group all turns in one conversation.
- Link conversation state and long-term context.
- Populate trace `session_id`.

### `turn_id`

Unique per user input.

Use cases:

- Show one request/answer pair in the UI.
- Aggregate all work done for that turn.
- Associate final model/provider with the answer.

### `run_id`

Unique per execution instance for a turn.

Use cases:

- Retries.
- Resume after interruption.
- Agent progress tracking.

### `step_id`

Unique per internal operation.

Use cases:

- Detailed observability.
- Tool and model call correlation.
- Step-by-step timeline rendering.

## Proposed Data Model

### Sessions

Suggested fields:

- `id`
- `session_key`
- `project_id`
- `org_id`
- `api_key_id`
- `end_user_id`
- `kind` (`chat` or `agent`)
- `title`
- `status` (`active`, `archived`, `closed`)
- `metadata` (JSON)
- `session_summary`
- `working_memory` (JSON)
- `created_at`
- `updated_at`
- `last_turn_at`

Notes:

- `session_key` is the externally supplied stable identifier.
- `working_memory` should store compact structured state, not raw full history.

### Turns

Suggested fields:

- `id`
- `session_id`
- `turn_index`
- `user_input`
- `input_payload` (JSON)
- `final_output`
- `final_provider_id`
- `final_provider_name`
- `final_model`
- `status` (`running`, `success`, `error`)
- `trace_id`
- `started_at`
- `ended_at`
- `latency_ms`
- `input_tokens`
- `output_tokens`
- `total_tokens`
- `metadata` (JSON)

Notes:

- A turn is the correct main object for the right-side details panel in the admin UI.
- The final answer shown to the user should map to `final_model` and `final_provider_name`.

### Runs

Suggested fields:

- `id`
- `turn_id`
- `run_index`
- `status` (`queued`, `running`, `waiting_tool`, `paused`, `success`, `error`, `cancelled`)
- `planner_state` (JSON)
- `checkpoint` (JSON)
- `started_at`
- `ended_at`
- `error_message`
- `metadata` (JSON)

Notes:

- For plain chat, each turn can have exactly one run.
- For agents, runs make resume and retry semantics explicit.

### Steps

Suggested fields:

- `id`
- `run_id`
- `parent_step_id`
- `step_index`
- `step_type` (`llm_call`, `tool_call`, `retrieval`, `planner`, `memory_write`, `handoff`)
- `provider_id`
- `provider_name`
- `model`
- `input_payload` (JSON)
- `output_payload` (JSON)
- `status`
- `error_message`
- `input_tokens`
- `output_tokens`
- `total_tokens`
- `trace_id`
- `observation_id`
- `started_at`
- `ended_at`
- `latency_ms`
- `metadata` (JSON)

Notes:

- A normal chat completion often maps to one `llm_call` step.
- Fallback across providers or models should create separate step records.

## Relationship To Existing Tables

### `request_logs`

Keep `request_logs`, but redefine its role as a low-level execution log.

Recommended future additions:

- `session_id`
- `turn_id`
- `run_id`
- `step_id`
- `trace_id`

This preserves backward compatibility while allowing the log table to participate in richer correlation.

### Existing `conversations` and `messages`

The repository already contains a `conversations/messages` model, but it is not currently connected to the OpenAI-compatible request path.

Recommended direction:

- Either evolve `conversations` into the canonical `sessions` layer.
- Or introduce a new `sessions` table and keep the existing conversation tables for a separate product surface.

For long-term clarity, one canonical session layer is preferable.

## API Design

## Input Contract

The gateway should support an explicit session identifier from clients.

Recommended options:

### Option A: Request Header

- `X-Session-Id`
- `X-Turn-Id` (optional)

Pros:

- Does not modify the standard OpenAI request body.
- Easier to introduce progressively.

Cons:

- Some clients are less convenient to customize at header level.

### Option B: Request Metadata

Add a structured extension field in the body, for example:

```json
{
  "model": "gpt-4o",
  "messages": [...],
  "metadata": {
    "session_id": "sess_123",
    "turn_id": "turn_456"
  }
}
```

Pros:

- More visible in debugging payloads.
- Easier to carry multiple correlation fields.

Cons:

- Less pure from an OpenAI compatibility perspective.

### Recommendation

Support both, with this precedence:

1. Request body metadata.
2. Request header.
3. Auto-generate on the gateway only when the client opts into gateway-managed sessions.

## Output Contract

The gateway should return correlation identifiers so the client can continue the same conversation.

Recommended response headers:

- `X-Session-Id`
- `X-Turn-Id`
- `X-Run-Id`

## Trace Integration

Trace should mirror the business identifiers, not replace them.

Recommended mapping:

- Trace `session_id` = gateway `session_id`
- Trace metadata includes `turn_id`, `run_id`, and `step_id`
- Trace observation per model/tool step

Recommended trace tags:

- `xgateway`
- session kind (`chat` or `agent`)
- provider name
- step type

Benefits:

- Session-wide observability in trace backends.
- Turn-level and run-level debugging without duplicating business logic into trace.

## Agent State Design

Future agent support requires durable state beyond raw message history.

Recommended durable state buckets:

- Session summary.
- Working memory.
- Planner state.
- Pending tool actions.
- Resume checkpoint.
- External artifact references.

Recommended rule:

- Persist compact structured state, not full prompt transcripts as the only recovery mechanism.

This allows:

- Resume after timeout or restart.
- Branching and retries.
- Better token efficiency.
- Clear UI for agent progress.

## UI Design Implications

### Current Limitation

The current request details panel is centered on one `request_log` row, so it cannot express a full multi-turn conversation with per-turn model changes.

### Recommended Future UI Shape

#### Session View

Shows:

- Session title.
- Session status.
- Turn list ordered by time.
- Latest summary and metadata.

#### Turn Details View

Shows:

- User input.
- Final output.
- Final provider and model.
- Total latency and tokens.
- Timeline of internal steps.

#### Step Timeline

Shows:

- Step type.
- Provider and model.
- Success or failure.
- Tool outputs.
- Retry and fallback path.

This UI can support both plain chat and future agent execution with the same conceptual model.

## Migration Strategy

### Phase 1: Introduce Correlation Fields

- Accept optional `session_id`.
- Return correlation identifiers.
- Populate trace `session_id`.
- Add nullable correlation columns to `request_logs`.

### Phase 2: Introduce Session And Turn Tables

- Create canonical `sessions` and `turns` tables.
- Persist each request as a turn.
- Backfill new logs with `turn_id`.

### Phase 3: Introduce Run And Step Tables

- Add `runs` and `steps` for agent support.
- Map fallback and retries to step records.
- Connect trace observations to step identifiers.

### Phase 4: Update Admin UI

- Shift from request-log-centric details to turn-centric details.
- Add session view and execution timeline.
- Preserve request log pages for low-level debugging.

## Tradeoffs

### Why Not Infer Sessions From Messages?

Because inference is not reliable. Identical or similar payloads can represent different conversations, and different payloads can represent the same conversation.

### Why Not Store Everything Only In Trace?

Because trace is best for observability, not for product state, durable session lifecycle, or query patterns needed by the admin UI.

### Why Keep `request_logs`?

Because the table is still useful for:

- Auditing.
- Low-level debugging.
- Compatibility with current admin pages.
- Operational analysis independent of session semantics.

## Open Questions

- Should the current `conversations` table evolve into `sessions`, or should a new canonical `sessions` table be introduced?
- Should session identifiers be opaque UUIDs generated by the gateway, or user-supplied stable IDs from clients?
- Should agent memory be stored inline on sessions, or delegated to a dedicated memory subsystem with references from sessions?
- What retention policy should apply to raw request content versus compact session state?

## Recommended Next Step

The most practical next step is to define the minimum viable version:

- Introduce `session_id`.
- Map each request to one turn.
- Populate trace `session_id`.
- Keep `request_logs` as the execution log layer.

That gives reliable multi-turn grouping immediately, while leaving room for agent runs and step timelines later.