- 3Microsoft principals composed for one employee
An agent identity for each employee
Helix needed an AI that acts in Microsoft 365 as one named employee, with its own identity and no shared super-account. I decided Microsoft would stay the permission authority and my code would compose and check identities. Each digital employee is an agent identity in the tenant under Microsoft Entra Agent ID.
The meeting action server signs certificate client assertions against the employee's agent blueprint and receives that employee's own Microsoft Graph tokens. Calling and attributed actions use separate token kinds, matching what the platform expects for each, and the tokens never reach a model.
I worked out which principal may call, act or be attributed by probing the real tenant and capturing the wire responses, because the platform's behaviour was ahead of its documentation. When outbound calls presented as a separate calling bot, I went with the platform's model; an identity layer that spoofs the caller is worthless. How the principals fit together is in Solving the digital-employee identity.
Provisioning and sign-in
A tenant installer provisions the employee and refuses to finish until its calling contract is sealed, so a half-configured identity never exists in the tenant. In the Teams working service, ownership of delegated work comes from the person's Entra sign-in in a Teams tab.
A tenant-pinned check at the edge
The Auth and access plane had to let Microsoft Copilot Studio reach my private tools without opening the estate, so I put the identity check at the edge. Copilot Studio requests carry Entra-issued tokens, and an edge proxy on Cloudflare Workers checks each RS256 signature with WebCrypto against the tenant's signing keys, cached in the edge key-value store so a round trip to Microsoft stays off every request.
Behind the proxy, the tool gateway accepts tokens from my own authorization server and from Microsoft, each checked against its issuer's published keys. I can build on Microsoft's identity platform past the point where its documentation stops.
I keep credentials out of model context and identity checks at the boundary where requests enter.