Skip to content

Add Salesforce Apex native Agent 365 observability sample#327

Open
rbrighenti wants to merge 1 commit into
mainfrom
user/rbrighenti/salesforce-apex
Open

Add Salesforce Apex native Agent 365 observability sample#327
rbrighenti wants to merge 1 commit into
mainfrom
user/rbrighenti/salesforce-apex

Conversation

@rbrighenti

Copy link
Copy Markdown
Contributor

Add Salesforce/Apex observability sample under a new top-level salesforce/ folder.

What this sample demonstrates:

  • Apex exposed as an Agent 365 tool surface (REST + Agentforce @InvocableMethod)
  • Native Apex OTLP span emission, correlated to the agent turn by a shared W3C trace id (fail-open, async via Queueable, config-gated)
  • Hand-rolled FMI 3-hop agent-bound token in Apex (MSAL is unavailable in Apex)
  • Salesforce originating a trace from an Agentforce turn

Add Salesforce/Apex observability sample under a new top-level `salesforce/` folder.

What this sample demonstrates:
- Apex exposed as an Agent 365 tool surface (REST + Agentforce @InvocableMethod)
- Native Apex OTLP span emission, correlated to the agent turn by a shared W3C
  trace id (fail-open, async via Queueable, config-gated)
- Hand-rolled FMI 3-hop agent-bound token in Apex (MSAL is unavailable in Apex)
- Salesforce originating a trace from an Agentforce turn

Repo integration:
- Top-level README, CLAUDE.md, and .gitignore updated for Salesforce.
@rbrighenti rbrighenti requested a review from a team as a code owner June 24, 2026 17:21
Copilot AI review requested due to automatic review settings June 24, 2026 17:21
@github-actions

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

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

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.

Pull request overview

Adds a new top-level salesforce/ area containing an SFDX sample that demonstrates native Salesforce Apex Agent 365 observability: emitting Agent 365 OTLP spans from Apex, correlating spans to an agent turn via W3C trace context, and (optionally) originating traces from an Agentforce turn with deterministic seeding.

Changes:

  • Introduces salesforce/apex-observability/ SFDX project with Apex classes, metadata, scripts, and docs for Agent 365 OTLP emission + FMI 3-hop agent-bound token acquisition.
  • Adds Apex unit tests covering trace parsing/seeding, OTLP body shape, token hop behavior, fail-open behavior, and gating.
  • Updates repository-level docs and ignore rules to include the new Salesforce/Apex samples.

Reviewed changes

