Skip to content

Use S2S-only OBS with isolated app-token providers across samples - #339

Open
Krishnadheeraj (DheerajPannala) wants to merge 8 commits into
mainfrom
users/DheerajPannala/obs-s2s-only-20260909
Open

Krishnadheeraj (DheerajPannala) wants to merge 8 commits into
mainfrom
users/DheerajPannala/obs-s2s-only-20260909

Conversation

@DheerajPannala

@DheerajPannala Krishnadheeraj (DheerajPannala) commented Sep 9, 2026 •

Copy link
Copy Markdown

Rollout: ship together with the SDK 2.0.0 release containing microsoft/Agent365-nodejs#290, along with microsoft/Agent365-devTools#501 and microsoft/agent365-skills#84. After SDK 2.0.0 ships, a follow-up moves the Node samples from 1.0.0 to 2.0.0.

Summary

  • Export OBS telemetry on the S2S /otlp route throughout the Node.js, Python, .NET and Salesforce samples.
  • Give interactive samples dedicated app-only OBS token providers: blueprint client_credentials with fmi_path, then agent-instance client_credentials with the exchange assertion. Business MCP/Graph/OBO authentication stays separate.
  • Reject delegated, missing, malformed, expired, or identity/audience-mismatched OBS tokens, with no stale or user-token fallback. Harden the existing autonomous token handling.
  • Reject the legacy per-request context-token bypass, and disable published-distro replay where stored records could replay to the legacy route.
  • Update configuration templates, documentation (details in docs/observability-s2s.md) and regression coverage. Salesforce ignores its deprecated endpoint-selection flag.

Dependency and code changes to note

  • Agent 365 SDK 1.0.0 (Node): copilot-studio, devin, perplexity, openai and vercel-sdk move from 0.1.0-preview.115 / ^0.1.0-preview.125 to the 1.0.0 packages, whose S2S exporter posts to the /otlp route. Copilot Studio, Devin and Perplexity move to the 1.0.0 scope APIs (Request, AgentDetails.tenantId, UserDetails, InvokeAgentScopeDetails, renamed baggage methods), with rewritten scope and dispose handling.
  • OpenAI Node sample: @openai/agents ^0.1 → ^0.7 and openai ^4 → ^6, needed to dedupe with the 1.0.0 extensions; the overrides block is dropped.
  • LangChain Node sample: @microsoft/opentelemetry floor ^1.4.0, the first release with durableDelivery (which the sample disables). Main's ^1.0.0 already resolves to 1.4.0 on a fresh install.
  • @opentelemetry/core@2.1.0 stays an explicit dependency in copilot-studio, devin and perplexity because the 1.0.0 exporter imports it without declaring it.
  • Removed the unused @microsoft/agents-a365-observability-hosting dependency (copilot-studio, vercel-sdk) and the retired delegated token-cache modules (Node devin/langchain/openai; Python agent-framework/claude/crewai/openai).
  • .NET providers are sample-local (Observability/ in each sample); dotnet/shared/Observability is gone.
  • New CI job ci-observability.yml: Python tests/observability on Windows and .NET ObservabilityAppTokenTests on Ubuntu.

Compatibility and setup

  • Node/Python interactive samples require dedicated AGENT365_OBS_* settings. .NET uses dedicated Agent365Observability configuration and supports blueprint secrets or managed identity. The checked-in templates leave export disabled, and providers are created and validated only when export is enabled.
  • The providers are single-instance: one configured agent instance and tenant, with a separate copy of the blueprint credential. The runtime agent ID must identify the provisioned instance, not its blueprint. Multi-instance or multi-tenant deployments should cache per agent/tenant and reuse the hosting connection credential.
  • Tokens come from login.microsoftonline.com; sovereign clouds need provider changes.
  • AI Teammates: complete the OtelWrite application-role step that a365 setup all --aiteammate prints. AI Teammate S2S export without it hasn't been validated.
  • S2S ingestion does not establish trusted user attribution merely because user baggage was preserved in the submitted payload.

Validation

  • Tests pass: 433 Node, 3185 Python and 197 .NET ObservabilityAppTokenTests. The Python suite passes on Windows without PYTHONUTF8.
  • All eight Node and four .NET sample builds pass.
  • Live check (September 28, 2026) with a roleless app-only token for a registered agent instance: the 1.0.0 exporter's /otlp route returned 200, and the legacy non-/otlp route returned 401 (AuthenticationSchemeNotSupported).
  • Salesforce/Apex execution requires a configured test org and was not run.

Configure S2S OBS across sample languages, add isolated blueprint-to-agent application-token providers, preserve workload OBO, and cover routing and authentication failure paths.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI lite review requested due to automatic review settings September 9, 2026 20:56
@github-actions

github-actions Bot commented Sep 9, 2026 •

Copy link
Copy Markdown

⚠️ Deprecation Warning: The deny-licenses option is deprecated for possible removal in the next major release. For more information, see issue 997.

Dependency Review

The following issues were found:
  • ✅ 0 vulnerable package(s)
  • ✅ 0 package(s) with incompatible licenses
  • ✅ 0 package(s) with invalid SPDX license definitions
  • ⚠️ 4 package(s) with unknown licenses.
See the Details below.

License Issues

.github/workflows/ci-observability.yml

PackageVersionLicenseIssue Type
actions/checkout4.*.*NullUnknown License
actions/setup-dotnet4.*.*NullUnknown License
actions/setup-python5.*.*NullUnknown License

python/crewai/sample_agent/pyproject.toml

PackageVersionLicenseIssue Type
microsoft_agents_a365_observability_core>= 1.0.0NullUnknown License
Denied Licenses: GPL-3.0-only, AGPL-3.0-only

OpenSSF Scorecard

