-
Notifications
You must be signed in to change notification settings - Fork 56
Add chief-of-staff scenario: Chief of Staff autopilot using Node.js SDK #333
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Yogeshp-MSFT (Yogeshp-MSFT)
wants to merge
7
commits into
microsoft:main
Choose a base branch
from
Yogeshp-MSFT:Chief-of-Staff
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 1 commit
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
6924afa
Add chief-of-staff scenario: Chief of Staff Teammate for Node.js
Yogeshp-MSFT 0b08498
Address Copilot review comments (safe fixes only)
Yogeshp-MSFT 8d96da2
Address second round of Copilot review comments (safe fixes only)
Yogeshp-MSFT 3cbf794
fix(chief-of-staff): snapshot READY payload before markCaptureComplet…
Yogeshp-MSFT 1eb0656
fix(chief-of-staff): wire A365 observability so MAC Activity tab popu…
Yogeshp-MSFT f71e0e6
refactor(chief-of-staff): shared observability module + real UPN in M…
Yogeshp-MSFT 93c9119
refactor(chief-of-staff): sync latest cos-agent — obs polish + card/s…
Yogeshp-MSFT File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,193 @@ | ||
| # ─── A365 platform / server ─── | ||
| NODE_ENV=development | ||
| HOST=127.0.0.1 | ||
| PORT=3978 | ||
| DEBUG=agents:* | ||
|
|
||
| # ─── Logging ─── | ||
| # LOG_LEVEL: error | warn | info | debug | trace (case-insensitive, default=info) | ||
| # LOG_HTTP: when 'true', prints every outgoing Graph/HTTP call with status + latency (secrets redacted) | ||
| LOG_LEVEL=info | ||
| LOG_HTTP=false | ||
|
|
||
| # ─── Agent identity (from `a365 develop setup`) ─── | ||
| agent_id= | ||
| # Agentic auth toggle. `true` uses the agentic OBO exchange for outbound | ||
| # calls (production). `false` falls back to BEARER_TOKEN below (early dev | ||
| # spike only). Leave `true` for the reference deployment. | ||
| USE_AGENTIC_AUTH=true | ||
| connections__service_connection__settings__clientId= | ||
| connections__service_connection__settings__clientSecret= | ||
| connections__service_connection__settings__tenantId= | ||
| connections__service_connection__settings__scopes=5a807f24-c9de-44ee-a3a7-329e88a00ffc/.default | ||
| connectionsMap__0__serviceUrl=* | ||
| connectionsMap__0__connection=service_connection | ||
| agentic_type=agentic | ||
| agentic_connectionName=AgenticAuthConnection | ||
| agentic_altBlueprintConnectionName=service_connection | ||
| agentic_scopes=https://graph.microsoft.com/.default | ||
|
|
||
| # ─── MCP platform ─── | ||
| # Leave empty to use the prod endpoint | ||
| # (https://agent365.svc.cloud.microsoft/agents/servers/*). Set only when | ||
| # pointing at a non-prod ring. | ||
| MCP_PLATFORM_ENDPOINT= | ||
| # Dev-mode bearer token for calling MCP servers when USE_AGENTIC_AUTH=false. | ||
| # Populate via `a365 develop get-token`. Ignored when agentic auth is on. | ||
| BEARER_TOKEN= | ||
| # When `false`, tool-registration failures crash boot (safer default). Set | ||
| # `true` only in constrained dev tenants where a subset of MCP servers is | ||
| # expected to be unavailable. | ||
| SKIP_TOOLING_ON_ERRORS=false | ||
|
|
||
| # ─── Foundry — Azure OpenAI (gpt-4o) ─── | ||
| AZURE_OPENAI_ENDPOINT= | ||
| AZURE_OPENAI_DEPLOYMENT=gpt-4o | ||
| AZURE_OPENAI_API_KEY= | ||
| AZURE_OPENAI_API_VERSION=2024-10-21 | ||
|
|
||
| # ─── Planner (single source of truth) ─── | ||
| # Two paths — you only need ONE. | ||
| # | ||
| # Path A (recommended, simplest): leave PLANNER_PLAN_ID + PLANNER_BUCKET_NEW | ||
| # blank and let the agent auto-resolve them from LEADERSHIP_TEAM_ID at | ||
| # runtime. Requirements: | ||
| # - LEADERSHIP_TEAM_ID is set (any format — GUID / display name / channel email) | ||
| # - The Team has exactly ONE Planner plan → auto-picked | ||
| # (or set PLANNER_PLAN_NAME to disambiguate when the Team has multiple) | ||
| # - The plan contains a bucket named "New" (case-insensitive) → auto-picked | ||
| # (or set PLANNER_BUCKET_NAME to override the search name) | ||
| # | ||
| # Path B (explicit): set both IDs directly. From the Planner URL + Graph Explorer: | ||
| # URL: …/plan/<PLAN_ID>/view/board | ||
| # GET /planner/plans/<PLAN_ID>/buckets → copy the "New" bucket id | ||
| PLANNER_PLAN_ID= | ||
| PLANNER_BUCKET_NEW= | ||
| # Optional overrides for Path A: | ||
| PLANNER_PLAN_NAME= | ||
| PLANNER_BUCKET_NAME=New | ||
|
|
||
| # ─── Leader ─── | ||
| # LEADER_AAD_ID auto-resolves from LEADER_UPN on first turn — leave blank if you like. | ||
| LEADER_UPN= | ||
| LEADER_AAD_ID= | ||
| # Display name used in card copy (e.g. "Assigned by: Alex"). Optional — falls | ||
| # back to "the Leader" when unset. | ||
| LEADER_NAME= | ||
| # ─── Standalone Graph worker app (recommended) ─── | ||
| # When all three are set, EVERY Graph API call uses this app's client | ||
| # credentials (application permissions) instead of the agentic OBO chain. | ||
| # Simpler consent, cleaner reproduction. See README §2b. | ||
| # Leave blank to fall back to the agentic OBO exchange. | ||
| GRAPH_APP_ID= | ||
| GRAPH_APP_SECRET= | ||
| GRAPH_TENANT_ID= | ||
|
|
||
| # ─── Team access control (Recall gate) ─── | ||
| # The leadership Team. Accepts any of: | ||
| # * M365 Group GUID e.g. 44db7598-1234-abcd-… | ||
| # * Teams channel email e.g. 44db7598.contoso.onmicrosoft.com@amer.teams.ms | ||
| # * Team display name e.g. Leadership Operations | ||
| # The last two are resolved to the GUID on first turn and cached for the | ||
| # process lifetime. If blank, Recall is open to anyone in the tenant. | ||
| LEADERSHIP_TEAM_ID= | ||
|
|
||
| # ─── In-process scheduler (cron + pollers) ─── | ||
| SCHEDULER_ENABLED=true | ||
| # Gate for the daily Brief cron. `true` = Brief card fires per CRON_BRIEF. | ||
| # `false` = silenced (all other crons still run). Default in code is false. | ||
| BRIEF_ENABLED=false | ||
| CRON_BRIEF=0 8 * * 1-5 | ||
| CRON_FOLLOWUP=0 * * * * | ||
| CRON_ESCALATE=0 */4 * * * | ||
| # IANA time zone for CRON_* patterns above. If blank, patterns are interpreted | ||
| # in the SERVER's local time — which differs between local dev and Azure App | ||
| # Service (UTC). Set explicitly for reproducibility across environments. | ||
| # Examples: America/Los_Angeles, Asia/Kolkata, Europe/London, UTC | ||
| CRON_TIMEZONE= | ||
| # Meeting-capture orchestrator (calendar-driven — leader-organized + CoS-invited) | ||
| POLL_MEETINGS_MS=60000 # 1 min — cheap; discovery + retry sweep per tick | ||
| POLL_TASKS_MS=300000 | ||
| # Hours to wait for the owner to reply to a follow-up card before escalating | ||
| # to the leader. Sweep runs at every follow-up cron tick. | ||
| FOLLOWUP_ESCALATE_AFTER_HOURS=3 | ||
| # Suppress a fresh check-in for the SAME owner within this window (hours) | ||
| # after they responded / resolved / had a meeting scheduled. Per-owner — | ||
| # reassignment clears the cooldown for the new owner. | ||
| FOLLOWUP_COOLDOWN_HOURS=4 | ||
|
|
||
| # ─── Meeting capture (transcripts + Copilot AI insights) ─── | ||
| # The CoS agent's inviteable UPN — used to filter calendar events. Meetings | ||
| # are only captured when the leader ORGANIZED them AND invited this UPN. | ||
| COS_AGENT_UPN= | ||
| # The CoS agent's AAD Object ID (a GUID, NOT the appId). Required for | ||
| # Adaptive Card DMs — with an application-permission token there is no | ||
| # implicit "caller", so POST /chats needs BOTH members listed explicitly. | ||
| # Look up via: az ad user show --id $COS_AGENT_UPN --query id -o tsv | ||
| COS_AGENT_AAD_ID= | ||
| # Which user's Graph endpoints do we hit? Two modes: | ||
| # cos-agent (default) — we read /users/{COS_AGENT_UPN}/... — Teams | ||
| # application-access policy needs to be granted ONLY to the CoS agent | ||
| # UPN. Zero per-leader setup; any leader who invites the CoS gets | ||
| # captured. Works iff attendee-role access is sufficient for the | ||
| # transcript/insights endpoints in your tenant. | ||
| # leader — we read /users/{LEADER_UPN}/... — policy must be granted to | ||
| # each leader (or -Global). Guaranteed to work but per-leader setup. | ||
| CAPTURE_GRAPH_OWNER=cos-agent | ||
| # How far back to scan the leader's calendar each tick. | ||
| TRANSCRIPT_WATCH_HOURS=4 | ||
| # How far FORWARD to scan the calendar. We include upcoming/in-progress | ||
| # meetings so the transcript-fetch retry loop can start early and pick up | ||
| # transcripts the moment Teams publishes them — even for meetings the | ||
| # leader joined-and-left before their scheduled end. | ||
| TRANSCRIPT_WATCH_FORWARD_HOURS=24 | ||
| # Wait for Copilot AI insights: waitMinutes = clamp(durationMin * mult, min, max) | ||
| INSIGHTS_WAIT_MULTIPLIER=0.5 | ||
| INSIGHTS_MIN_WAIT_MINUTES=3 | ||
| INSIGHTS_MAX_WAIT_MINUTES=30 | ||
| # If transcript still isn't there after this many hours since meeting end, drop. | ||
| CAPTURE_GIVE_UP_AFTER_HOURS=4 | ||
| # Attempt count after which we consider transcript-only capture READY (skips | ||
| # the polite retry for Copilot insights). Default 2 — fires on second attempt | ||
| # if transcript is inlined and insights are still empty. Set to 1 for demo | ||
| # tenants where insights never arrive (fires on first attempt). | ||
| CAPTURE_MIN_ATTEMPTS_TRANSCRIPT_ONLY=2 | ||
|
|
||
| # ─── Display formatting ─── | ||
| # IANA time zone used for wall-clock text in Adaptive Cards (Brief, follow-up, | ||
| # blocker slots, etc.). Set to your leader's home TZ for realistic copy. | ||
| # Examples: America/Los_Angeles, Europe/London, Asia/Kolkata, UTC. | ||
| BRIEF_DISPLAY_TZ=UTC | ||
|
|
||
| # ─── State persistence (single-instance file-backed) ─── | ||
| # STATE_BACKEND=file — persist to STATE_DIR (default; survives restart) | ||
| # STATE_BACKEND=null — in-memory only (lost on restart; use for tests) | ||
| STATE_BACKEND=file | ||
| # Directory for state files. Local dev default: ./.cos-state | ||
| # Azure App Service (single-instance): set to /home/data/cos-state — /home | ||
| # is the per-app persistent volume mounted across restarts. | ||
| STATE_DIR=./.cos-state | ||
| # TTL for finished captures. In-flight (pending/ready) records are always | ||
| # kept; complete/gave-up records older than this many days are pruned on | ||
| # next hydration to keep the JSON file small. | ||
| CAPTURE_STATE_RETENTION_DAYS=30 | ||
| # TTL for terminal follow-ups (responded/resolved). In-flight (pending/ | ||
| # escalated) records are always kept. Set well above the cooldown window | ||
| # in cos/followup.ts so cooldowns survive restart. | ||
| FOLLOWUP_STATE_RETENTION_HOURS=72 | ||
|
|
||
| # ─── Observability ─── | ||
| ENABLE_A365_OBSERVABILITY_EXPORTER=true | ||
| A365_OBSERVABILITY_LOG_LEVEL=info | ||
| # When `true`, the observability SDK uses a caller-supplied resolver for | ||
| # activity attribution instead of the default. Leave `false` unless you've | ||
| # wired a custom resolver. (Note: this key is intentionally mixed-case to | ||
| # match the observability SDK.) | ||
| Use_Custom_Resolver=false | ||
| agent365Observability__agentId= | ||
| agent365Observability__agentName=Chief of Staff | ||
| agent365Observability__agentDescription=Chief of Staff | ||
| agent365Observability__tenantId= | ||
| agent365Observability__agentBlueprintId= | ||
| agent365Observability__clientId= | ||
| agent365Observability__clientSecret= | ||
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| # ─── Node / build ─── | ||
| node_modules/ | ||
| dist/ | ||
|
|
||
| # ─── Secrets ─── never commit | ||
| .env | ||
| .env.bak-* | ||
| .env.local | ||
| cred.json | ||
|
|
||
| # ─── Generated by `a365 develop setup` ─── | ||
| # Per-machine encrypted secret + tenant-specific IDs. Each reproducer | ||
| # regenerates these by running `a365 develop setup`. | ||
| a365.config.json | ||
| a365.generated.config.json | ||
|
|
||
| # ─── Runtime state (regenerated by the process) ─── | ||
| # In-process state (pending captures, follow-ups, conversation refs, planner | ||
| # baseline). Regenerated at runtime — never commit. | ||
| .cos-state/ | ||
|
|
||
| # ─── Logs ─── every reproducer has different ones | ||
| *.log | ||
| log.txt | ||
| logs/ | ||
|
|
||
| # ─── OS / editor ─── | ||
| .DS_Store | ||
| Thumbs.db | ||
| .vscode/ | ||
| .idea/ | ||
|
|
||
| # ─── Personal notes ─── | ||
| todos.md | ||
|
|
||
| # ─── Copilot chat history export (may contain secrets) ─── | ||
| chat.json | ||
|
|
||
| # ─── Generated by `a365 publish --aiteammate` ─── | ||
| # Each reproducer regenerates the manifest with their own agent id. | ||
| manifest/ |
Oops, something went wrong.
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.