Copilot reviewed 67 out of 68 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
salesforce/docs/design.md Cross-sample Salesforce design/convention guidance.
salesforce/apex-observability/sfdx-project.json SFDX project definition for the sample.
salesforce/apex-observability/scripts/verify-span.apex Execute-Anonymous smoke script to enqueue and verify span ingest.
salesforce/apex-observability/scripts/create-obs-config.apex Execute-Anonymous seeding script for CMDT config record.
salesforce/apex-observability/README.md End-to-end sample documentation (deploy/config/test/troubleshoot).
salesforce/apex-observability/force-app/main/default/permissionsets/A365_Observability.permissionset-meta.xml Permission set for Apex class + external credential principal access.
salesforce/apex-observability/force-app/main/default/objects/A365_Observability_Config__mdt/A365_Observability_Config__mdt.object-meta.xml CMDT type for non-secret runtime config.
salesforce/apex-observability/force-app/main/default/objects/A365_Observability_Config__mdt/fields/Enabled__c.field-meta.xml CMDT kill switch for boundary emission.
salesforce/apex-observability/force-app/main/default/objects/A365_Observability_Config__mdt/fields/TenantId__c.field-meta.xml CMDT tenant id field for routing/headers.
salesforce/apex-observability/force-app/main/default/objects/A365_Observability_Config__mdt/fields/AgentId__c.field-meta.xml CMDT agent id field for routing/token binding.
salesforce/apex-observability/force-app/main/default/objects/A365_Observability_Config__mdt/fields/IngestBase__c.field-meta.xml CMDT ingest base field (documented host).
salesforce/apex-observability/force-app/main/default/objects/A365_Observability_Config__mdt/fields/ObsScope__c.field-meta.xml CMDT observability scope field.
salesforce/apex-observability/force-app/main/default/objects/A365_Observability_Config__mdt/fields/FmiScope__c.field-meta.xml CMDT FMI scope field.
salesforce/apex-observability/force-app/main/default/objects/A365_Observability_Config__mdt/fields/UseS2SEndpoint__c.field-meta.xml CMDT toggle for S2S vs non-S2S ingest path.
salesforce/apex-observability/force-app/main/default/objects/A365_Observability_Config__mdt/fields/ServiceName__c.field-meta.xml CMDT boundary service.name field.
salesforce/apex-observability/force-app/main/default/objects/A365_Observability_Config__mdt/fields/AgentforceServiceName__c.field-meta.xml CMDT originated-trace service.name field.
salesforce/apex-observability/force-app/main/default/objects/A365_Observability_Config__mdt/fields/OriginateEnabled__c.field-meta.xml CMDT kill switch for origination path.
salesforce/apex-observability/force-app/main/default/namedCredentials/A365_Obs_Token.namedCredential-meta.xml Named Credential for FMI hop 1/2 (Basic auth injected).
salesforce/apex-observability/force-app/main/default/namedCredentials/A365_Obs_TokenJwt.namedCredential-meta.xml Named Credential for FMI hop 3 (no auth header).
salesforce/apex-observability/force-app/main/default/namedCredentials/A365_Obs_Ingest.namedCredential-meta.xml Named Credential for OTLP ingest endpoint.
salesforce/apex-observability/force-app/main/default/namedCredentials/A365_Callback.namedCredential-meta.xml Named Credential placeholder for optional /callback callout.
salesforce/apex-observability/force-app/main/default/externalCredentials/A365_Obs_Entra.externalCredential-meta.xml External Credential to hold blueprint secret (Setup-entered).
salesforce/apex-observability/force-app/main/default/customMetadata/A365_Observability_Config.Default.md-meta.xml Template CMDT record (excluded from deploy; used as documentation).
salesforce/apex-observability/force-app/main/default/cachePartitions/A365Obs.cachePartition-meta.xml Optional Platform Cache partition for token/root dedup caching.
salesforce/apex-observability/force-app/main/default/classes/A365Trace.cls W3C traceparent parsing + deterministic seed helpers.
salesforce/apex-observability/force-app/main/default/classes/A365Trace.cls-meta.xml ApexClass metadata for A365Trace.
salesforce/apex-observability/force-app/main/default/classes/A365TraceTest.cls Unit tests for traceparent parsing and id generation.
salesforce/apex-observability/force-app/main/default/classes/A365TraceTest.cls-meta.xml ApexClass metadata for A365TraceTest.
salesforce/apex-observability/force-app/main/default/classes/A365TraceSeedTest.cls Unit tests for deterministic seed helpers.
salesforce/apex-observability/force-app/main/default/classes/A365TraceSeedTest.cls-meta.xml ApexClass metadata for A365TraceSeedTest.
salesforce/apex-observability/force-app/main/default/classes/A365ObsConfig.cls CMDT reader with safe defaults + test override support.
salesforce/apex-observability/force-app/main/default/classes/A365ObsConfig.cls-meta.xml ApexClass metadata for A365ObsConfig.
salesforce/apex-observability/force-app/main/default/classes/A365ObsSpan.cls OTLP JSON body builder matching Agent 365 ingest expectations.
salesforce/apex-observability/force-app/main/default/classes/A365ObsSpan.cls-meta.xml ApexClass metadata for A365ObsSpan.
salesforce/apex-observability/force-app/main/default/classes/A365ObsSpanTest.cls Unit tests for OTLP body wire shape and correlation.
salesforce/apex-observability/force-app/main/default/classes/A365ObsSpanTest.cls-meta.xml ApexClass metadata for A365ObsSpanTest.
salesforce/apex-observability/force-app/main/default/classes/A365ObsToken.cls FMI 3-hop token acquisition + caching helpers.
salesforce/apex-observability/force-app/main/default/classes/A365ObsToken.cls-meta.xml ApexClass metadata for A365ObsToken.
salesforce/apex-observability/force-app/main/default/classes/A365ObsTokenTest.cls Unit tests for hop bodies, ordering, and error behavior.
salesforce/apex-observability/force-app/main/default/classes/A365ObsTokenTest.cls-meta.xml ApexClass metadata for A365ObsTokenTest.
salesforce/apex-observability/force-app/main/default/classes/A365Telemetry.cls Public façade for boundary emission + origination paths.
salesforce/apex-observability/force-app/main/default/classes/A365Telemetry.cls-meta.xml ApexClass metadata for A365Telemetry.
salesforce/apex-observability/force-app/main/default/classes/A365TelemetryQueueable.cls Async worker to acquire token and POST OTLP spans.
salesforce/apex-observability/force-app/main/default/classes/A365TelemetryQueueable.cls-meta.xml ApexClass metadata for A365TelemetryQueueable.
salesforce/apex-observability/force-app/main/default/classes/A365TelemetryTest.cls Unit tests for boundary emission, gating, fail-open, caching.
salesforce/apex-observability/force-app/main/default/classes/A365TelemetryTest.cls-meta.xml ApexClass metadata for A365TelemetryTest.
salesforce/apex-observability/force-app/main/default/classes/A365TelemetryOriginateTest.cls Unit tests for origination path behavior and dedup.
salesforce/apex-observability/force-app/main/default/classes/A365TelemetryOriginateTest.cls-meta.xml ApexClass metadata for A365TelemetryOriginateTest.
salesforce/apex-observability/force-app/main/default/classes/A365ToolRest.cls Apex REST tool surface + SERVER span emission.
salesforce/apex-observability/force-app/main/default/classes/A365ToolRest.cls-meta.xml ApexClass metadata for A365ToolRest.
salesforce/apex-observability/force-app/main/default/classes/A365ToolRestTest.cls REST contract tests + emission enabled/disabled regression guards.
salesforce/apex-observability/force-app/main/default/classes/A365ToolRestTest.cls-meta.xml ApexClass metadata for A365ToolRestTest.
salesforce/apex-observability/force-app/main/default/classes/A365Callout.cls Optional outbound callback callout + CLIENT span emission.
salesforce/apex-observability/force-app/main/default/classes/A365Callout.cls-meta.xml ApexClass metadata for A365Callout.
salesforce/apex-observability/force-app/main/default/classes/A365CalloutTest.cls Unit tests for callback behavior + client-span emission.
salesforce/apex-observability/force-app/main/default/classes/A365CalloutTest.cls-meta.xml ApexClass metadata for A365CalloutTest.
salesforce/apex-observability/force-app/main/default/classes/A365AgentforceTool.cls Agentforce invocable action that originates traces from a turn.
salesforce/apex-observability/force-app/main/default/classes/A365AgentforceTool.cls-meta.xml ApexClass metadata for A365AgentforceTool.
salesforce/apex-observability/force-app/main/default/classes/A365AgentforceToolTest.cls Unit tests for Agentforce origination behavior + fallbacks.
salesforce/apex-observability/force-app/main/default/classes/A365AgentforceToolTest.cls-meta.xml ApexClass metadata for A365AgentforceToolTest.
salesforce/apex-observability/docs/design.md Sample-specific architecture (flows/token model/wire shape).
salesforce/apex-observability/agent/README.md Instructions for building the optional Agentforce agent per-org.
salesforce/apex-observability/agent/A365_Observability_Sample.agent Reference Agent Script wiring for Agentforce origination path.
salesforce/apex-observability/.gitignore Sample-level ignore rules for SFDX artifacts/logs.
salesforce/apex-observability/.forceignore Excludes CMDT record deploy to avoid CLI UNKNOWN_EXCEPTION issues.
README.md Updates repository summary to include Salesforce/Apex samples.
CLAUDE.md Documents Salesforce sample layout and CLI commands; adds Apex header guidance.
.gitignore Adds repository-level ignores for SFDX local artifacts.

