Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
200 changes: 200 additions & 0 deletions scenarios/chief-of-staff/.env.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
# ─── 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
# Runtime agent identity (the AGENTIC INSTANCE app id, not the blueprint).
# Normally left blank — it is read per turn from activity.recipient.agenticAppId.
# Set it only for a deployment where inbound activities don't carry it; a wrong
# value here makes every span unbindable and MAC Activity stays empty.
agent365Observability__agentInstanceId=
# NOTE: agent365Observability__agentId holds the BLUEPRINT id and is used only
# as span metadata + for warming the blueprint's observability token.
agent365Observability__agentId=
agent365Observability__agentName=Chief of Staff
agent365Observability__agentDescription=Chief of Staff
agent365Observability__tenantId=
agent365Observability__agentBlueprintId=
agent365Observability__clientId=
agent365Observability__clientSecret=
41 changes: 41 additions & 0 deletions scenarios/chief-of-staff/.gitignore
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/
Loading
Loading