Scorecard details
PackageVersionScoreDetails
actions/actions/checkout 4.*.* 🟢 6.6
Details
CheckScoreReason
Maintained🟢 79 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 7
Code-Review🟢 10all changesets reviewed
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Binary-Artifacts🟢 10no binaries found in the repo
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Pinned-Dependencies🟢 3dependency not pinned by hash detected -- score normalized to 3
Fuzzing⚠️ 0project is not fuzzed
License🟢 10license file detected
Packaging⚠️ -1packaging workflow not detected
Signed-Releases⚠️ -1no releases found
Security-Policy🟢 9security policy file detected
SAST🟢 10SAST tool is run on all commits
Branch-Protection🟢 5branch protection is not maximal on development and all release branches
actions/actions/setup-dotnet 4.*.* 🟢 6.5
Details
CheckScoreReason
Code-Review🟢 10all changesets reviewed
Binary-Artifacts🟢 10no binaries found in the repo
Maintained🟢 911 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 9
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Packaging⚠️ -1packaging workflow not detected
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Pinned-Dependencies🟢 8dependency not pinned by hash detected -- score normalized to 8
License🟢 10license file detected
Fuzzing⚠️ 0project is not fuzzed
Signed-Releases⚠️ -1no releases found
Security-Policy🟢 9security policy file detected
Branch-Protection⚠️ 0branch protection not enabled on development/release branches
SAST🟢 9SAST tool is not run on all commits -- score normalized to 9
actions/actions/setup-python 5.*.* 🟢 6.6
Details
CheckScoreReason
Maintained🟢 1016 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 10
Code-Review🟢 10all changesets reviewed
Binary-Artifacts🟢 10no binaries found in the repo
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Packaging⚠️ -1packaging workflow not detected
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
Pinned-Dependencies🟢 7dependency not pinned by hash detected -- score normalized to 7
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Fuzzing⚠️ 0project is not fuzzed
License🟢 10license file detected
Signed-Releases⚠️ -1no releases found
Security-Policy🟢 9security policy file detected
SAST🟢 9SAST tool is not run on all commits -- score normalized to 9
Branch-Protection⚠️ 0branch protection not enabled on development/release branches
nuget/Azure.Identity 1.17.1 🟢 6.5
Details
CheckScoreReason
Code-Review🟢 10all changesets reviewed
Maintained🟢 1030 commit(s) and 14 issue activity found in the last 90 days -- score normalized to 10
Packaging⚠️ -1packaging workflow not detected
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
License🟢 10license file detected
Security-Policy🟢 10security policy file detected
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Signed-Releases⚠️ -1no releases found
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
Branch-Protection🟢 5branch protection is not maximal on development and all release branches
Binary-Artifacts🟢 9binaries present in source code
SAST⚠️ 0SAST tool is not run on all commits -- score normalized to 0
Pinned-Dependencies🟢 8dependency not pinned by hash detected -- score normalized to 8
Fuzzing⚠️ 0project is not fuzzed
npm/@opentelemetry/core 2.1.0 🟢 7.3
Details
CheckScoreReason
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Packaging⚠️ -1packaging workflow not detected
Code-Review🟢 10all changesets reviewed
Maintained🟢 1030 commit(s) and 6 issue activity found in the last 90 days -- score normalized to 10
Token-Permissions🟢 10GitHub workflow tokens follow principle of least privilege
Dependency-Update-Tool🟢 10update tool detected
Binary-Artifacts🟢 10no binaries found in the repo
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Pinned-Dependencies🟢 8dependency not pinned by hash detected -- score normalized to 8
License🟢 10license file detected
Branch-Protection🟢 4branch protection is not maximal on development and all release branches
Vulnerabilities⚠️ 19 existing vulnerabilities detected
Signed-Releases⚠️ 0Project has not signed or included provenance with any releases.
SAST🟢 10SAST tool is run on all commits
Security-Policy🟢 10security policy file detected
Fuzzing⚠️ 0project is not fuzzed
CI-Tests🟢 1030 out of 30 merged PRs checked by a CI test -- score normalized to 10
Contributors🟢 10project has 40 contributing companies or organizations
npm/@microsoft/agents-a365-notifications 1.0.0 UnknownUnknown
npm/@microsoft/agents-a365-observability 1.0.0 UnknownUnknown
npm/@microsoft/agents-a365-runtime 1.0.0 UnknownUnknown
npm/@opentelemetry/core 2.1.0 🟢 7.3
Details
CheckScoreReason
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Packaging⚠️ -1packaging workflow not detected
Code-Review🟢 10all changesets reviewed
Maintained🟢 1030 commit(s) and 6 issue activity found in the last 90 days -- score normalized to 10
Token-Permissions🟢 10GitHub workflow tokens follow principle of least privilege
Dependency-Update-Tool🟢 10update tool detected
Binary-Artifacts🟢 10no binaries found in the repo
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Pinned-Dependencies🟢 8dependency not pinned by hash detected -- score normalized to 8
License🟢 10license file detected
Branch-Protection🟢 4branch protection is not maximal on development and all release branches
Vulnerabilities⚠️ 19 existing vulnerabilities detected
Signed-Releases⚠️ 0Project has not signed or included provenance with any releases.
SAST🟢 10SAST tool is run on all commits
Security-Policy🟢 10security policy file detected
Fuzzing⚠️ 0project is not fuzzed
CI-Tests🟢 1030 out of 30 merged PRs checked by a CI test -- score normalized to 10
Contributors🟢 10project has 40 contributing companies or organizations
npm/@microsoft/agents-a365-notifications 1.0.0 UnknownUnknown
npm/@microsoft/agents-a365-observability 1.0.0 UnknownUnknown
npm/@microsoft/agents-a365-runtime 1.0.0 UnknownUnknown
npm/@microsoft/agents-a365-tooling 1.0.0 UnknownUnknown
npm/@types/express ^4.17.21 UnknownUnknown
npm/dotenv ^17.2.3 UnknownUnknown
npm/@microsoft/opentelemetry ^1.4.0 UnknownUnknown
npm/@microsoft/agents-a365-notifications 1.0.0 UnknownUnknown
npm/@microsoft/agents-a365-observability 1.0.0 UnknownUnknown
npm/@microsoft/agents-a365-observability-extensions-openai 1.0.0 UnknownUnknown
npm/@microsoft/agents-a365-observability-hosting 1.0.0 UnknownUnknown
npm/@microsoft/agents-a365-runtime 1.0.0 UnknownUnknown
npm/@microsoft/agents-a365-tooling 1.0.0 UnknownUnknown
npm/@microsoft/agents-a365-tooling-extensions-openai 1.0.0 UnknownUnknown
npm/@openai/agents ^0.7.0 UnknownUnknown
npm/openai ^6.27.0 UnknownUnknown
npm/@opentelemetry/core 2.1.0 🟢 7.3
Details
CheckScoreReason
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Packaging⚠️ -1packaging workflow not detected
Code-Review🟢 10all changesets reviewed
Maintained🟢 1030 commit(s) and 6 issue activity found in the last 90 days -- score normalized to 10
Token-Permissions🟢 10GitHub workflow tokens follow principle of least privilege
Dependency-Update-Tool🟢 10update tool detected
Binary-Artifacts🟢 10no binaries found in the repo
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
Pinned-Dependencies🟢 8dependency not pinned by hash detected -- score normalized to 8
License🟢 10license file detected
Branch-Protection🟢 4branch protection is not maximal on development and all release branches
Vulnerabilities⚠️ 19 existing vulnerabilities detected
Signed-Releases⚠️ 0Project has not signed or included provenance with any releases.
SAST🟢 10SAST tool is run on all commits
Security-Policy🟢 10security policy file detected
Fuzzing⚠️ 0project is not fuzzed
CI-Tests🟢 1030 out of 30 merged PRs checked by a CI test -- score normalized to 10
Contributors🟢 10project has 40 contributing companies or organizations
npm/@microsoft/agents-a365-observability 1.0.0 UnknownUnknown
npm/@microsoft/agents-a365-runtime 1.0.0 UnknownUnknown
npm/@microsoft/agents-a365-notifications 1.0.0 UnknownUnknown
npm/@microsoft/agents-a365-observability 1.0.0 UnknownUnknown
npm/@microsoft/agents-a365-runtime 1.0.0 UnknownUnknown
npm/@microsoft/agents-a365-tooling 1.0.0 UnknownUnknown
pip/microsoft_agents_a365_observability_core >= 1.0.0 UnknownUnknown
pip/microsoft-agents-a365-observability-core >= 1.0.0 UnknownUnknown
pip/microsoft-agents-a365-observability-core >= 1.0.0 UnknownUnknown
pip/microsoft-agents-a365-observability-core >= 1.0.0 UnknownUnknown
nuget/Azure.Identity 1.17.1 🟢 6.5
Details
CheckScoreReason
Code-Review🟢 10all changesets reviewed
Maintained🟢 1030 commit(s) and 14 issue activity found in the last 90 days -- score normalized to 10
Packaging⚠️ -1packaging workflow not detected
CII-Best-Practices⚠️ 0no effort to earn an OpenSSF best practices badge detected
License🟢 10license file detected
Security-Policy🟢 10security policy file detected
Dangerous-Workflow🟢 10no dangerous workflow patterns detected
Signed-Releases⚠️ -1no releases found
Token-Permissions⚠️ 0detected GitHub workflow tokens with excessive permissions
Branch-Protection🟢 5branch protection is not maximal on development and all release branches
Binary-Artifacts🟢 9binaries present in source code
SAST⚠️ 0SAST tool is not run on all commits -- score normalized to 0
Pinned-Dependencies🟢 8dependency not pinned by hash detected -- score normalized to 8
Fuzzing⚠️ 0project is not fuzzed

Scanned Files

  • .github/workflows/ci-observability.yml
  • dotnet/w365-computer-use/sample-agent/W365ComputerUseSample.csproj
  • nodejs/copilot-studio/sample-agent/package.json
  • nodejs/devin/sample-agent/package.json
  • nodejs/langchain/sample-agent/package.json
  • nodejs/openai/sample-agent/package.json
  • nodejs/perplexity/sample-agent/package.json
  • nodejs/vercel-sdk/sample-agent/package.json
  • python/crewai/sample_agent/pyproject.toml
  • python/observability-with-azure-monitor/pyproject.toml
  • python/observability-with-langgraph/pyproject.toml
  • python/observability-with-otlp/pyproject.toml
  • tests/e2e/Agent365.E2E.Tests.csproj