-->
<NamedCredential xmlns="http://soap.sforce.com/2006/04/metadata">
<label>A365 Callback</label>
<endpoint>https://REPLACE-WITH-YOUR-TUNNEL-URL.devtunnels.ms</endpoint>
Comment on lines +55 to +61
String tenantId = A365ObsConfig.tenantId();
String agentId = A365ObsConfig.agentId();
String token = A365ObsToken.getToken();

String body = A365ObsSpan.buildBody(
tenantId, agentId, traceId, parentSpanId, spanId,
spanName, kind, statusCode, attrs, startNs, endNs, serviceName);
| `Enabled__c` | `true` | Master kill switch for the boundary emitter (`false` = no-op). |
| `TenantId__c` | `<<TENANT_ID>>` | Entra tenant id. |
| `AgentId__c` | `<<AGENT_ID>>` | Agent 365 agent id (in the ingest URL; token `azp` must match). |
| `IngestBase__c` | `https://agent365.svc.cloud.microsoft` | OTLP ingest host. |
Comment thread README.md

This samples repository is currently in active development and contains:
- **Sample Agents**: Production-ready examples in C#/.NET, Python, and Node.js/TypeScript demonstrating observability, notifications, tooling, and hosting patterns
- **Sample Agents**: Production-ready examples in C#/.NET, Python, Node.js/TypeScript, and Salesforce/Apex demonstrating observability, notifications, tooling, and hosting patterns
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.

2 participants