内容
<div align="center">
<img src="afterlogin-title.png" alt="Afterlogin — The Hunt × Helper Patrol: one keyhole between a haunted manor and a helper factory" width="840"/>
<sub><i>Key art generated with Azure OpenAI <code>gpt-image-2</code> — the two worlds, joined by the keyhole.</i></sub>
# 🕯️ Afterlogin — The Hunt × Helper Patrol
### A cinematic game that *trains real identity-security response* — powered by genuine, tool-calling AI agents.
*One engine, two faces: a tense SOC night for security pros, and a coached training game for everyone else.*
[](https://victorious-plant-0c1e7790f.7.azurestaticapps.net)
[](#-how-it-works)
[](#-microsoft-iq-integration--foundry-iq)
[](mcp/)
[](LICENSE)
**Built for the [Microsoft Agents League](https://aka.ms/agentsleague) · Creative Apps track**
`Azure AI Foundry` · `Model Context Protocol` · `Azure OpenAI / GitHub Models` · `GitHub Copilot` · `Azure Static Web Apps`
[**▶ Play it**](https://victorious-plant-0c1e7790f.7.azurestaticapps.net) · [**Architecture**](#-how-it-works) · [**Try in 60 s**](#-quick-start)
> **Status — fully live.** The deployed app is running **real tool-calling agents** (`gpt-4o` via GitHub
> Models) and **Foundry IQ** grounded retrieval right now. Open the in-app **🗺 Live architecture** map and
> it pings the endpoints live — **10 of 11 services verify green**, badge reads **● Live agents · gpt-4o**.
</div>
---
## 📑 Table of contents
- [Overview](#-overview)
- [The problem](#-the-problem)
- [The solution](#-the-solution)
- [Key features](#-key-features)
- [How it works](#-how-it-works)
- [Microsoft IQ integration → Foundry IQ](#-microsoft-iq-integration--foundry-iq)
- [GitHub Copilot](#-github-copilot)
- [What you actually learn](#-what-you-actually-learn)
- [Quick start](#-quick-start)
- [Deployment](#-deployment)
- [Project structure](#-project-structure)
- [Judging-criteria mapping](#-judging-criteria-mapping)
- [Security & responsible AI](#-security--responsible-ai)
- [Tech stack](#-tech-stack)
- [License](#-license)
---
## 🌙 Overview
**Afterlogin** is a playable, cinematic security-training game. You are the **night auditor of a haunted
estate** — every "spirit" is a real, forgotten identity (a stale admin, an unowned service account, an
over-permissioned app). An **AI agent council** investigates each one and *advises* — but it can be
wrong, and it never makes the call. **You** decide its fate before dawn. Neglect a high-risk account and
an adversary takes it over, triggering a **multi-stage attack kill-chain** you fight by choosing the
control that *actually* stops the attack.
It ships in two skins from one engine: **🕯️ The Hunt** (haunted manor, for security pros) and
**☀️ Helper Patrol** (a friendly factory, for coached beginners).
> 🎮 **Play now:** https://victorious-plant-0c1e7790f.7.azurestaticapps.net
---
## 🎯 The problem
> **Forgotten and over-privileged identities are the #1 way attackers get into an organization.**
A dormant admin no one deprovisioned. A service account whose owner left. An app granted tenant-wide
consent that nobody reviews. Every identity someone *stopped watching* is a door left unlocked — and the
hard part isn't the tooling, it's the **human judgment**: knowing which account is safe to remove, which
is load-bearing, and which control *actually* stops a given attack. The classic, expensive mistakes:
- A **password reset** doesn't kill a **stolen session token**.
- **Revoking sessions** doesn't remove an **illicit OAuth grant**.
- **MFA** doesn't strip **standing Global Admin**.
And as teams adopt AI copilots for security, a *new* discipline matters: **not blindly trusting the AI** —
verifying before you act. There's little that *trains* that judgment in a way people actually want to do.
---
## 💡 The solution
Afterlogin turns identity-attack response into a game you *want* to play — and every move maps to a
**real Microsoft control**:
| In the game | Real control |
|---|---|
| **Divine** an account | Map its dependencies / lineage |
| **Summon** the council | Multi-agent investigation + **Foundry IQ** grounded, cited evidence |
| **Lay to Rest** | Deprovision via a lifecycle workflow |
| **Bind & Watch** | Conditional Access + monitoring |
| **Acknowledge** | Certify in an access review |
| **Boss kill-chain** | Pick the control that remediates the live attack |
The AI **advises**; the human **decides** (a **Discernment** meter rewards verifying over rubber-stamping —
human-in-the-loop, made a mechanic). A **Pro view** surfaces the real control behind every action, a
**mission briefing** explains the why on first launch, and a **live architecture map** lets a judge press a
button and watch the real agents fire.
---
## ✨ Key features
| | Feature |
|---|---|
| 🤖 | **Real multi-agent system** — Warden + Skeptic *debate* via function tools; a Council synthesises a **cited** advisory and never names the verdict |
| 🔎 | **Foundry IQ grounded retrieval** (live) — Azure AI Search–backed, cited evidence in the council |
| ⛓️ | **MCP server** — the same identity tools exposed over the Model Context Protocol for **GitHub Copilot / VS Code / Foundry** |
| ☁️ | **Azure AI Foundry** connected-agents tier (optional), with graceful fallback: Foundry → live agents → scripted |
| 🗺️ | **Interactive Live Architecture Map** — tap any node for what it does; **"Run a live investigation"** fires the real agents and lights the path |
| 🎓 | **Real training** — telegraphed kill-chains, an attack-technique stage tracker, control hover-cards, and a run-end "what you practiced" debrief |
| 🎬 | **Cinematic UX** — keyhole boot, split-world landing, living encounters, arena combat, sunrise finale (8 original generated artworks) |
| ♻️ | **Roguelite depth** — Discernment meter, relics, daily challenge, ranks, cross-examine deduction |
---
## 🧠 How it works
The council is a genuine **multi-agent, tool-calling** system — not a single chatbot. The **Warden** and
**Skeptic** each call function tools over a synthetic identity store, investigate independently, **debate**,
and a **Council** agent synthesises a **cited** advisory.
```mermaid
flowchart LR
Dev[GitHub Copilot<br/>in VS Code] -. builds / drives .-> G
G[Game UI<br/>encounter + combat] -->|account| API[/api/reason<br/>Azure Function/]
subgraph Council [Multi-agent council]
W[🛡 Warden agent] -->|debate| S[🔍 Skeptic agent] --> C[✓ Council agent]
end
API --> Council
Council -->|tool calls| T[(Identity tools<br/>signin · deps · oauth · groups)]
T -->|cited results| Council
API -->|grounded query| FIQ[Foundry IQ<br/>Azure AI Search<br/>grounded retrieval]
FIQ -->|cited evidence| C
Council -->|warden · skeptic · verdict<br/>+ citations + trace| G
T -. also exposed over .-> MCP[[MCP server<br/>GitHub Copilot / VS Code / Foundry]]
API -. optional .-> F[Azure AI Foundry<br/>connected agents]
```
### Live architecture (the submission diagram)
The app ships a **live architecture map** that pings every endpoint on open and color-codes each of
its ~35 parts by *real* status. Here it is showing **10 of 11 services verified live**, agents on `gpt-4o`:

**Three execution tiers, each falling back safely:**
| Tier | What runs | Status |
|---|---|---|
| **Inline agents** ← *running now* | tool-calling loop in the Function — `gpt-4o` via GitHub Models | ✅ **live** in the deployed app |
| **Azure AI Foundry** *(optional)* | Warden/Skeptic/Council as Foundry connected-agents | available via `foundry/setup.mjs` + `FOUNDRY_*` |
| **Scripted** | curated reasoning, no model | always-on safety net (works offline) |
A live run shows **"● live agents · N tools"** and streams the real tool-call trace on screen (model ·
latency · citations). The four function tools — `get_signin_activity`, `get_dependencies`,
`get_oauth_grants`, `get_group_memberships` — are **also exposed over MCP** ([`mcp/`](mcp/)).
---
## 🔬 Technical deep dive
<details>
<summary><b>1 · The multi-agent tool-calling loop</b> (how the agents actually reason)</summary>
<br/>
`POST /api/reason` orchestrates three agents over a synthetic identity store
([`api/reason/index.js`](api/reason/index.js)):
1. **Provider selection** — `provider()` picks the model backend from env: Azure OpenAI →
GitHub Models → OpenAI; returns `null` (→ scripted fallback) if none configured.
2. **Warden agent** — runs `runAgent(WARDEN_SYS, …)`: a bounded **function-calling loop** (max 4 turns).
The model decides which tools to call; the loop executes `runTool(name, record)`, pushes a proper
`{role:'tool', tool_calls_id, content}` message back, and continues until the model answers. Every
tool call is recorded to a `trace` entry `{agent, tool, result}`.
3. **Skeptic agent** — same loop with an **adversarial** system prompt: it's told to hunt the
contradicting signal the Warden may have missed, and is given the Warden's read to contest.
4. **Council agent** — synthesises Warden + Skeptic into a **cited** advisory + a confidence score,
and is explicitly instructed to **never name the verdict** (the human decides).
5. **Foundry IQ grounding** — the council's evidence is enriched by `/api/ground` (Azure AI Search).
6. **Layered fallback** — `Azure AI Foundry (foundry.js) → inline agents → scripted` so it always works.
The browser renders the returned `trace` live in an on-screen panel (agent → tool → snippet, with
model · latency · citation count).
</details>
<details>
<summary><b>2 · API reference</b> (request / response contracts)</summary>
<br/>
**`POST /api/reason`** — run the multi-agent council on one account.
```jsonc
// request
{ "account": "billing", "name": "svc-billing-reconcile" }
// response
{
"configured": true, "agentic": true, "source": "github-models", "model": "gpt-4o",
"warden": "…surface read…", "skeptic": "…contesting read…",
"council": "…cited advisory (no verdict)…", "confidence": 0.78,
"citations": ["Entra sign-in logs", "CMDB", "OAuth consent audit"],
"toolCalls": 4, "latency": 1840,
"trace": [ { "agent": "Warden", "tool": "get_signin_activity", "result": "…" }, … ]
}
```
**`POST /api/reason`** with `{ "probe": true }` — cheap tier check (no agent run):
```jsonc
{ "configured": true, "source": "github-models", "foundry": false, "model": "gpt-4o" }
```
**`GET /api/ground?q=<question>`** — Foundry IQ grounded retrieval over Azure AI Search:
```jsonc
{ "grounded": true, "question": "…", "answers": [ … ],
"citations": [ { "title": "…", "source": "…", "score": 4.41, "snippet": "…" } ] }
// unconfigured → { "grounded": false, "fallback": true }
```
</details>
<details>
<summary><b>3 · The MCP server</b> (5 tools, protocol-validated)</summary>
<br/>
[`mcp/server.js`](mcp/server.js) exposes the identity-governance tools over the **Model Context
Protocol** (StreamableHTTP on `/mcp`, or `--stdio`), so **GitHub Copilot, VS Code, Claude or Foundry**
can drive them. Validate with `npm test` (in-memory protocol client). Tools:
| Tool | Returns |
|---|---|
| `list_accounts` | every account + grade + one-line summary |
| `get_signin_activity` | last interactive / non-interactive sign-in, source-cited |
| `get_dependencies` | what binds to the account + whether each binding is **live** |
| `get_oauth_grants` | delegated / app-only consents and their scope |
| `get_group_memberships` | groups & roles (standing privilege) |
Connect it to GitHub Copilot in ~5 min → [`COPILOT.md`](COPILOT.md).
</details>
<details>
<summary><b>4 · Game systems in depth</b></summary>
<br/>
- **Core loop** — select a room (account) → **Divine** (map dependencies; preliminary council read) →
**Summon** (full agent investigation + Foundry IQ evidence; costs essence) → **Judge**
(Lay to Rest / Bind & Watch / Acknowledge). Judge every soul before **dawn**.
- **The Hungry** — a predator that paths the corridors toward neglected high-risk accounts; reach the
**Vault** (Tier-0) and you lose. Visible on a live mini-map + screen-edge shadow sweeps.
- **Boss kill-chains** — neglected accounts get taken over by **The Token Thief** (stolen session),
**The Consent Daemon** (OAuth grant), **The Hollow** (admin takeover). Multi-stage fights with
**attack telegraphs**, an **attack-technique stage tracker**, a d20, and **control hover-cards**; the right
control is decisive, the wrong one whiffs *with a "why."*
- **Discernment meter** — judging *after* verifying (Summon) raises it (Clear-eyed ≥75 → score ×1.25);
blind calls breed Hubris (≤25 → ×0.8). The human-in-the-loop discipline, scored.
- **Cross-examine** — predict load-bearing vs. safe *before* the AI confirms it; rewards reasoning.
- **Roguelite** — Discernment, **Relics** (lifetime-unlocked starting boons), daily challenge with
modifiers, ranks, badges, combo multiplier, and a run-end training debrief.
- **Boss-gated floors** — Ground → Upper → Attic; a floor's guardian must be confronted to ascend.
- **Difficulty** — Casual / Auditor / Nightmare tune council confidence, summon cost, and the Hungry.
</details>
<details>
<summary><b>5 · The synthetic identity store</b> (data model — no PII)</summary>
<br/>
The store ([`api/reason/index.js`](api/reason/index.js), mirrored in [`mcp/server.js`](mcp/server.js))
is a fabricated directory. Each record:
```jsonc
"svc-billing-reconcile": {
"signin": { "interactive": "412 days ago", "noninteractive": "3 hours ago" },
"dependencies":[ { "label": "nightly AP-Close job", "live": true } ],
"oauthGrants": [ … ],
"groups": [ "Finance-Apps", "…" ],
"source": "Entra sign-in logs · CMDB · OAuth consent audit"
}
```
Accounts span service accounts, admins (incl. break-glass), guests, kiosks and users — each graded
F→A. **No real people, tenants, or credentials.**
</details>
<details>
<summary><b>6 · Themes, art & UX</b></summary>
<br/>
One engine, two `data-theme` skins: **spectral** (haunted manor) and **helpers** (sunny factory).
8 original generated artworks (painted room backdrops + combat arenas, authored via a custom pixel
renderer and AI image tools). Cinematic flow: keyhole-unlock boot → split-world landing (mouse
parallax) → mission briefing → living encounter stage → arena combat → sunrise finale. Accessibility:
`prefers-reduced-motion` support, keyboard focus rings, fine-pointer-only effects, responsive ≤760px.
</details>
---
## 🔎 Microsoft IQ integration → Foundry IQ
✅ **Live and verifiable.** [`api/ground`](api/ground/index.js) performs real, permission-aware,
**cited grounded retrieval over Azure AI Search** (Foundry IQ) against the `afterlogin-knowledge` index.
The game surfaces those citations as the council's *Foundry IQ · cited evidence*, badged
**"● Grounded via Foundry IQ."**
```bash
curl "https://victorious-plant-0c1e7790f.7.azurestaticapps.net/api/ground?q=load-bearing+service+account"
# → {"grounded":true,"citations":[{"title":"Load-bearing service accounts","source":"Identity Governance - lifecycle", ...}]}
```
Reproduce from scratch in ~10 min: [`go-live.ps1`](go-live.ps1) / [`SETUP-IQ.md`](SETUP-IQ.md). It falls
back to baked evidence when unconfigured. *(The in-game "Fabric IQ" label is a thematic nod to data
lineage — the real, active IQ layer is Foundry IQ.)*
---
## 🐙 GitHub Copilot
> *Document your **actual** GitHub Copilot usage here before submitting — and only what's true.*
A concrete, on-spec hook the track explicitly asks for: this repo's **MCP server** exposes the identity
tools so you can **connect it to GitHub Copilot in VS Code / Copilot CLI** and drive the agents' tools
from a Copilot chat. See [`COPILOT.md`](COPILOT.md) for the 5-minute setup — *that* is a real, recordable
GitHub Copilot integration. Also note the Copilot Chat sessions you used while building (debugging,
explanation, generation). **Don't claim usage you didn't do.**
---
## 🎓 What you actually learn
Each boss is a real attack as a **multi-stage kill-chain**; the **right control is decisive, the wrong one
whiffs with a "why"**:
| Attack | ✅ Decisive control | ❌ Common mistake |
|---|---|---|
| **Stolen session token (AiTM)** | Revoke sign-in sessions / CAE | password reset *(doesn't kill a live token)* |
| **Illicit OAuth consent** | Remove the enterprise-app grant | revoke sessions *(leaves the app's access)* |
| **Tier-0 / domain-admin takeover** | Strip standing privilege + rotate secrets | MFA *(won't remove standing access)* |
Plus the governance instincts: don't delete a *load-bearing* service account, verify live bindings before
deprovisioning, and keep a **human in the loop**.
**想? **[打开在线://victorious-plant-0c1e7790f.azurestaticapps.net)**,点击一个世界,按照任务简**在本地运行游戏**(单个文件,零依赖):
python -m http.server 8080 # 然后打开 http8080
```
**运行 MCP 服务器**(验证协议,然后ilot — 参见 [`COPILOT.md`](COPILOT.md)):
```bash
cd mcp && npm install && npm test 协议验证
npm start # HTTP /mcp (或:npm run stdio)
```
**激活实时集成**(Foundry IQ +代理)— 在 `az login` 之后:
```powershell
./.ps1 -Sku basicToken github_pat_xxxxx # Foundry IQ + 实时代理
./go-live.ps1 -Sku # 仅 Foundry IQ
```
---
## ☁️ 部署
托管在 **Azure 静态网页应用 + 管理的 Azure 函数** 上。推送到 `master` → GitHub Actions 构建函数并部署整个应用。
```bash
# 在服务端启用实时代理(仓库中永远)
az staticwebapp appsettings set -n afterlogin -g rg-afterlogin --setting-names GITHUB_MODELS_TOKEN=YOURTOKEN
#URE_OPENAI_ENDPOINT + AZURE_OPENAI_KEY (+ AZURE_DEPLOYMENT) 以在租户内保留推理
```
---
## 📁 项目结构
```
index.html / encounter.html 游戏(单个文件;encounter.html 是开发副本)
api/
reason/ / — 多代理工具调用端点 + foundry.js 层
ground/ /api/ground — Foundry IQ 接地检索(Azure AI 搜索)
mcp/ 身份治理 MCP 服务器(+ 测试,Dockerfile,README/ Azure AI Found代理配置(setup.mjs)+ 运行手册
assets/ · assets/helpers/ 绘制的房间 / 鬼 / 竞技豪宅 + 工厂主题)
go-live.ps1 ·UP-IQ.md 一次性 Foundry IQ + 激活
COPILOT.md 将 MCP 服务器连接到 GitHub Cop VS Code
SUBMISSION.md · PITCH.md 面向评委的总结
CHANGELOG.md 完整的版本历史
```
---
## 🏆 评判标准映射
映射到官方 Agents League 评分标准:
| 标准(权重) | Afterlogin 如何满足 |
|---|---|
| **准确性(20%)** | 代理调用 **真实函数工具**,通过身份存储;委员会发布基于 **Foundry IQ** 检索的 **引用** 建议 — 每个声明都有来源且可检查,绝不幻觉 |
| **推理(20%)** | 真正的 **多代理工具调用循环** — Warden 和 Skeptic 独立调查,**辩论**,委员会综合;实时工具调用轨迹 + `gpt-4o` 延迟在屏幕上显示 |
| **创造力(15%)** | 一个可玩的,电影式的 **安全培训游戏** — 一个引擎,两个世界(哥特式安全运营中心夜晚 ⟷ 帮助工厂)— 其中人类在环路中是 *机制*,而不是免责声明 |
| **用户体验 / 展示(15%)** | 单文件,零依赖应用;电影式 onboarding,专业视图,目标导轨,事后总结和 **实时架构图**,在打开时验证其自己的服务 |
| **可靠性 / 安全性(20%)** | **仅合成数据**(无个人身份信息);委员会 **永远不会** 发出裁决(人类决定);三个执行层具有 **优雅退**(Foundry → 实时代理 → 脚本),始终有效 |
| **社区投票(10%)** | 适用于 *安全运营中心* 专业人员和完全初学者的接近方式 — 相同的引擎,两个界面 — 设计为可共享和可玩 **必需技术检查清单:** ✅ **Microsoft IQ** — 实时 & 引用 · ✅ **Creative Apps 工具 GitHub Copilot 驱动 MCP 服务器([`COPILOT.mdILOT.md))· ✅ 公共仓库 · ✅ (如下)· ✅ 演示视频 ≤ 5 分钟## 🔒 安全与负责任的 AI
- **仅合成数据 — 无真实个人身份信息。** 每个帐户,登录和授权都是虚构的。
- **仓库中没有。** 模型令牌和搜索密钥仅存在于 Azure 应用设置中;`.env*`,密钥和 `.vscode/mcp 被 git 忽略;仓库被机密扫描。
- **诚实的 AI.** 委员会公开其自身的不确定性,绝不虚假裁决;人类做出决定。
- **分层** 意味着应用始终有效,即使离线(脚本层)。
---
## 🛠️ 技术栈
`Azure 静态网页应用` · `Azure 函数 (Node)` · `Azure AI Foundry` (`@azure/ai-agents`) ·
`Azure AI 搜索`(Foundry IQ)· `Azure OpenAI / GitHub 模型`(函数调用)·
**`模型上下文协议`** (`@modelcontextprotocol/sdk`) · `GitHub Copilot`(VS Code)· Web Audio。
前端:单个零依赖 `index.html`(DOM + SVG,无框架)。
---
## 📄 许可证
[MIT](LICENSE) 202 Lynch。所有游戏内均为合成数据;不包含真实个人数据。
<div align="center">
*为 Microsoft Agents League 构建。叙事是一个鬼屋 — 真实的多代理系统。*
**[▶ 玩 Afterlogin](https://victorious-plant-0c1e7790f.urestaticapps.net)**
</div>
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器