# Architecture

This package exists to keep agent-core platform-neutral while still allowing an
M365-hosted agent to receive Microsoft Agent 365 tools for the current turn.

## Layer Split

| Layer                              | Owns                                                                                                                       | Does not own                                                      |
| ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- |
| `@cuylabs/agent-core`              | Agent runtime, model loop, tool execution, MCP client lifecycle, `capabilityProviders`                                     | Microsoft channel objects, Azure auth, Agent 365 discovery        |
| `@cuylabs/channel-m365-agent-core` | M365 Activity/CloudAdapter ingress and ambient `TurnContext` binding                                                       | Agent 365 MCP discovery or MCP client connection                  |
| `@microsoft/agents-a365-tooling`   | Agent 365 tooling discovery, `ToolingManifest.json` dev mode, gateway calls, token exchange, per-server auth headers       | agent-core tool registration or model-loop lifecycle              |
| `@cuylabs/agent-a365-tooling`      | Glue that resolves Agent 365 MCP servers for the current turn and exposes them as agent-core capability-provided MCP tools | Chat transport, model provider, long-lived pooling, token refresh |

The important boundary is that agent-core never imports Microsoft hosting
types. Microsoft-specific request state stays in the channel and adapter
packages.

## Turn Flow

At runtime, one user message flows like this:

1. M365 channel receives an Activity.
2. `@cuylabs/channel-m365-agent-core` binds the active Microsoft `TurnContext` in
   AsyncLocalStorage.
3. The host calls `agent.chat()` through the M365 adapter.
4. agent-core starts the chat turn.
5. agent-core calls this package's `AgentCapabilityProvider`.
6. This package reads the active `TurnContext`.
7. This package calls Microsoft's `McpToolServerConfigurationService`.
8. Microsoft's SDK resolves Agent 365 MCP server configs from either:
   `ToolingManifest.json` in development, or the Agent 365 tooling gateway in
   production.
9. This package optionally applies `filterServers`.
10. This package connects the MCP servers through agent-core's MCP manager.
11. agent-core exposes the resulting MCP tools to the model for this turn.
12. After the turn, agent-core runs cleanup and closes the per-turn MCP
    manager.

## Why Not Put This In Agent-Core?

Agent 365 tooling has Microsoft-specific inputs:

- Microsoft `TurnContext`
- Microsoft Agents SDK `Authorization`
- `authHandlerName`
- OBO token exchange behavior
- Agent 365 MCP server metadata

Putting those concepts in agent-core would make core platform-specific. The
adapter package keeps that boundary clean.

## Why Not Create A Generic Tooling Discovery Package?

This package intentionally does not extract a generic discovery abstraction
yet. The A365 path is specific to Microsoft turn state and token exchange. A
future Salesforce, Slack, or internal platform discovery adapter may need a
different shape.

The rule for now is simple: wait for a second real adapter before extracting a
shared abstraction.
