You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The token must be issued for an app registration that has the **`Agent365.Observability.OtelWrite`** application role (scope). Without this role, the backend returns `403 Forbidden`.
329
+
330
+
> **Important:** The `gen_ai.agent.id` value in your span attributes **must match** the application identity in the Bearer token. The backend validates that the agent ID in the payload corresponds to the authenticated app. Mismatches result in `403 Forbidden`.
331
+
311
332
The token is obtained from a **token resolver** — a function with signature:
"""Return a valid Bearer token for the given agent and tenant, or None if unavailable."""
316
337
...
317
338
```
318
339
319
-
How you implement this depends on your environment (MSAL client credentials, managed identity, etc.). The A365 SDK uses this same interface internally.
340
+
If the token resolver returns `None`, the exporter should skip that batch and log a warning. How you implement this depends on your environment (MSAL client credentials, managed identity, etc.). The A365 SDK uses this same interface internally.
320
341
321
342
### Payload format
322
343
@@ -396,12 +417,43 @@ The body is JSON with this structure:
396
417
397
418
| Constraint | Value | Behavior |
398
419
|------------|-------|----------|
399
-
| Max payload size |~900,000 bytes | Split spans across multiple POST requests |
400
-
| Max individual span | 250,000 bytes | Largest attributes are replaced with `"TRUNCATED"`|
420
+
| Max payload size (server limit) | 1,000,000 bytes | Requests exceeding 1 MB are rejected |
421
+
| Recommended max payload |~900,000 bytes | Use as conservative buffer below the 1 MB limit |
422
+
| Max individual span | 250,000 bytes | Truncate largest attributes (see below) |
401
423
| Retry on | 408, 429, 5xx | Exponential backoff; respect `Retry-After` header for 429 |
402
424
| Fail on | Other 4xx | Non-retryable; check auth and payload format |
If a serialized batch exceeds ~900,000 bytes, split it into multiple POST requests. Each request must still respect the grouping requirement (same tenant + agent). A simple approach:
if current_chunk and current_size + span_size + overhead > max_bytes:
442
+
chunks.append(current_chunk)
443
+
current_chunk = []
444
+
current_size =0
445
+
current_chunk.append(span)
446
+
current_size += span_size
447
+
448
+
if current_chunk:
449
+
chunks.append(current_chunk)
450
+
return chunks
451
+
```
452
+
453
+
#### Span truncation
454
+
455
+
If a single span exceeds 250,000 bytes (typically due to large `gen_ai.input.messages` or `gen_ai.output.messages`), truncate the largest attribute values by replacing them with `"TRUNCATED"`. Prioritize keeping structural attributes intact and truncating message content first.
456
+
405
457
### Grouping requirement
406
458
407
459
All spans in a single POST must share the same `microsoft.tenant.id` and `gen_ai.agent.id`. If your batch contains spans for multiple tenants or agents, partition them into separate requests.
0 commit comments