Comment thread dotnet/shared/Observability/ObservabilityAppTokenProvider.cs Fixed
Comment thread dotnet/shared/Observability/ObservabilityAppTokenProvider.cs Fixed
Comment thread tests/e2e/ObservabilityAppTokenTests.cs Fixed

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The new OBS-only token helper has an opaque error message (“not a ******”) across multiple samples and the .NET managed-identity assertion scope is likely incorrect without the /.default suffix.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR standardizes Agent 365 observability (OBS) export across the repository to use S2S-only ingestion (/observabilityService), and introduces isolated app-only token providers for interactive samples so OBS authentication is kept separate from business MCP/Graph/OBO authentication.

Changes:

  • Adds/updates sample-local OBS app-token resolvers (blueprint FMI → agent client_credentials) and wires them into Node.js, Python, and .NET sample observability configuration.
  • Removes legacy “per-request export” and delegated-token fallback paths, and hardens token/expiry/identity validation behavior in samples and tests.
  • Updates READMEs, .env/appsettings templates, and adds regression coverage for route selection and configuration.
File summaries
File Description
README.md Documents S2S-only OBS routing, token requirements, and validation commands
tests/observability/test_s2s_export.py Adds mocked HTTP regression test ensuring no legacy route fallback
tests/e2e/Agent365.E2E.Tests.csproj Links shared .NET OBS token provider + fixture sources into E2E test project
python/docs/design.md Updates Python design guidance to use OBS-only token service + exporter options
python/openai/sample-agent/README.md Documents dedicated OBS credentials and flow for OpenAI Python sample
python/openai/sample-agent/pyproject.toml Raises observability core minimum to >= 1.0.0
python/openai/sample-agent/host_agent_server.py Removes delegated token exchange/caching for OBS
python/openai/sample-agent/docs/design.md Updates design to use exporter_options with S2S + OBS-only resolver
python/openai/sample-agent/agent.py Switches to OBS-only token resolver + exporter_options S2S configuration
python/openai/sample-agent/AGENT-CODE-WALKTHROUGH.md Updates walkthrough to use exporter_options + OBS-only resolver
python/openai/sample-agent/.env.template Adds AGENT365_OBS_* settings; removes legacy KAIRO flag
python/openai/sample-agent/observability_token_service.py Adds sample-local OBS-only token acquisition/cache helper
python/observability-with-otlp/README.md Adds optional A365 S2S export section + prerequisites
python/observability-with-otlp/pyproject.toml Pins observability core minimum to >= 1.0.0
python/observability-with-otlp/main.py Uses exporter_options with S2S + OBS-only resolver; stamps AgentDetails IDs
python/observability-with-otlp/.env.template Adds AGENT365_OBS_* settings for optional exporter
python/observability-with-otlp/observability_token_service.py Adds sample-local OBS-only token acquisition/cache helper
python/observability-with-langgraph/README.md Documents optional S2S export + removes stub-token narrative
python/observability-with-langgraph/pyproject.toml Pins observability core minimum to >= 1.0.0
python/observability-with-langgraph/main.py Updates to exporter_options S2S + OBS-only resolver and newer scope APIs
python/observability-with-langgraph/.env.template Adds AGENT365_OBS_* settings for optional exporter
python/observability-with-langgraph/observability_token_service.py Adds sample-local OBS-only token acquisition/cache helper
python/observability-with-azure-monitor/README.md Documents optional S2S export + removes stub-token narrative
python/observability-with-azure-monitor/pyproject.toml Pins observability core minimum to >= 1.0.0
python/observability-with-azure-monitor/main.py Uses exporter_options S2S + adds explicit baggage context for standalone demo
python/observability-with-azure-monitor/.env.template Adds AGENT365_OBS_* settings for optional exporter
python/observability-with-azure-monitor/observability_token_service.py Adds sample-local OBS-only token acquisition/cache helper
python/google-adk/sample-agent/README.md Documents OBS S2S auth + clarifies app-id vs agent-user attribution
python/google-adk/sample-agent/pyproject.toml Raises observability core minimum to >= 1.0.0
python/google-adk/sample-agent/main.py Uses exporter_options S2S + OBS-only resolver
python/google-adk/sample-agent/agent.py Uses agentic_app_id (or OBS env) instead of agent-user ID for OBS baggage
python/google-adk/sample-agent/.env.template Adds AGENT365_OBS_* settings
python/google-adk/sample-agent/observability_token_service.py Adds sample-local OBS-only token acquisition/cache helper
python/crewai/sample_agent/start_with_generic_host.py Switches to exporter_options S2S + OBS-only resolver
python/crewai/sample_agent/README.md Documents shared OBS-only resolver for both bootstraps
python/crewai/sample_agent/pyproject.toml Raises observability core minimum to >= 1.0.0
python/crewai/sample_agent/host_agent_server.py Removes delegated token exchange/caching; wires exporter_options S2S + OBS-only resolver
python/crewai/sample_agent/.env.template Adds AGENT365_OBS_* settings
python/crewai/sample_agent/observability_token_service.py Adds sample-local OBS-only token acquisition/cache helper
python/claude/sample-agent/README.md Documents dedicated OBS credentials and flow
python/claude/sample-agent/pyproject.toml Raises observability core minimum to >= 1.0.0
python/claude/sample-agent/observability_config.py Uses exporter_options S2S + OBS-only resolver
python/claude/sample-agent/host_agent_server.py Removes delegated token exchange/caching for OBS
python/claude/sample-agent/.env.template Adds AGENT365_OBS_* settings
python/claude/sample-agent/observability_token_service.py Adds sample-local OBS-only token acquisition/cache helper
python/agent-framework/sample-agent/README.md Documents required OBS-only credentials when distro export is enabled
python/agent-framework/sample-agent/host_agent_server.py Uses distro S2S + OBS-only resolver; removes delegated token exchange/caching
python/agent-framework/sample-agent/agent.py Removes legacy cached-token resolver block from agent
python/agent-framework/sample-agent/AGENT-CODE-WALKTHROUGH.md Updates observability section to distro S2S + OBS-only resolver
python/agent-framework/sample-agent/.env.template Adds required AGENT365_OBS_* settings
python/agent-framework/sample-agent/observability_token_service.py Adds sample-local OBS-only token acquisition/cache helper
python/autonomous/github-trending/observability_token_service.py Hardens OBS token acquisition expiry validation and cache behavior
python/autonomous/github-trending/main.py Fails closed when OBS token missing/expired (no empty-token fallback)
nodejs/docs/design.md Updates Node.js design guidance for S2S + OBS-only token resolver patterns
nodejs/openai/sample-agent/src/otel.ts Adds early OBS bootstrap: S2S enabled + token resolver + per-request export guard
nodejs/openai/sample-agent/src/observability-token-service.ts Adds OBS-only blueprint FMI → agent token resolver with strict validation
nodejs/openai/sample-agent/src/index.ts Imports ./otel first to ensure early OBS configuration
nodejs/openai/sample-agent/src/client.ts Removes in-module manager setup; scopes now use turn context identities
nodejs/openai/sample-agent/src/agent.ts Removes delegated token preloading; stamps agent/tenant baggage explicitly
nodejs/openai/sample-agent/README.md Documents OBS-only app auth + legacy service route behavior
nodejs/openai/sample-agent/docs/design.md Updates design docs to reference otel.ts bootstrap and resolver
nodejs/openai/sample-agent/AGENT-CODE-WALKTHROUGH.md Updates walkthrough for new bootstrap + scope signature changes
nodejs/openai/sample-agent/.env.template Adds AGENT365_OBS_* settings; removes custom resolver toggle
nodejs/langchain/sample-agent/src/observability-token-service.ts Adds OBS-only token resolver helper
nodejs/langchain/sample-agent/src/index.ts Distro S2S enabled + durable delivery replay disabled + OBS-only resolver
nodejs/langchain/sample-agent/src/client.ts Uses turnContext/env tenant+agent IDs for attribution
nodejs/langchain/sample-agent/src/agent.ts Removes delegated token preload logic
nodejs/langchain/sample-agent/README.md Documents OBS-only app auth and S2S exporter behavior
nodejs/langchain/sample-agent/package.json Bumps @microsoft/opentelemetry to ^1.4.0
nodejs/langchain/sample-agent/docs/design.md Updates design docs package references for distro usage
nodejs/langchain/sample-agent/Agent-Code-Walkthrough.md Updates walkthrough imports and scope signature
nodejs/langchain/sample-agent/.env.example Adds AGENT365_OBS_* settings; removes legacy resolver toggle
nodejs/vercel-sdk/sample-agent/src/otel.ts Adds early OBS bootstrap for legacy SDK family + per-request export guard
nodejs/vercel-sdk/sample-agent/src/index.ts Imports ./otel first
nodejs/vercel-sdk/sample-agent/src/client.ts Uses turnContext identities and user details for inference scopes
nodejs/vercel-sdk/sample-agent/src/agent.ts Passes turnContext into client factory for correct attribution
nodejs/vercel-sdk/sample-agent/README.md Documents OBS-only app auth and legacy route selection
nodejs/vercel-sdk/sample-agent/docs/design.md Pins observability package version reference to preview.125
nodejs/vercel-sdk/sample-agent/.env.example Adds AGENT365_OBS_* settings
nodejs/perplexity/sample-agent/src/otel.ts Adds early OBS bootstrap for legacy SDK family + per-request export guard
nodejs/perplexity/sample-agent/src/index.ts Imports ./otel first
nodejs/perplexity/sample-agent/README.md Documents pinned legacy SDK family + OBS-only app auth
nodejs/perplexity/sample-agent/package.json Pins preview.115 dependencies, adds Node >=22 engines, adds @opentelemetry/core
nodejs/perplexity/sample-agent/docs/design.md Documents otel.ts bootstrap + OBS-only app auth settings
nodejs/perplexity/sample-agent/.env.template Adds AGENT365_OBS_* settings and removes legacy flags
nodejs/devin/sample-agent/src/utils.ts Adds caller details + normalizes tenant/agent ID sourcing for OBS
nodejs/devin/sample-agent/src/otel.ts Adds early OBS bootstrap + per-request export guard
nodejs/devin/sample-agent/src/observability-token-service.ts Adds OBS-only token resolver helper
nodejs/devin/sample-agent/src/index.ts Imports ./otel first; keeps shutdown hook for ObservabilityManager
nodejs/devin/sample-agent/src/agent.ts Removes in-constructor OBS init; improves scope disposal/error recording
nodejs/devin/sample-agent/README.md Documents pinned legacy SDK family + OBS-only app auth
nodejs/devin/sample-agent/package.json Pins preview.115 deps, adds @opentelemetry/core, updates deps
nodejs/devin/sample-agent/docs/design.md Documents otel.ts bootstrap + pinned SDK family
nodejs/devin/sample-agent/.env.example Adds AGENT365_OBS_* settings; removes legacy flags
nodejs/copilot-studio/sample-agent/src/otel.ts Adds early OBS bootstrap + per-request export guard
nodejs/copilot-studio/sample-agent/src/index.ts Imports ./otel first
nodejs/copilot-studio/sample-agent/src/client.ts Refactors scope creation to include baggage + explicit disposal/error recording
nodejs/copilot-studio/sample-agent/src/agent.ts Removes delegated token preload; builds baggage explicitly with IDs
nodejs/copilot-studio/sample-agent/README.md Documents pinned legacy SDK family + OBS-only app auth
nodejs/copilot-studio/sample-agent/package.json Pins preview.115 deps, adds Node >=22 engines, adds @opentelemetry/core
nodejs/copilot-studio/sample-agent/.env.template Adds AGENT365_OBS_* settings; removes legacy resolver toggle
nodejs/claude/sample-agent/src/otel.ts Enables distro S2S + uses OBS-only resolver
nodejs/claude/sample-agent/src/client.ts Removes blueprint secret from subprocess env; uses turnContext/env IDs for scopes
nodejs/claude/sample-agent/README.md Documents OBS-only app auth and distro configuration
nodejs/claude/sample-agent/docs/design.md Updates distro snippet to include S2S + token resolver
nodejs/claude/sample-agent/.env.template Adds AGENT365_OBS_* settings
nodejs/autonomous/github-trending/src/observability-token-service.ts Requires real expiry for cached OBS tokens; sanitizes error bodies
nodejs/autonomous/github-trending/src/index.ts Fails closed if OBS token missing/expired; removes empty-token fallback
dotnet/shared/Observability/ObservabilityAppTokenFactory.cs Adds managed-identity assertion wiring for shared OBS-only token provider
dotnet/w365-computer-use/sample-agent/W365ComputerUseSample.csproj Adds Azure.Identity alias and links shared Observability sources
dotnet/w365-computer-use/sample-agent/Telemetry/ObservabilityServiceCollectionExtensions.cs Uses S2S endpoint + injects dedicated OBS token resolver
dotnet/w365-computer-use/sample-agent/Telemetry/A365OtelWrapper.cs Removes delegated token registration/caching path for OBS
dotnet/w365-computer-use/sample-agent/README.md Documents Agent365Observability config + deployment guidance
dotnet/w365-computer-use/sample-agent/Program.cs Wires shared OBS-only app token provider into OpenTelemetry config
dotnet/w365-computer-use/sample-agent/appsettings.json Adds BlueprintClientId/Secret + managed identity knobs
dotnet/w365-computer-use/sample-agent/Agent/MyAgent.cs Removes exporter token cache dependencies from agent constructor/calls
dotnet/semantic-kernel/sample-agent/SemanticKernelSampleAgent.csproj Adds Azure.Identity alias and links shared Observability sources
dotnet/semantic-kernel/sample-agent/README.md Documents dedicated OBS-only credentials and S2S configuration
dotnet/semantic-kernel/sample-agent/Program.cs Injects shared OBS-only resolver and enables S2S on exporter
dotnet/semantic-kernel/sample-agent/appsettings.json Adds Agent365Observability configuration template
dotnet/docs/design.md Updates .NET design docs for shared OBS-only provider + S2S-only exporter
dotnet/autonomous/github-trending/sample-agent/Program.cs Fails closed if OBS token missing/expired (no empty-token fallback)
dotnet/agent-framework/sample-agent/README.md Documents dedicated OBS-only credentials and deployment considerations
dotnet/agent-framework/sample-agent/Program.cs Injects shared OBS-only resolver and enables S2S on exporter
dotnet/agent-framework/sample-agent/appsettings.json Replaces legacy client ID/secret fields with OBS-only settings
dotnet/agent-framework/sample-agent/AgentFrameworkSampleAgent.csproj Adds Azure.Identity alias and links shared Observability sources
dotnet/agent-framework/sample-agent/Agent/MyAgent.cs Removes delegated token registration for OBS; keeps business auth separate
agent-platforms/salesforce/apex-observability/README.md Marks endpoint-selection flag deprecated; OBS always uses S2S path
agent-platforms/salesforce/apex-observability/force-app/main/default/objects/A365_Observability_Config__mdt/fields/UseS2SEndpoint__c.field-meta.xml Deprecates legacy route flag metadata and labeling
agent-platforms/salesforce/apex-observability/force-app/main/default/classes/A365TelemetryTest.cls Adds tests asserting no legacy route fallback (including on 401)
agent-platforms/salesforce/apex-observability/force-app/main/default/classes/A365ObsConfig.cls Forces S2S route selection regardless of deprecated flag
Review details
  • Files reviewed: 141/141 changed files
  • Comments generated: 9
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread dotnet/shared/Observability/ObservabilityAppTokenFactory.cs Outdated
Comment thread python/agent-framework/sample-agent/observability_token_service.py
Comment thread python/claude/sample-agent/observability_token_service.py
Comment thread python/crewai/sample_agent/observability_token_service.py
Comment thread python/google-adk/sample-agent/observability_token_service.py
Comment thread python/observability-with-langgraph/observability_token_service.py
Comment thread python/observability-with-otlp/observability_token_service.py
Comment thread python/openai/sample-agent/observability_token_service.py

