Add MEAI: Otel GenAI Manager agentic workflow - #20
Draft
jeffhandley wants to merge 7 commits into
Draft
Conversation
jeffhandley
force-pushed
the
jeffhandley/otel-genai-manager
branch
13 times, most recently
from
July 3, 2026 04:59
bf9bd0a to
d802ac3
Compare
There was a problem hiding this comment.
Pull request overview
Adds a scheduled “MEAI: Otel GenAI Manager/Producer” GitHub Agentic Workflow that continuously tracks and integrates upstream OpenTelemetry GenAI semantic-conventions changes into Microsoft.Extensions.AI, alongside repository scaffolding for hosting gh-aw workflows (PAT pool, MCP config, and supporting skills/scripts).
Changes:
- Introduces a deterministic manager workflow + discovery script that resolves upstream scan targets and invokes a reusable agentic producer workflow.
- Adds a shared Copilot PAT pool component (docs + import workflow) and a scheduled PAT pool validation workflow.
- Refines the existing
update-otel-genai-conventionsskill and PR-body tracking conventions (including release-tag confidence guidance).
Reviewed changes
Copilot reviewed 16 out of 17 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| .github/workflows/validate-pat-pool.yml | New scheduled workflow to validate PAT pool entries via Copilot CLI. |
| .github/workflows/shared/pat_pool.README.md | Documentation for PAT pool onboarding/usage and security rationale. |
| .github/workflows/shared/pat_pool.md | Shared gh-aw import that selects a random PAT slot and outputs its index. |
| .github/workflows/meai-otel-genai-producer.md | New agentic producer workflow definition (prompt + safe outputs + lifecycle rules). |
| .github/workflows/meai-otel-genai-producer.lock.yml | Compiled gh-aw lock workflow for the producer. |
| .github/workflows/meai-otel-genai-manager.yml | New deterministic manager workflow that discovers upstream target and calls producer. |
| .github/workflows/copilot-setup-steps.yml | Adds Copilot setup workflow for gh-aw tooling in the Copilot environment. |
| .github/skills/update-otel-genai-conventions/SKILL.md | Updates skill wording and guidance (release tagging analysis, tracking PR lifecycle ownership). |
| .github/skills/update-otel-genai-conventions/references/pr-description.md | Updates tracking PR body template (release confidence section, YAML-fenced tracking block). |
| .github/skills/agentic-workflows/SKILL.md | Adds router skill to direct gh-aw workflow tasks to the right prompts. |
| .github/skills/agentic-workflow-designer/SKILL.md | Adds interview-style workflow designer skill for gh-aw workflow creation. |
| .github/scripts/meai-otel-genai-producer-setup.sh | Host-side deterministic setup script to discover PR state, compute action, and write target.json. |
| .github/scripts/meai-otel-genai-manager-discover.sh | Deterministic upstream SHA resolution and target emission for the manager. |
| .github/mcp.json | Adds local MCP server wiring for gh aw mcp-server. |
| .github/aw/actions-lock.json | Adds pinned action SHAs used by gh-aw scaffolding. |
| .github/agents/agentic-workflows.md | Adds an agent dispatcher doc for gh-aw workflow work in this repo. |
| .gitattributes | Marks .github/workflows/*.lock.yml as generated and resolves merges with ours. |
jeffhandley
force-pushed
the
jeffhandley/otel-genai-manager
branch
2 times, most recently
from
July 3, 2026 06:53
c06a92a to
a7eae6a
Compare
jeffhandley
force-pushed
the
jeffhandley/otel-genai-manager
branch
3 times, most recently
from
July 3, 2026 08:32
cabf18e to
a467a83
Compare
jeffhandley
force-pushed
the
jeffhandley/otel-genai-manager
branch
from
July 3, 2026 09:09
a467a83 to
c8d26d0
Compare
jeffhandley
force-pushed
the
jeffhandley/otel-genai-manager
branch
from
July 3, 2026 09:50
2d20cea to
2d5031c
Compare
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…scans Move ownership of upstream-scan tracking-PR maintenance out of the skill and onto the maintaining workflow: the skill no longer documents a refresh procedure and instead continues past the tracking PR during its preflight. Switch the tracking-state block delimiters from HTML comments to fenced yaml comments (# otel-genai-tracking:begin/end) so GitHub Actions safe-output processing, which strips HTML comments from PR bodies, preserves them. List every open upstream PR in the in-flight applicability table, and clarify that the defer-constant rule applies only to brand-new attributes with no emission site, not to changes to already-emitted conventions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
jeffhandley
force-pushed
the
jeffhandley/otel-genai-manager
branch
from
July 3, 2026 10:32
2d5031c to
fda4e3c
Compare
jeffhandley
force-pushed
the
jeffhandley/otel-genai-manager
branch
2 times, most recently
from
July 3, 2026 20:41
cb743a4 to
fe42396
Compare
Add a plain (non-agentic) orchestration workflow whose discovery job resolves the open-telemetry/semantic-conventions-genai ref to scan and emits a single self-contained integration target. The discovery script resolves the requested upstream ref (or the default-branch HEAD) to a commit SHA with retries and hard-fails rather than emitting an empty target. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
jeffhandley
force-pushed
the
jeffhandley/otel-genai-manager
branch
2 times, most recently
from
July 4, 2026 05:48
f9dd6ab to
7ea7cdb
Compare
jeffhandley
force-pushed
the
jeffhandley/otel-genai-manager
branch
from
July 7, 2026 02:31
7ea7cdb to
f4496d5
Compare
Add the agentic producer and wire the manager's produce job to invoke it as a reusable workflow (workflow_call) for a single discovery target, so it runs in the manager's run context and inherits the manager's actor -- satisfying the producer's activation role check -- and grant it the contents, pull-requests, issues, and discussions writes it requests. A dry_run dispatch input gates the produce job so a manual run can compute and print the target without invoking the producer. A host setup step resolves the target, discovers and classifies the maintained draft PR (ours / blocked / none), reads the recorded scan state, and computes the recommended lifecycle action, writing target.json for the agent to consume. The agent applies the update-otel-genai-conventions skill to produce the integration and maintains the tracking PR through native gh-aw safe outputs (create, push, update, comment, mark-ready, no-op). A post-step validates that every full-body PR write carries the tracking identity before it can publish. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Let a person hand-start an Otel GenAI integration PR that the automation then takes over and maintains. When a PR on the evergreen branch is labeled automation + area-ai but carries no tracking marker yet, classify it as adopt: the producer writes the tracking block into its body on this run and maintains it thereafter, exactly as if it had opened the PR itself. The automation + area-ai labels are the opt-in -- any other PR occupying the branch stays human-owned and blocks the automation. Recompiled meai-otel-genai-producer.lock.yml. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Extend the producer to address reviewer feedback on the maintained draft PR on the next scheduled run, without triggering on review events. The agent collects the PR's submitted reviews and inline review comments itself through GitHub integrity filtering: tools.github sets min-integrity: approved, and features.integrity-reactions lets a maintainer promote an external contributor's comment to approved with an endorsement reaction. Only write-access and endorsed feedback reaches the agent, so it applies no host-side trust handling of its own. The host setup records a feedback-processed-through watermark and this run's run_started_at in target.json, and computes a body-free wake gate that counts review activity newer than the watermark so a caught-up PR still wakes the agent when new review activity exists. If any of the three activity queries fails, the gate opens automatically, keeping a transient API error from masking real, unprocessed feedback. The agent acts on feedback created after the watermark, folds in-scope feedback into the differential commit(s), rejects out-of-scope requests, resolves contradictions by recency, and advances the watermark to run_started_at. Fetch the maintained PR body with a three-attempt retry and gate the watermark read and wake gate on a successful read, so a transient blip never drops the tracking marker and replays feedback from an empty watermark. If a persistent failure still leaves the PR classified ours with an empty recorded scan ref and watermark, the agent re-reads the body itself once to recover them before scoping feedback or computing the differential, and if that read also fails treats the watermark as this run's start rather than reprocessing every earlier comment. Strip trailing inline # comments when reading the tracking block's feedback-processed-through, upstream-scan-ref, and upstream-release values. Require every iterative update to the maintained PR -- the incremental, feedback-only, and release mark-ready paths -- to fully regenerate the PR description via update-pull-request so it always reflects the current integrated state, including a feedback-only run that only advances the watermark. The behind non-draft advisory path is the exception: it only comments, so a PR a human has marked Ready for review keeps its body. Scope tracking-block extraction to the machine-managed block so human prose in the PR body cannot shadow the recorded state: read every field through tracking_block(), which emits only the last `# meai-otel-genai-producer:state:begin` .. `:state:end` range (the skill writes the live block at the very bottom, so the body ends with it). Otherwise a "> upstream-scan-ref:" line, a future "> feedback-processed-through:", or an older block a maintainer pastes above the live one would win tracking_value's first match and could force a false caught-up no-op or silently suppress real reviewer feedback. Apply the same within-block scoping in the publish guardrail so the guard and the extractor stay symmetric. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
jeffhandley
force-pushed
the
jeffhandley/otel-genai-manager
branch
from
July 7, 2026 04:44
f4496d5 to
d4c5212
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR adds MEAI: Otel GenAI Manager, a scheduled GitHub Agentic Workflow (gh-aw) that continuously integrates OpenTelemetry GenAI semantic-conventions updates into
Microsoft.Extensions.AI. A deterministic manager resolves the upstream scan target and fans out to an agentic producer that wraps the existingupdate-otel-genai-conventionsskill and maintains a single draft pull request tracking the upstreamopen-telemetry/semantic-conventions-genairepository, incrementally folding in new convention changes as they land upstream.It also lands the gh-aw scaffolding this repository needs to host agentic workflows (agent definitions, the Copilot PAT pool, and MCP configuration), plus small refinements to the
update-otel-genai-conventionsskill so it delegates tracking-PR lifecycle to the maintaining workflow.How it works
Otel GenAI Manager (
.github/workflows/meai-otel-genai-manager.yml+meai-otel-genai-manager-discover.sh) -- deterministic discovery, no agent. It scansopen-telemetry/semantic-conventions-genaiat the default-branch HEAD (or an explicitupstream_refwhen dispatched), resolving it to a concrete commit SHA with automatic retry, and emits a single fully-specified target. It invokes the producer as a reusable workflow (workflow_call) once.Otel GenAI Producer (
.github/workflows/meai-otel-genai-producer.md-> compiled.lock.yml, +meai-otel-genai-producer-setup.sh) -- a host-side setup step locates the standing draft tracking PR, classifies it, and computes the recommended lifecycle action from the recorded scan ref vs. the freshly resolved upstream SHA. The agent then delegates all convention analysis and implementation to theupdate-otel-genai-conventionsskill, builds and tests the change, folds in reviewer feedback, and a safe-output layer refreshes the draft PR for a human to review and merge.Behavior
update-otel-genai-to-latestbranch still lingers from a previously closed PR, the new PR is opened on a run-scoped branch to preserve the existing one, and a> [!NOTE]block documenting the deviation is added to the PR body../build.sh -vs AIthen./build.sh -build -test) before a PR is opened or updated. When the internal NuGet feeds are unreachable and the change cannot be validated, the run emits areport_incompletesignal and fails, keeping every published PR build-and-test validated.min-integrity: approved): only reviews and comments from write-access reviewers (OWNER/MEMBER/COLLABORATOR) -- plus any external comment a maintainer has endorsed with a 👍/❤️ reaction -- reach the agent. Conflicting comments resolve to the most recent guidance. The tracking block'sfeedback-processed-throughwatermark advances to the run's start time each run, so feedback is processed exactly once across runs -- this cross-run dedup is the "already handled" signal.automationlabel is an intentional pause -- therequired-labelssafe-output gate holds all writes until the label is restored.automation+area-aiand carries a machine-readable state block delimited by# meai-otel-genai-producer:state:begin/:state:endsentinel comments in its body. Before publishing, a post-run guardrail validates that every full-body PR write still carries that state block -- the sentinel markers, a non-emptyupstream-scan-ref, and afeedback-processed-throughwatermark -- matching the sentinels as whole comment lines and each field the same quote/comment-tolerant way the next run's setup parses it, so every published body is guaranteed resumable by the next run.upstream_refinput exists primarily for time-travel testing and targeted re-scans; scheduled runs always scan the upstream default-branch HEAD.Supporting changes
New agentic workflow (manager + producer)
.github/workflows/meai-otel-genai-manager.yml,.github/scripts/meai-otel-genai-manager-discover.sh-- the deterministic discovery manager..github/workflows/meai-otel-genai-producer.md-> compiled.github/workflows/meai-otel-genai-producer.lock.yml,.github/scripts/meai-otel-genai-producer-setup.sh-- the agentic producer and its host-side setup/classification.gh-aw + PAT pool infrastructure
.github/agents/agentic-workflows.md,.github/skills/agentic-workflow-designer/SKILL.md,.github/skills/agentic-workflows/SKILL.md-- agent/skill definitions for authoring workflows..github/aw/actions-lock.json,.github/mcp.json,.github/workflows/copilot-setup-steps.yml-- gh-aw scaffolding..github/workflows/shared/pat_pool.md,.github/workflows/shared/pat_pool.README.md-- the Copilot PAT pool integration that selects a random PAT from a numbered pool to avoid single-token rate limiting.Skill refinements (
update-otel-genai-conventions)yamlblock whose first and last lines are# meai-otel-genai-producer:state:begin/:state:endsentinel comments, because safe-output processing strips HTML comments from PR/issue bodies.Validation
The full lifecycle was exercised end-to-end against a dedicated test repository by forcing historical upstream commit SHAs into the
upstream_refdispatch input to simulate progressing through time. Every reachable scenario passed cleanly:Test plan executed -- chaos-monkey end-to-end validation of the deterministic host-side logic
A comprehensive, adversarial ("chaos monkey") test pass drove the manager and producer's deterministic scripts and lock-file shell steps -- upstream discovery, producer setup classification/action, the review-activity wake gate, tracking-block parsing, and the manifest guardrail -- against a mock
ghharness with fixture-driven responses and failure injection. Trust and feedback selection are delegated to gh-aw integrity filtering (min-integrity: approvedplus maintainer endorsement reactions), enforced by the framework itself. The pass validated the setup's resilience behavior, notably retrying the PR-body fetch to keep the tracking marker intact and our own PR correctly classified across transient API blips. It also expanded into the release-gate lifecycle, command-injection safety, forward-threaded idempotence sequences, targeted failure injection, and a full cross-script handoff round-trip, and was capped by randomized property-based fuzzing and an exhaustive combinatorial sweep of the decision state space. Along the way it surfaced and fixed one defect on the release path (an unresolvable release tag could abort a run; readiness now degrades gracefully instead). Scenarios executed:ours(marker present),adopt(automation labels, no marker),blocked(human-owned PR on the branch),none(no PR), and the body-fetch-blip fallback (unreadable body but automation labels present is treated asours, preserving prior ownership). A fork PR reusing the branch name is filtered out by head-repository owner, and both discovery stages are scoped to PRs whose base ismain(matching the create-pull-requestbase-branch), so a PR reusing the tracking branch but targeting a different base -- e.g. a backport onto a release branch -- is never mistaken for the maintained PR.adoptalways produces, even when the SHA looks current, so the tracking block is written on adoption; empty recorded-SHA and empty upstream-SHA guards; most-recently-updated PR selection when multiple PRs occupy the branch.release_matches_scan,release_matches_pr, andrelease_readyare computed independently. When a published release exists but its tag cannot be resolved to a commit (for example a brief replication lag between the releases and git-refs APIs, or a retagged release), readiness is withheld at low confidence and the run continues normally rather than aborting. The draft mark-ready path (release_pending) always produces so the Ready-for-review transition completes, settling to a no-op only once the PR is non-draft with the release recorded in its body.has_new_feedbackso a caught-up PR is woken for a feedback-only update; activity at or before the watermark leaves the gate closed; an empty watermark opens the gate. Each of the three activity queries (issue comments, review comments, submitted reviews) is retried, and if any still fails the gate opens rather than under-counting, so a transient blip never drops real feedback. Bot activity (including the automation's own summary comments) is filtered out to avoid a self-wake loop. The gate is author-agnostic and body-free -- it only decides whether to wake the agent, while integrity filtering governs which feedback the agent may then see.adopt->oursis one-way, so a PR is never re-adopted once its tracking marker is written; and a torn run that refreshed the body but never advanced the recorded SHA self-heals on the next run. The no-op state is stable across identical reruns, and the watermark advances monotonically so a given piece of feedback is processed exactly once.update-otel-genai-to-latest_<run_id>, digits only) while rejecting near-miss suffixes (_12a, a bare trailing_,_1_2, an embedded1a2, and a trailing underscore), and validates that each candidate's recorded scan ref is a well-formed commit SHA before selecting the most recently updated one.#comment values; CRLF line endings (GitHub returns\r\n); indented field names; an optional leading markdown list/quote marker (-,*,+,>) on field values; bare marker with no fields. The setup parser and the publish-time guardrail match the sentinels as whole comment lines and read each field the same quote/comment-tolerant way, and both scope extraction to the last# meai-otel-genai-producer:state:begin/:state:endrange, so any body that passes the guard is guaranteed parseable next run -- format drift or human prose cannot wedge the state machine into a permanent re-produce / re-wake loop.$(...), backticks,;,|,&) embedded in PR-body tracking values, branch names, and refs are carried strictly as data; a command-execution canary confirmed no substitution ever fires along any parsing path. Branch-name injection is rejected by the numeric-suffix guard, a field-name prefix such asx-upstream-scan-refdoes not false-match the real field, and oversized (20 KB), unicode, and control-character bodies parse without error. Malicious values never produce a false no-op -- an unrecognized scan ref simply drives a produce.{}, and fully-specifiedTARGET_JSONall resolve to safe defaults; a missing repository/token safely falls back to a fresh-produce decision, keeping the run productive. The producer setup independently re-resolves the scan ref and hard-fails (exit 1) rather than proceeding with an emptyupstream_sha, so a standalone dispatch with an unresolvableupstream_reffails fast instead of publishing an unrecoverable body. An end-to-end round-trip feeds the manager's real discovery output straight into the producer setup, confirming the resolved SHA is passed through verbatim (never silently re-resolved to a different commit) and that the custom repo and branch fields drive the state machine, withoursclassification gated on the hard-coded# meai-otel-genai-producer:state:sentinel written into the tracking block.upstream-scan-ref, or thefeedback-processed-throughwatermark fails the run, including the mixed valid-plus-invalid batch case.cancel-in-progress: falseconcurrency group serializes runs, keeping pushes to the single evergreen PR strictly sequential; removing theautomationlabel mid-run is a coherent atomic pause (therequired-labelssafe-output gate holds both the code push and the tracking-block update together, keeping the PR in a consistent state, and the next run re-does the work idempotently).adopt, or fresh state produces;blockedstands down; and an unresolvable release withholds readiness without aborting. These invariants were exercised both by randomized property-based fuzzing over the full state space and by an exhaustive combinatorial sweep of every discrete state (PR classification x recorded-SHA x draft x release resolvability x recorded release x feedback timing), with zero violations across every case, confirming the decision logic cannot silently skip real work or crash on any modeled state.Deployment prerequisite
The safe-output publish path creates and updates the tracking PR with
GITHUB_TOKEN, so the repo/org must enable "Allow GitHub Actions to create and approve pull requests" (actions/permissions/workflow can_approve_pull_request_reviews=true). Copilot requests in the agent are funded by thecopilot-pat-poolenvironment.Draft for iteration.