Skip to content

Quickstart

Source: https://github.com/brandwe/entrabot-identity-research

Prerequisites

  • Python 3.12+ on PATH
  • Azure CLI (az) logged in with admin access to your Entra tenant (Application Administrator or higher)
  • gh (GitHub CLI) — optional, used by some helper scripts
  • Git
  • An M365 license available for the Agent User (E3/E5/Teams Enterprise — anything that grants a Teams seat)
  • macOS, Linux, or Windows 10 21H2+/11. Windows uses scripts/setup-windows.ps1 (PowerShell 7+); see docs/runbooks/windows-setup.md.

One-Command Setup (macOS/Linux)

git clone https://github.com/brandwe/entrabot-identity-research.git
cd entrabot-identity-research
./scripts/setup.sh

This will: 1. Create a dedicated provisioner app registration (avoids Azure CLI token rejection — Learning #1) 2. Create an Agent Identity Blueprint + BlueprintPrincipal (separate steps — Learning #2) 3. Create an Agent Identity (per-device service principal) 4. Create an Agent User (Entra user account linked to the Agent Identity) 5. Grant consent for Teams/Chat Graph permissions 6. Generate a self-signed certificate, upload public key to Entra, store private key in the OS keystore (Keychain / TPM / Keyring — ADR-003) 7. Install Python dependencies and write .env (no secrets — only the cert thumbprint)

The script is idempotent — safe to re-run. State is persisted in .entrabot-state.json.

Optional flags

  • --use-cloud-memory — opt in to Azure Blob Storage for operational data (interaction log, daily summaries, watched chats, email cursor). Default is local-only.
  • --keep-memory-local — explicit form of the default. Accepted for backwards compatibility.

See docs/reference/setup-script.md for the full flag list, and docs/guides/storage-configuration.md for the local-vs-cloud trade-offs.

After Setup

  1. Assign an M365 license to the Agent User in the Entra admin center (E3/E5/Teams Enterprise).
  2. Wait 10–15 minutes for Teams/mailbox provisioning. The Agent User won't be reachable in Teams until this completes — there is no faster path.
  3. Run tests:
source .venv/bin/activate
pytest -v --cov=entrabot --cov-report=term-missing

Launching the Agent

The repo isn't published to npm or pypi — your host CLI loads the local stdio MCP server from .mcp.json in the current directory. No flag is needed for that part; MCP servers in .mcp.json are auto-discovered. What differs between hosts is how inbound Teams DMs reach the agent.

Channel push: inbound Teams messages and emails arrive as next-turn system reminders without a tool call. Requires the dev-channel allowlist flag:

claude --dangerously-load-development-channels server:entrabot

The double-dash matters. Single-dash silently treats server:entrabot as prompt text — see Learning #44 in docs/runbooks/hard-won-learnings.md. server:entrabot is the MCP server name from .mcp.json, not a publication identifier — the value matches the key inside the mcpServers object in .mcp.json.

GitHub Copilot CLI, Codex, Cursor, and other non-Claude hosts

MCP tools work, but there is no notifications/claude/channel equivalent — channel push is silently absent. Inbound Teams messages instead arrive inline as a sponsor_reply field on send_teams_message, which auto-blocks until the sponsor replies. This is host-detected on the server side; no flag, no parameter:

copilot   # or: codex, cursor, etc. — no flag, just launch from the repo dir

While the agent is blocked waiting on a Teams reply (any host that calls wait_for_sponsor_dm explicitly, or the auto-wait inside send_teams_message on non-Claude hosts), the host CLI shows a heartbeat animation so you know it is listening to Teams, not your keyboard:

           __
      (___()'`;  woof! 🐕
      /,    /`
      \"--\

(•ᴗ•) zZz... listening for Teams DM [42s] (Ctrl+C to break)

Frames cycle every ~30s with an elapsed-time counter:

  • (•ᴗ•) zZz... listening for Teams DM
  • (•ᴗ•)╯ checking inbox
  • ʕ•ᴥ•ʔ waiting on sponsor
  • (´・ω・) sponsor hasn't replied yet`
  • (╯°□°)╯ Teams DM = next turn
  • (◕‿◕) still here, still waiting

Ctrl+C breaks out cleanly. Full host-by-host protocol is in docs/claude-copilot-cli-channel-port.md and prompts/anatomy/channel-discipline.md.

Common Pitfalls

  • Teams provisioning latency. The 10–15 min wait is real. If create_chat 404s, give it another five minutes before debugging.
  • az CLI tokens hard-403 against Agent Identity APIs. Don't az rest against the agent-identity beta — the dedicated provisioner app exists for that reason. Learning #1.
  • pip install -e . inside a worktree silently re-points the parent venv. If you run sub-agents in git worktrees, give them a worktree-local venv. Learning #36.
  • Stderr must stay visible. Don't 2>/dev/null setup scripts — failures become invisible. Learning #6.

Without an Entra Tenant

If you just want to run the code and tests locally:

python3.12 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
pytest -v

All Graph API calls are mocked in tests — no tenant needed.

Teardown

./scripts/teardown.sh

Removes the Agent User, Agent Identity, Blueprint, Provisioner app, and local state.

Next Steps