@Jason-R-Lien Jason-R-Lien left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Full first-pass panel review

Verdict: Needs work (medium risk). The cross-language S2S implementation consistently isolates observability credentials from business MCP/Graph/OBO credentials, validates the returned app token, bounds refreshes, and fails closed. One new regression test does not actually protect the isolation invariant it claims to verify.

Should fix

  • tests/observability/node-app-token.test.cjs:212-213 - The business-auth regression reads its before value from git show HEAD:<file> and compares it with the same clean-checkout file, so it is tautological in CI. Assert the expected call arguments directly, execute the calls with mocks, or compare against a real base fixture so a PR that changes addToolServersToAgent/exchangeToken fails the test.

Existing review reconciliation

Twelve exact-head bot threads remain unresolved, so the approval gate cannot pass even apart from the new finding. I did not duplicate them: eight are the same diagnostic-rendering comment, and the remaining four cover a broad catch, LINQ style, fixture-path hardening, and the managed-identity request resource. The last claim does not survive source verification: Azure Identity's managed-identity path converts a single TokenRequestContext value to a resource, accepting api://AzureADTokenExchange unchanged and stripping /.default when supplied (Azure.Core ScopeUtilities.ScopesToResource).

Trade-off

Keeping a static structural guard is useful for these samples, but it must be independent of the commit under test; otherwise the test adds maintenance cost without protecting the business-auth boundary.

