@cuylabs/agent-microsoft-opentelemetry 4.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,123 @@
1
+ # Microsoft Distro Alignment
2
+
3
+ This package follows the Microsoft OpenTelemetry distro model while preserving
4
+ `@cuylabs/agent-core` as the owner of agent execution.
5
+
6
+ ## Startup
7
+
8
+ Microsoft recommends loading the OpenTelemetry ESM hook before application
9
+ modules. Use this package's loader entry point for that path:
10
+
11
+ ```bash
12
+ node --import @cuylabs/agent-microsoft-opentelemetry/loader dist/server.js
13
+ ```
14
+
15
+ The loader imports `@microsoft/opentelemetry/loader` first, then runs
16
+ `@cuylabs/agent-microsoft-opentelemetry/register`. This gives automatic
17
+ instrumentations the earliest possible hook while keeping the application on the
18
+ env-driven adapter.
19
+
20
+ Apps that initialize observability in code can call
21
+ `initMicrosoftOpenTelemetry()` directly at the beginning of their entry point.
22
+
23
+ ## Distro Options
24
+
25
+ `initMicrosoftOpenTelemetry()` maps directly to `useMicrosoftOpenTelemetry()`.
26
+
27
+ | Microsoft distro option | Adapter option |
28
+ | --- | --- |
29
+ | `resource` | `resource` with `serviceName`, `serviceVersion`, and custom attributes. |
30
+ | `azureMonitor` | `azureMonitor`. |
31
+ | `instrumentationOptions` | `instrumentationOptions`. |
32
+ | `agent-core`-focused instrumentation defaults | `instrumentationProfile: "agent-core"`. |
33
+ | `a365.enabled` | `a365.enabled`. |
34
+ | `a365.enableObservabilityExporter` | `a365.enableObservabilityExporter`. |
35
+ | `a365.tokenResolver` | `a365.tokenResolver`. |
36
+ | `a365.useS2SEndpoint` | `a365.useS2SEndpoint`. |
37
+ | Export queue, timeout, batch, cluster, domain, and scope options | Same A365 option names. |
38
+
39
+ The adapter also accepts `a365.exporterEnabled` as a compatibility alias for
40
+ `a365.enableObservabilityExporter`. New code should use Microsoft's official
41
+ option name.
42
+
43
+ OTLP export is intentionally environment-driven, matching the Microsoft distro.
44
+ Set standard `OTEL_EXPORTER_OTLP_*` variables to enable OTLP exporters.
45
+
46
+ ## Token Resolution
47
+
48
+ Microsoft's distro calls `tokenResolver(agentId, tenantId, authScopes)` when the
49
+ Agent 365 exporter sends a batch. `createMicrosoftA365S2STokenResolverFromEnv()`
50
+ implements the Agent 365 S2S flow created by the A365 CLI:
51
+
52
+ 1. Read tenant, agent identity, blueprint client ID, and client secret from
53
+ `A365_OBSERVABILITY_*` or `agent365Observability__*` variables.
54
+ 2. Exchange the blueprint credential for a federated managed identity assertion.
55
+ 3. Exchange that assertion as the Agent 365 agent identity for an Observability
56
+ API token.
57
+ 4. Cache the token until it approaches expiration.
58
+
59
+ This is different from Microsoft's `AgenticTokenCacheInstance`, which is meant
60
+ for Microsoft Agent Hosting and per-turn authorization flows.
61
+
62
+ ## Context Propagation
63
+
64
+ Microsoft's distro uses `BaggageBuilder` and `A365SpanProcessor`. The adapter
65
+ uses the same path:
66
+
67
+ 1. Build normalized `MicrosoftA365RequestContext` values from channel/runtime
68
+ data.
69
+ 2. Convert those values to Microsoft baggage keys with
70
+ `buildMicrosoftA365BaggagePairs()`.
71
+ 3. Run the agent turn inside `runWithMicrosoftA365Context()`.
72
+ 4. Let the Microsoft distro copy baggage onto spans during span start.
73
+
74
+ For channel adapters, prefer `createMicrosoftA365ObservedTurnSource()`. It is
75
+ the `agents-ts` equivalent of Microsoft Hosting's `BaggageMiddleware`: it wraps
76
+ each `AgentTurnSource.chat()` call in a Microsoft baggage scope.
77
+
78
+ For apps that do use Microsoft Agent Hosting compatible adapters, call
79
+ `configureMicrosoftA365Hosting(adapter, options)`. This is a small pass-through
80
+ to the official distro's `configureA365Hosting()` helper, with a fallback for
81
+ older distro versions that expose `ObservabilityHostingManager` instead.
82
+
83
+ ## Agent-Core Tracing
84
+
85
+ The adapter does not create a second agent runtime. It returns tracing settings
86
+ for `createAgent({ tracing })`:
87
+
88
+ ```ts
89
+ const microsoftOtel = await initMicrosoftOpenTelemetryFromEnv();
90
+
91
+ const agent = createAgent({
92
+ name: "scout",
93
+ model,
94
+ tracing: microsoftOtel.tracing,
95
+ });
96
+ ```
97
+
98
+ `agent-core` emits the agent invocation span and passes AI SDK v7 GenAI telemetry
99
+ into `streamText()`. The Microsoft distro owns the provider, span processors,
100
+ and exporters. This keeps one OpenTelemetry pipeline while avoiding duplicate
101
+ tool spans.
102
+
103
+ ## Optional Microsoft Framework Instrumentation
104
+
105
+ The Microsoft distro's OpenAI Agents and LangChain integrations are optional
106
+ framework auto-instrumentations. They listen to those frameworks when the
107
+ corresponding packages are installed. They are different from `agent-core`
108
+ tracing, which instruments `agents-ts` execution and AI SDK v7 `streamText()`.
109
+
110
+ Use `instrumentationOptions.openaiAgents` or
111
+ `instrumentationOptions.langchain` only when the process actually uses those
112
+ frameworks. The adapter's default `agent-core` profile disables them because the
113
+ normal `agents-ts` path does not execute through those frameworks.
114
+
115
+ The adapter types expose Microsoft's `isContentRecordingEnabled` flags for
116
+ those framework instrumentations. They are separate from `agent-core`
117
+ `recordInputs` and `recordOutputs`, which control AI SDK v7 telemetry produced
118
+ through `@cuylabs/agent-core`.
119
+
120
+ The early pre-release profile name `agent365-genai` remains accepted as a
121
+ compatibility alias for `microsoft-genai`, but new code should use
122
+ `agent-core`, `microsoft-genai`, `full-stack`, `manual`, or
123
+ `microsoft-default`.
package/docs/env.md ADDED
@@ -0,0 +1,76 @@
1
+ # Environment Variables
2
+
3
+ The package accepts both Microsoft OpenTelemetry resource settings and Agent 365
4
+ CLI-generated observability settings.
5
+
6
+ ## Resource
7
+
8
+ | Variable | Meaning |
9
+ | --- | --- |
10
+ | `MICROSOFT_OTEL_SERVICE_NAME` or `OTEL_SERVICE_NAME` | OpenTelemetry `service.name`. |
11
+ | `MICROSOFT_OTEL_SERVICE_VERSION` or `OTEL_SERVICE_VERSION` | OpenTelemetry `service.version`. |
12
+ | `MICROSOFT_OTEL_SERVICE_NAMESPACE` or `OTEL_SERVICE_NAMESPACE` | OpenTelemetry `service.namespace`. |
13
+ | `MICROSOFT_OTEL_SERVICE_INSTANCE_ID` or `OTEL_SERVICE_INSTANCE_ID` | OpenTelemetry `service.instance.id`. |
14
+
15
+ ## Destinations
16
+
17
+ | Variable | Meaning |
18
+ | --- | --- |
19
+ | `APPLICATIONINSIGHTS_CONNECTION_STRING` | Enables Azure Monitor export in the Microsoft distro. |
20
+ | `MICROSOFT_OTEL_AZURE_MONITOR_ENABLED` | Explicit Azure Monitor enable flag used by the adapter helpers. |
21
+ | `OTEL_EXPORTER_OTLP_ENDPOINT` | Enables OTLP export for traces, metrics, and logs. |
22
+ | `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` | Enables or overrides OTLP trace export. |
23
+ | `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT` | Enables or overrides OTLP metric export. |
24
+ | `OTEL_EXPORTER_OTLP_LOGS_ENDPOINT` | Enables or overrides OTLP log export. |
25
+ | `MICROSOFT_OTEL_ENABLE_CONSOLE_EXPORTERS` | Explicitly enables console exporters. |
26
+ | `MICROSOFT_OTEL_INSTRUMENTATION_PROFILE` | `agent-core`, `microsoft-genai`, `full-stack`, `manual`, or `microsoft-default`. |
27
+
28
+ ## Agent 365
29
+
30
+ | Variable | Meaning |
31
+ | --- | --- |
32
+ | `MICROSOFT_OTEL_A365_ENABLED` or `A365_OBSERVABILITY_ENABLED` | Enables the Agent 365 distro path. |
33
+ | `ENABLE_A365_OBSERVABILITY_EXPORTER` | Enables HTTP export to Agent 365. |
34
+ | `A365_OBSERVABILITY_TENANT_ID` | Tenant that owns the agent identity. |
35
+ | `A365_OBSERVABILITY_AGENT_ID` | Agent 365 agent identity ID. |
36
+ | `A365_OBSERVABILITY_CLIENT_ID` | Blueprint client ID used for the FMI token exchange. |
37
+ | `A365_OBSERVABILITY_CLIENT_SECRET` | Blueprint client secret. Use Key Vault or managed identity in production. |
38
+ | `A365_OBSERVABILITY_USE_MANAGED_IDENTITY` | Uses a managed-identity assertion provider when supplied by the host app. |
39
+ | `A365_OBSERVABILITY_USE_S2S_ENDPOINT` | Uses the Agent 365 S2S ingestion endpoint. |
40
+ | `A365_OBSERVABILITY_CLUSTER_CATEGORY` or `CLUSTER_CATEGORY` | Agent 365 endpoint cluster category, such as `prod`, `test`, or `gov`. |
41
+ | `A365_OBSERVABILITY_AUTHENTICATION_SCOPES` | Space- or comma-separated auth scopes. |
42
+ | `A365_OBSERVABILITY_SCOPES_OVERRIDE` | Official Microsoft distro auth-scope override. It is passed to the distro as A365 auth scopes. |
43
+ | `A365_OBSERVABILITY_DOMAIN_OVERRIDE` | Agent 365 domain override for non-production clouds. |
44
+ | `A365_OBSERVABILITY_LOG_LEVEL` | Microsoft distro A365 log level, for example `warn|error`. |
45
+ | `A365_OBSERVABILITY_MAX_QUEUE_SIZE` | Agent 365 exporter queue size. |
46
+ | `A365_OBSERVABILITY_SCHEDULED_DELAY_MS` | Agent 365 exporter batch delay in milliseconds. |
47
+ | `A365_OBSERVABILITY_EXPORTER_TIMEOUT_MS` | Agent 365 export timeout in milliseconds. |
48
+ | `A365_OBSERVABILITY_HTTP_REQUEST_TIMEOUT_MS` | Agent 365 per-request HTTP timeout in milliseconds. |
49
+ | `A365_OBSERVABILITY_MAX_EXPORT_BATCH_SIZE` | Agent 365 maximum spans per export batch. |
50
+ | `A365_OBSERVABILITY_MAX_PAYLOAD_BYTES` | Agent 365 maximum estimated payload size per HTTP chunk. |
51
+
52
+ In code, prefer Microsoft's official `a365.enableObservabilityExporter` option.
53
+ The package also accepts `a365.exporterEnabled` as a compatibility alias.
54
+
55
+ The double-underscore CLI aliases are also accepted for the core S2S values,
56
+ such as `agent365Observability__tenantId`, `agent365Observability__agentId`,
57
+ `agent365Observability__clientId`, and
58
+ `agent365Observability__clientSecret`.
59
+
60
+ ## Distro-Owned Pass-Through Variables
61
+
62
+ The Microsoft distro also reads some variables directly from `process.env`.
63
+ This adapter does not parse or duplicate those settings because the official
64
+ package owns their behavior.
65
+
66
+ | Variable | Meaning |
67
+ | --- | --- |
68
+ | `A365_PER_REQUEST_MAX_TRACES` | Max buffered traces for the distro's A365 per-request pipeline. |
69
+ | `A365_PER_REQUEST_MAX_SPANS_PER_TRACE` | Max spans buffered per trace. |
70
+ | `A365_PER_REQUEST_MAX_CONCURRENT_EXPORTS` | Max concurrent A365 exports. |
71
+ | `A365_PER_REQUEST_FLUSH_GRACE_MS` | Grace period after a root span ends. |
72
+ | `A365_PER_REQUEST_MAX_TRACE_AGE_MS` | Max trace age before forced flush. |
73
+
74
+ Set those variables on the process exactly as the Microsoft distro documents
75
+ them; `@cuylabs/agent-microsoft-opentelemetry` does not need adapter-specific
76
+ aliases for them.
@@ -0,0 +1,40 @@
1
+ import { createAgent } from "@cuylabs/agent-core";
2
+ import { openai } from "@ai-sdk/openai";
3
+ import {
4
+ createMicrosoftA365S2STokenResolverFromEnv,
5
+ initMicrosoftOpenTelemetry,
6
+ } from "../src/index.js";
7
+
8
+ const observability = await initMicrosoftOpenTelemetry({
9
+ resource: {
10
+ serviceName: process.env.OTEL_SERVICE_NAME ?? "agent-service",
11
+ serviceVersion: process.env.OTEL_SERVICE_VERSION ?? "0.0.0",
12
+ },
13
+ a365: {
14
+ enabled: true,
15
+ enableObservabilityExporter:
16
+ process.env.ENABLE_A365_OBSERVABILITY_EXPORTER === "true",
17
+ useS2SEndpoint: true,
18
+ tokenResolver: createMicrosoftA365S2STokenResolverFromEnv(),
19
+ },
20
+ azureMonitor: {
21
+ enabled: Boolean(process.env.APPLICATIONINSIGHTS_CONNECTION_STRING),
22
+ },
23
+ instrumentationProfile: "agent-core",
24
+ agent: {
25
+ agentId: process.env.A365_OBSERVABILITY_AGENT_ID,
26
+ agentDescription: "Example Agent 365 S2S agent",
27
+ recordInputs: true,
28
+ recordOutputs: true,
29
+ },
30
+ });
31
+
32
+ const agent = createAgent({
33
+ name: "example-agent",
34
+ model: openai(process.env.OPENAI_MODEL ?? "gpt-4o-mini"),
35
+ systemPrompt: "You are a concise assistant.",
36
+ tracing: observability.tracing,
37
+ });
38
+
39
+ void agent;
40
+ await observability.shutdown();
package/package.json ADDED
@@ -0,0 +1,77 @@
1
+ {
2
+ "name": "@cuylabs/agent-microsoft-opentelemetry",
3
+ "version": "4.8.0",
4
+ "description": "Microsoft OpenTelemetry distro adapter for @cuylabs/agent-core",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "default": "./dist/index.js"
13
+ },
14
+ "./register": {
15
+ "types": "./dist/register.d.ts",
16
+ "import": "./dist/register.js",
17
+ "default": "./dist/register.js"
18
+ },
19
+ "./loader": {
20
+ "types": "./dist/loader.d.ts",
21
+ "import": "./dist/loader.js",
22
+ "default": "./dist/loader.js"
23
+ }
24
+ },
25
+ "files": [
26
+ "dist",
27
+ "docs",
28
+ "examples",
29
+ "README.md"
30
+ ],
31
+ "devDependencies": {
32
+ "@ai-sdk/openai": "4.0.0-beta.38",
33
+ "@types/node": "^22.0.0",
34
+ "ai": "7.0.0-beta.111",
35
+ "dotenv": "^17.2.3",
36
+ "tsup": "^8.0.0",
37
+ "typescript": "^5.7.0",
38
+ "vitest": "^4.0.18",
39
+ "zod": "^3.25.76 || ^4.1.8",
40
+ "@cuylabs/agent-core": "^4.8.0"
41
+ },
42
+ "peerDependencies": {
43
+ "@cuylabs/agent-core": "^4.0.0",
44
+ "@microsoft/opentelemetry": ">=1.0.1 <2.0.0",
45
+ "ai": "7.0.0-beta.111"
46
+ },
47
+ "keywords": [
48
+ "agent",
49
+ "microsoft",
50
+ "opentelemetry",
51
+ "agent365",
52
+ "a365",
53
+ "azure-monitor",
54
+ "observability"
55
+ ],
56
+ "author": "cuylabs",
57
+ "license": "Apache-2.0",
58
+ "repository": {
59
+ "type": "git",
60
+ "url": "https://github.com/cuylabs-ai/agents-ts.git",
61
+ "directory": "packages/agent-microsoft-opentelemetry"
62
+ },
63
+ "engines": {
64
+ "node": ">=20"
65
+ },
66
+ "publishConfig": {
67
+ "access": "public"
68
+ },
69
+ "scripts": {
70
+ "build": "tsup src/index.ts src/register.ts src/loader.ts --format esm --dts --clean",
71
+ "dev": "tsup src/index.ts src/register.ts src/loader.ts --format esm --dts --watch",
72
+ "typecheck": "tsc --noEmit",
73
+ "test": "vitest run",
74
+ "test:watch": "vitest",
75
+ "clean": "rm -rf dist"
76
+ }
77
+ }