Persona roll-up

  • Security: No new credential crossover, delegated-token fallback, token logging, or fail-open path found; the two-step tokens are audience/role/type/expiry validated.
  • Privacy: No new user identity collection, cross-tenant cache reuse, or sensitive diagnostic disclosure found.
  • Performance: Refreshes are cached, single-flight, timeout-bounded, and do not return stale tokens after failure.
  • Customer service: The migration guidance is broad, but the advertised Node business-auth regression is ineffective.
  • Business / COGS: Token exchanges occur only on refresh; no material storage, egress, or cardinality increase found.
  • Senior engineer: One should-fix test defect; the .NET and Python focused tests otherwise exercise failure and cache behavior well.
  • Architect: The S2S endpoint and app-only resolver contract is consistent across supported sample families; no additional design break found.

Feedback ledger

No repository-specific ledger existed, so no prior dismissal suppressed a source-valid finding. Existing PR threads were reconciled and not duplicated.

Approval gate

Not approved: one should-fix finding remains and all 12 prior review threads are unresolved. The PR is open at a6f88cf310557d9609688cb12eff6c2b702dd711; all 41 exact-head checks are complete and successful.

Comment thread tests/observability/node-app-token.test.cjs Outdated
Preserve workload OBO while accepting explicitly app-only roleless OBS tokens. Add independent business-auth contract guards, narrow .NET acquisition failures, harden fixture paths, and reuse the managed-identity exchange scope. Align OpenAI dependencies and update registration and authentication guidance.

Review response amendments:

- Roleless tokens now also accepted when oid==sub (with no scp), because Entra may not emit idtyp=app for the OBS resource in every tenant. Delegated tokens have oid != sub, so this stays app-only.
- Restore the .NET "never leak secrets" guarantee: sanitize CryptographicException, IOException, and any unexpected non-programming exception; still propagate InvalidOperation/NullReference/Argument/KeyNotFound/Overflow as programming failures.
- Widen the OpenAI tracing smoke fixture timeout to tolerate cold-cache require() resolution.

Follow-ups (session files/pr-followups.md):
- Bump sample SDK once #290 publishes and remove the per-request-export startup rejection.
- Live-verify roleless acceptance against a second tenant and an OBO-authorized agent.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5cbf5f6b-cc40-4b7e-a591-65848db73a12
@DheerajPannala

Copy link
Copy Markdown
Author

Review feedback addressed

Pushed e9206cb.

Changes

  • Roleless OBS tokens: Node, Python and .NET providers accept an app-only token without roles when it declares idtyp=app or has oid == sub. Tokens with any scp, a non-app idtyp, malformed roles, or the wrong tenant, client, audience or lifetime are still rejected. Workload OBO and the FMI token exchange are unchanged.
  • Business-auth guard (Jason's comment): the MCP/OBO call check now compares against reviewed fixtures instead of git show HEAD. Mutation controls prove it fails when the handler, turn context, token source or scopes change, or when a call is removed.
  • .NET: expected parsing and credential failures are sanitized without inner exceptions; caller cancellation and programming errors propagate. Fixture paths accept bare filenames only. The managed-identity request reuses ExchangeScope.
  • OpenAI sample: @openai/agents ^0.7.0 and openai ^6.27.0, matching what the published A365 OpenAI extensions require, so the app and the instrumentation share one Agents runtime.
  • Docs: permissionless S2S OBS depends on an eligible, registered agent instance and service policy. An OBS role grant is not a universal prerequisite, and creating an Entra identity alone is not registration.

Validation

  • Clean checkout of this commit: Node 426, Python 3,183 and .NET 183 offline tests pass. An offline OpenAI agent run with a mocked model emits both agent-invocation and inference spans.
  • Live: with the earlier roleless-token fix, the OpenAI sample exported real agent telemetry through the S2S OTLP route using a roleless app-only token (HTTP 200, downstream processing confirmed).

Known gaps

  • The legacy-SDK Node samples (OpenAI, Vercel, Devin, Perplexity, Copilot Studio) still use the published SDK's non-OTLP S2S route. Roleless acceptance on that route has not been verified live. The samples can move once agents-a365-nodejs Remove status from readme #290 is published.
  • Running the business-auth guard in CI follows in a separate commit.
  • The oid == sub fallback is covered by offline tests only.
  • The W365 sample's full build could not be run locally because of a NuGet access issue. Its shared observability code is compiled and tested through the other .NET projects.

Comment thread tests/e2e/ObservabilityAppTokenTests.cs Fixed
Comment thread tests/e2e/ObservabilityAppTokenTests.cs Fixed
Comment thread tests/e2e/ObservabilityAppTokenTests.cs Fixed
Comment thread tests/e2e/ObservabilityAppTokenTests.cs Fixed
Comment thread tests/e2e/ObservabilityAppTokenTests.cs Fixed
Comment thread tests/e2e/ObservabilityAppTokenTests.cs Fixed

@Jason-R-Lien Jason-R-Lien left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-review of a6f88cf..e9206cb

Verdict: Needs work (medium risk). The new roleless app-token checks are fail-closed across .NET, Node, and Python, and all exact-head CI checks are successful. Approval is still blocked by one existing test-coverage finding and one new documentation-contract finding.

Author-claimed fixes

  • Business-auth guard — partially accepted. The git show HEAD tautology is gone: business-auth-contracts.json is an independent oracle, and the mutation cases cover handler, turn context, workload token/scope, and call removal. However, no workflow invokes tests/observability/node-app-token.test.cjs; the author also lists CI wiring as a known gap. The original regression-protection finding therefore remains open until this guard runs in CI.
  • Roleless OBS token validation — accepted in source. All three providers reject any scp, explicit non-app/null idtyp, malformed roles, wrong tenant/client/audience, and invalid lifetime; absent/empty roles require idtyp=app or, when idtyp is absent, oid == sub. The new focused tests exercise both acceptance and rejection branches.
  • .NET exception handling — accepted. Expected HTTP, acquisition, cryptographic, I/O, timeout, parsing, shape, and lifetime failures are sanitized without inner exceptions; caller cancellation and the enumerated programming errors propagate.
  • Fixture-path hardening — accepted. Fixture() rejects rooted, traversal, drive-relative, UNC/device, ADS, separator, whitespace, and trailing-dot/space inputs before Path.Combine; the new generic Path.Combine alert does not survive source verification.
  • Managed-identity exchange scope — accepted. The factory now reuses ExchangeScope (api://AzureADTokenExchange/.default).
  • Masked “bearer token” comments — accepted as display-only false positives. The raw source already contains the actionable bearer token wording in every helper copy.
  • OpenAI runtime alignment — accepted. The package now declares @openai/agents ^0.7.0 and openai ^6.27.0, with a runtime-resolution/instrumentation regression in the Node test.
  • Documentation — rejected in part. Registration/service-policy guidance is improved, but the newly added roleless-token wording excludes the implemented oid == sub fallback in the root and two .NET sample READMEs; see the inline finding.

Approval blockers

  1. Existing tests/observability/node-app-token.test.cjs business-auth finding: independent oracle fixed, but the guard is not wired into CI.
  2. New auth-contract documentation inconsistency at README.md:64 (also dotnet/agent-framework/sample-agent/README.md:163 and dotnet/semantic-kernel/sample-agent/README.md:49).
  3. Live review threads remain unresolved. The new LINQ advisories are non-consequential style suggestions, and the new Path.Combine advisory is rebutted by the preceding bare-filename validator; they are not counted as substantive findings, but the Step 7 thread-state gate is not satisfied.

Persona roll-up

  • Security / Privacy: App-only/delegated separation, tenant-agent binding, audience/lifetime validation, sanitization, and no-secret diagnostics are source-correct; no new privacy flow found.
  • Performance / COGS: Refresh remains cached, single-flight, and bounded; no hot-path or material cost regression found.
  • Customer service: One operator-facing authentication contract is internally contradictory.
  • Senior engineer / Architect: The original guard now has a real oracle but no automated execution; no additional architecture or correctness defect found.

No repository-specific feedback ledger exists, so no finding was suppressed. Merge remains subject to branch protection.

Comment thread README.md Outdated
Align the roleless OBS token guidance in the root, .NET, Node.js and
Python docs with the implemented providers: absent or empty roles are
accepted with idtyp=app, or with absent idtyp when a nonempty oid equals
sub. Tokens without idtyp still work with valid nonempty roles. The .NET
autonomous README no longer implies that the service requires idtyp=app.

Also use Select projections for the five claim loops and Path.Join for
the validated fixture filename in ObservabilityAppTokenTests.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5cbf5f6b-cc40-4b7e-a591-65848db73a12
…orkflow

Run the reviewed business MCP/OBO contract and mutation checks from tests/observability/node-app-token.test.cjs after the OpenAI sample build, so they execute in CI.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5cbf5f6b-cc40-4b7e-a591-65848db73a12

@Jason-R-Lien Jason-R-Lien left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-review of e9206cb..f85bf6c

Verdict: Needs work (medium risk); no new findings. The documentation-contract inconsistency is fixed and the quality-only test refactors preserve behavior. One existing should-fix remains: the business-auth regression has an independent fixture oracle, but no workflow invokes tests/observability/node-app-token.test.cjs, so the isolation invariant is still not protected in CI.

Author-response reconciliation

  • Business-auth guard — partially accepted, still open. The git show HEAD tautology was fixed in e9206cb; the reviewed fixture and mutation controls are source-valid. The author's stated CI-wiring gap remains at f85bf6c: no workflow references the Node observability test or its fixture.
  • Roleless-token validation and provider behavior — accepted. The .NET, Node, and Python providers and focused tests support idtyp=app or absent idtyp with nonempty oid == sub, while retaining fail-closed delegated, identity, audience, tenant, and lifetime checks.
  • Documentation fix — accepted. The root, .NET, Node, and Python documentation now describes both accepted roleless forms and no longer contradicts the providers.
  • .NET exception sanitization — accepted. Expected acquisition/parsing/transport failures are sanitized; caller cancellation and the documented programming errors propagate.
  • Explicit claim-validation loop rebuttal — accepted. The loop validates every present appid/azp claim and avoids the invalid TryGetProperty predicate suggested by the advisory.
  • Fixture-path hardening and Path.Join follow-up — accepted. Bare-filename validation precedes the join, and the join change does not widen accepted input.
  • Managed-identity exchange scope — accepted. The factory reuses ExchangeScope with /.default.
  • Eight masked “bearer token” replies — accepted as display-only false positives. Raw source contains the full actionable wording.
  • OpenAI runtime alignment — accepted. The declared Agents/OpenAI versions and runtime-resolution regression remain in place.
  • Five LINQ Select fixes — accepted. Each loop now projects claims before iteration with no semantic change; the exact-head focused token suite passes.

Approval gate

  • Blocked: one consequential review thread remains unresolved because the business-auth guard is not run by CI.
  • Clean: all exact-head GitHub checks are completed and successful; no new correctness, security/privacy, performance/COGS, customer-service, or architecture finding was introduced by this delta.

Merge remains subject to branch protection.

@Jason-R-Lien Jason-R-Lien left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same-head PR-content re-review

Verdict: Needs work (medium risk); no new findings. The head remains f85bf6c, and the current title/description matches content hash 5e8dacb…, which was already reviewed. The updated operator guidance does not contradict the implementation, but the prior CI-coverage blocker remains.

Author-response reconciliation

  • Business-auth guard — partially accepted, still open. The independent fixture oracle and mutation controls fixed the original git show HEAD tautology. Source at this head still has no workflow reference to tests/observability/node-app-token.test.cjs, matching the author's stated CI-wiring gap.
  • Roleless-token behavior and documentation — accepted. Provider tests and active docs consistently allow explicit idtyp=app or absent idtyp with nonempty oid == sub, while retaining delegated, identity, tenant, audience, and lifetime rejection.
  • .NET exception sanitization, claim-validation-loop rebuttal, fixture-path hardening/Path.Join, and managed-identity exchange scope — accepted. The previously verified source remains unchanged.
  • Masked “bearer token” replies — accepted as display-only false positives. Raw source contains the full wording.
  • OpenAI runtime alignment and five LINQ Select fixes — accepted. The verified implementation is unchanged.

Approval gate

  • Blocked: the one source-valid business-auth regression is not run by CI; its thread remains unresolved consistently with that missing acceptance criterion.
  • Clean: all 40 exact-head checks are completed and successful, and no later author response, submitted review, issue comment, or source change introduces another finding.

Merge remains subject to branch protection.

@DheerajPannala

Copy link
Copy Markdown
Author

Jason-R-Lien, the remaining blocker is addressed in 3bac1b1: the business-auth guard (tests/observability/node-app-token.test.cjs) now runs in the Node.js OpenAI workflow on Node 18 and 20, and passes on both. That was the only change since f85bf6c. The thread is replied to and resolved, and all 40 checks are green.

Jason-R-Lien
Jason-R-Lien previously approved these changes Sep 28, 2026

@Jason-R-Lien Jason-R-Lien left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-review of f85bf6c..3bac1b1

Approved. The only delta wires the existing independent business-auth fixture/mutation guard into the required Node.js OpenAI workflow. The step runs from the repository root, selects all 24 business-auth contract cases, and completed successfully on both Node 18 and Node 20. No new findings.

Author-response reconciliation

  • Business-auth oracle and CI coverage — accepted. e9206cb replaced the git show HEAD comparison with reviewed fixtures and mutation controls; 3bac1b1 now invokes that unchanged guard from CI. This fully closes the prior should-fix.
  • Roleless-token contract and documentation — accepted. The fail-closed idtyp=app / absent-idtyp with oid == sub behavior and matching documentation remain present at head.
  • .NET exception handling, fixture-path validation, exchange scope, OpenAI runtime alignment, LINQ projections, and Path.Join refactor — accepted. The previously cited source and regression coverage remain unchanged at head.
  • Explicit appid/azp claim loop — rebuttal accepted. The loop intentionally validates every present claim and avoids a redundant lookup; no correctness issue remains.
  • Eight masked Python error-message comments — rebuttal accepted. The source contains the explicit not a bearer token wording; the masked rendering was not a source defect.

All 20 review threads are resolved, all 40 exact-head checks completed successfully, and there are no open blocking or should-fix findings. Merge remains subject to branch protection.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes, mainly because of the cross-PR rollout; see the [Blocking] inline comment on copilot-studio otel.ts.

The app-only token providers look solid:

  • token validation is strict
  • failures fail closed, with no stale-token or delegated fallback
  • business MCP/OBO auth stays separate from OBS auth

I ran everything locally at 3bac1b1 and it passed:

  • all 8 Node samples build, and 426/426 Node OBS tests pass
  • the 4 .NET samples build, and 183/183 ObservabilityAppTokenTests pass
  • 3183/3183 Python tests/observability tests pass (on Windows only with PYTHONUTF8=1; see the inline comment on encoding)

All referenced package versions are published, and nothing depends on the unreleased SDK.

Cross-PR consistency

  • (a) CLI and the legacy route. microsoft/Agent365-devTools#501's "registered blueprint agents need no OtelWrite" was validated on the /otlp route. Five Node samples here export to the legacy non-/otlp route (inline on copilot-studio otel.ts).
  • (b) Credential model and SDK family. microsoft/agent365-skills#84's resolver reuses the hosting connection for each turn's agent identity and scaffolds the @microsoft/opentelemetry distro. These samples use a static single-instance AGENT365_OBS_* config with a duplicate secret, and pin three samples to the legacy preview.115 packages.
  • (c) AI Teammates. The CLI and Skills PRs keep the OtelWrite app-role step for AI Teammates, but the sample docs say not to add OtelWrite.
  • (d) Roleless token contract. The hosting design doc in microsoft/Agent365-nodejs#290 says roleless tokens need explicit idtyp=app. The providers here also accept a token with no idtyp when oid == sub. Could we settle on one documented contract across both repos?
  • (e) After the SDK release. When microsoft/Agent365-nodejs#290 ships, the preview-pinned samples will still use the non-/otlp route; they don't pick up the new behavior.

Items not tied to a changed line

  • [Should-fix] The unused token-cache.ts / token_cache.py modules (the delegated OBS cache pattern this PR retires) are still in nodejs/{devin,langchain,openai} and python/{agent-framework,claude,crewai,openai}. .github/workflows/python-claude-sample.yml still compiles and imports token_cache. Could we delete them?
  • [Should-fix] Step 4 of the message flow in python/openai/sample-agent/docs/design.md still says "Token exchange for observability… cache_agentic_token()".
  • [Nit] python/agent-framework/sample-agent/agent.py still has the old "Microsoft. All rights reserved." header. It was fixed in python/openai but not here.
  • [Question] The OpenAI Node sample bumps @openai/agents 0.1→0.7 and openai 4→6 and drops overrides. Devin, Perplexity and Copilot Studio also get scope and dispose rewrites. The dispose fixes look good, and the OpenAI bump is needed for dedupe. Could the description call these changes out? Its validation counts also look stale: I see 426 Node and 3183 Python tests.

Comment thread nodejs/copilot-studio/sample-agent/src/otel.ts
Comment thread dotnet/agent-framework/sample-agent/Program.cs Outdated
Comment thread python/agent-framework/sample-agent/host_agent_server.py Outdated
Comment thread dotnet/agent-framework/sample-agent/AgentFrameworkSampleAgent.csproj Outdated
Comment thread nodejs/openai/sample-agent/src/observability-token-service.ts
Comment thread nodejs/copilot-studio/sample-agent/package.json Outdated
Comment thread nodejs/langchain/sample-agent/package.json
Comment thread dotnet/agent-framework/sample-agent/appsettings.json
Comment thread dotnet/shared/Observability/ObservabilityAppTokenProvider.cs Outdated
Comment thread nodejs/openai/sample-agent/src/observability-token-service.ts
Align the manager-based Node samples on the Agent365 1.0.0 package family so S2S export uses the /otlp route with the isolated app-token resolver. Update scope calls for the 1.0.0 observability API and extend route/version regression coverage.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5cbf5f6b-cc40-4b7e-a591-65848db73a12
Move Node observability guidance into configuration sections, document the static single-instance provider limitation, AI Teammate OtelWrite caveat, and sovereign-cloud limitation. Remove unused delegated token-cache helpers and stale preview/legacy-route documentation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5cbf5f6b-cc40-4b7e-a591-65848db73a12
Gate .NET and Python observability token providers behind exporter enablement, make .NET helpers sample-local, remove retired Python delegated caches, and add offline observability CI coverage.

Update root and sample documentation for the /otlp route finding, static single-instance provider limitation, AI Teammate OtelWrite caveat, roleless app-token contract, and sovereign-cloud limitations.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5cbf5f6b-cc40-4b7e-a591-65848db73a12
…core pin

- Drop the engines blocks this PR added to copilot-studio and perplexity so
  engine changes stay out of this PR.
- Restore .NET test packages from the repository's default feeds in CI.
- Keep the @opentelemetry/core pin: the 1.0.0 exporter requires it without
  declaring it, so the READMEs now say why.
- Keep internal service-policy detail out of the public route note.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 5cbf5f6b-cc40-4b7e-a591-65848db73a12
@DheerajPannala

Krishnadheeraj (DheerajPannala) commented Sep 28, 2026 •

Copy link
Copy Markdown
Author

Thanks, Rick, and thanks Jason and Dominik for the approvals. I pushed 0f3aefe, 00cec4e, 8ff1e7f and 065753c, and replied on every inline thread.

Blocking item: the five Node samples that exported to the legacy route now use @microsoft/agents-a365-observability@1.0.0 and post to /otlp. I probed both routes live with the same roleless app-only token for a registered agent instance: the legacy non-/otlp route returned 401 (AuthenticationSchemeNotSupported) and /otlp returned 200.

Items not tied to a changed line

  • Deleted the unused delegated token-cache.ts / token_cache.py modules in Node devin/langchain/openai and Python agent-framework/claude/crewai/openai, and removed the token_cache compile/import check from python-claude-sample.yml.
  • Step 4 of python/openai/sample-agent/docs/design.md now describes the app-only resolver flow.
  • Fixed the python/agent-framework/sample-agent/agent.py header.
  • The description now calls out the dependency and code changes (OpenAI @openai/agents 0.1→0.7 and openai 4→6 with overrides dropped; the 1.0.0 scope/dispose rewrites in Devin, Perplexity and Copilot Studio) and has current validation counts: 433 Node, 3185 Python, 197 .NET.

Cross-PR consistency

  • (a) CLI and the legacy route: resolved. Every sample now exports on /otlp, where registered, roleless app-only tokens were validated.
  • (b) Credential model and SDK family:
    • The three preview.115 samples are on 1.0.0.
    • The static single-instance credential stays, to keep telemetry auth isolated from business auth. Its limits are documented prominently: one instance/tenant, a separate blueprint secret, and no managed identity for Node/Python.
    • The docs point multi-instance deployments to the per-identity, hosting-connection approach that agent365-skills#84 uses.
  • (c) AI Teammates: the READMEs and docs/observability-s2s.md now tell users to complete the OtelWrite application-role step that a365 setup all --aiteammate prints, matching #501 and skills#84.
  • (d) Roleless token contract: settled. Agent365-nodejs#290's design doc (acdb9b5) now states the same predicate these providers enforce: idtyp=app, or, when idtyp is absent, a non-empty roles array or a non-empty oid == sub. Any other idtyp value and any scp claim are rejected.
  • (e) After the SDK release: the Node samples are on the /otlp route now, so they no longer depend on the new SDK to pick up the right route. Moving them to 2.0.0 after the release is listed as a follow-up in the description.

Also found while integrating: @microsoft/agents-a365-observability@1.0.0 requires @opentelemetry/core (for ExportResultCode) without declaring it, so the @opentelemetry/core@2.1.0 pin stays in copilot-studio, devin and perplexity. Without it, the exporter fails with MODULE_NOT_FOUND, which the Node suite catches. The READMEs now explain why. The missing declaration is fixed on the SDK side in microsoft/Agent365-nodejs#290 (14fad0c).

CI: all 41 checks pass on 065753c, including the new Observability Offline Tests jobs.

@Jason-R-Lien Jason-R-Lien left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-review of 3bac1b1..065753c

Comment — no new code findings, but the approval gate is still blocked. I reviewed the four-commit, 90-file remediation delta and refreshed the complete review record.

Author-response reconciliation

  • Legacy Node route and SDK migration — accepted. Copilot Studio, Devin, OpenAI, Perplexity, and Vercel now pin the published Agent 365 1.0.0 family, retain useS2SEndpoint = true, and document the /otlp route. The exact-head Node E2E/build checks that exist are green, and the new source-contract tests pin the package family and route.
  • .NET and Python disabled-export startup — accepted. All three .NET entry points use CreateIfEnabled; disabled placeholder configurations, enabled-invalid configurations, and invalid flags have focused tests. Python Agent Framework no longer forces enabled=True, and its bootstrap path is covered.
  • Self-contained .NET samples — accepted. Each sample now owns identical ObservabilityAppTokenFactory.cs and ObservabilityAppTokenProvider.cs copies; project links to dotnet/shared are gone, and the regression suite compares the copies.
  • Single-instance credential model — accepted as a documented sample limitation. The root guide, docs/observability-s2s.md, and sample READMEs explicitly bound the examples to one tenant/instance, a separate blueprint credential, no Node/Python managed identity, and direct multi-instance deployments to a per-agent/per-tenant hosting-connection design.
  • AI Teammate and sovereign-cloud guidance — accepted. The docs preserve the OtelWrite setup step for AI Teammates and state that the hard-coded public-cloud authority requires provider changes for sovereign clouds. Companion PRs Agent365-devTools#501 and agent365-skills#84 carry the same AI Teammate boundary.
  • Roleless token cross-repo contract — accepted. Agent365-nodejs#290 at ceea486 documents the same idtyp=app / nonempty roles / absent-idtyp with oid == sub contract and rejects any scp.
  • UTF-8 and offline CI coverage — accepted. Every tests/observability read_text call is explicit UTF-8; the required orchestrator now runs the Python suite on Windows and ObservabilityAppTokenTests on Ubuntu, and both exact-head jobs passed. The author’s deferred full Node suite and three additional sample builds do not invalidate the requested Python/.NET minimum, but remain manual coverage.
  • Cleanup claims — accepted. The retired Node/Python token-cache files and stale imports/docs are gone, the Agent Framework Python header is corrected, the stale LangChain comment is removed, Node boolean parsing accepts on, unused hosting dependencies are removed where claimed, the .NET instance-ID placeholder is corrected, and refresh lead time is aligned to 60 seconds.
  • Node engine response — accepted as scoped. The temporary Copilot Studio/Perplexity engine edits were removed; LangChain already resolved @microsoft/opentelemetry 1.4.0 from its prior unlocked ^1.0.0 range, so the Node-version mismatch was not introduced by this delta.
  • PR description update — accepted. The live body now calls out the Node 1.0.0/OpenAI dependency and scope/dispose migrations and reports the current 433 Node, 3185 Python, and 197 .NET validation counts.
  • Prior author responses remain accepted. The independent business-auth fixture/mutation oracle and required CI invocation, roleless-token docs, .NET exception/path/exchange fixes, runtime alignment, LINQ/Path.Join changes, intentional appid/azp loop, and explicit Python bearer-token wording remain source-valid at head.
  • Three new Where suggestions — rejected as non-actionable duplicates. They target byte-identical sample-local copies of the same intentional appid/azp loop already reviewed: the loop validates every present claim with one lookup; the suggested rewrite adds another lookup without changing correctness.

Approval gate

All 42 exact-head checks are complete and successful, with zero new blocking or should-fix findings. However, GitHub currently reports 39 review threads, 19 unresolved, including the human change-request threads and the three duplicate Where threads. Step 7 requires every prior thread to be resolved after source verification, so I am leaving a COMMENT rather than re-approving. Once the thread owners resolve/close those discussions, the source and CI evidence support approval; merge remains subject to branch protection.

@Jason-R-Lien Jason-R-Lien left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Metadata-only re-review at 065753c

Comment — no new findings; approval remains blocked only by thread state. The title/description update is consistent with the reviewed source and closes the prior metadata mismatch.

Author-response reconciliation

  • Rollout and dependency guidance — accepted. The live body now states the coordinated SDK 2.0.0 rollout, identifies Agent365-nodejs#290, Agent365-devTools#501, and agent365-skills#84, and records the follow-up from Node 1.0.0 to 2.0.0. This matches the previously verified /otlp migration and companion-PR contracts.
  • Migration and validation claims — accepted. The body now names the OpenAI dependency upgrades, the 1.0.0 scope/dispose rewrites, the retained @opentelemetry/core@2.1.0 workaround, and the current 433 Node / 3185 Python / 197 .NET results. All 42 exact-head checks are complete and successful.
  • Legacy-route fix — accepted. The five affected Node samples use the published 1.0.0 observability family and /otlp; source-contract tests pin that route/package family, consistent with the author's reported 200 /otlp and 401 legacy-route probe.
  • Startup gating and sample isolation — accepted. The .NET samples use CreateIfEnabled, Python Agent Framework no longer forces export on, and each .NET sample owns identical local provider/factory copies. Focused regression coverage exercises disabled placeholders and enabled-invalid configurations.
  • Credential and environment boundaries — accepted as documented limitations. The docs state one configured instance/tenant, a separate blueprint credential, no Node/Python managed identity, the per-agent/per-tenant design for multi-instance hosts, the AI Teammate OtelWrite requirement, and the public-cloud authority limitation.
  • Roleless-token contract — accepted. The providers and Agent365-nodejs#290 align on idtyp=app, or absent idtyp with nonempty roles or oid == sub, while rejecting scp and other idtyp values.
  • Cleanup and coverage claims — accepted. Retired token caches/import checks are removed, the Python design flow and header are corrected, UTF-8 reads are explicit, Node boolean parsing includes on, unused hosting dependencies are removed, and required Windows Python / Ubuntu .NET offline CI is wired and green.
  • Node engine response — accepted as scoped. Temporary engine edits were removed; LangChain's unlocked pre-existing range already resolved to the Node-22-requiring telemetry package, so that compatibility mismatch was not introduced here.
  • Earlier fixes remain accepted. The independent business-auth fixture/mutation oracle and required CI invocation, roleless-token docs, .NET exception/path/exchange fixes, runtime alignment, Path.Join/LINQ cleanups, intentional appid/azp validation loop, and explicit Python bearer-token wording remain source-valid at this unchanged head.
  • Rejected author claims: none. The three Where suggestions were reviewer-generated, not author claims; they were correctly left unchanged because they duplicate the already adjudicated appid/azp loop suggestion without improving correctness.

Approval gate

GitHub currently reports 39 review threads, 16 unresolved. Those are the human change-request threads whose fixes/rationales are accepted above; the three duplicate Where threads have now been resolved. The gate nevertheless requires every prior thread to be resolved, so I am leaving a COMMENT rather than re-approving. Once the remaining thread owners resolve/close those discussions, the source, metadata, and CI evidence support approval; merge remains subject to branch protection.

@DheerajPannala

Copy link
Copy Markdown
Author

I've resolved the 16 remaining review threads. Each has a reply pointing to the commit with the fix, and the fixes were verified in the review at 065753c.

Jason-R-Lien, this should clear the thread gate from your last review.
Rick Brighenti (@rbrighenti), if any of these still needs work, reopen the thread and I'll follow up.

@Jason-R-Lien Jason-R-Lien left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same-head author-response re-review at 065753c

Approved. The author's latest claim is accepted: GitHub now reports all 39 review threads resolved. The head and PR-content hash are unchanged from the prior evidence pass, where the source, updated requirements, and all author-claimed fixes were verified.

Author-response reconciliation

  • Thread-gate claim — accepted. A fresh GraphQL query reports 39 total threads, 0 unresolved.
  • Previously claimed source fixes — accepted. The /otlp and Node 1.0.0 migration, disabled-export startup gating, sample-local .NET providers, UTF-8 handling, offline CI, cleanup, documentation boundaries, roleless-token contract, business-auth guard, and current PR description remain accepted from the prior exact-head source review.
  • Intentional appid/azp loop rebuttal — accepted. The three duplicate Where suggestions are resolved and do not identify a correctness change.
  • Rejected author claims — none.

Approval gate

The PR is open at 065753c; there are zero open blocking or should-fix findings, all review threads are resolved, and all 42 exact-head checks are complete and successful. No later substantive structured-review finding was posted. Merge remains subject to branch protection.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants