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
48 changes: 48 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,54 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
runtime, so installs where npm did not hoist another copy failed with
`MODULE_NOT_FOUND` when loading the exporter.

### Added (`@microsoft/agents-a365-tooling`)

- **Microsoft Defender for AI real-time protection client (opt-in)** -
`DefenderRtpClient.evaluateHookContext` sends an agent-hooks/0.1 context to the Defender
prevention endpoint (`POST .../v1/protection/evaluate`) at the four points Defender evaluates
(`input`, `pre_tool_call`, `post_tool_call`, `output`) and returns its verdict (`deny` and
`transform` block). A copy of the context is fitted to Defender's request validation while it is
read: every string is well formed (a lone surrogate becomes U+FFFD), each content string is
clamped, the copy carries at most four times `A365_DEFENDER_RTP_MAX_CONTENT_CHARACTERS` of content
(the content under decision first, every copied element counting at least one character, and no
list or object scanned beyond what fits), and optional fields of another shape are left out. The
host's context is not modified.
- Calls carry the agent identity's own app-only token for the Defender API
(`api://86a21212-634e-4553-b3d6-e477e4c9d9ec`, role `RealtimeProtection.Evaluate.All`), resolved
by a `DefenderRtpTokenResolver` and cached per agent, tenant and scope;
`DefenderRtpTokenResolvers.fromAgenticConnection` uses the agent's Agents SDK connection, the same
authority as Observability S2S export. The endpoint and the token authority must be `https`, and
neither request follows a redirect.
- Every call sends a unique `x-ms-correlation-id`. One deadline covers the token acquisition and the
request. When no verdict is obtained, the result follows `A365_DEFENDER_RTP_FAIL_MODE` (fail open
by default; a value other than `open` or `closed` is rejected), and a `400` reports the failed
validation rules.
- Content under decision that does not fit (longer than `A365_DEFENDER_RTP_MAX_CONTENT_CHARACTERS`,
or beyond its share of the copy), or whose keys become one once made well formed, is sent incomplete.
At a tool call, the called tool's declaration is copied first, searched for among the first 10000
declarations; it is incomplete too when its description or schema is cut or it lies beyond them.
Defender's block of the copy stands, but its allow does not cover the rest: the result is marked
`truncated` and follows the fail mode, so padded content cannot be authorized unseen.
- `tenant.id` is always the agent's tenant, which Defender requires to match the token's tenant.
- Configured with `ENABLE_A365_DEFENDER_RTP`, `A365_DEFENDER_RTP_ENDPOINT`,
`A365_DEFENDER_RTP_FAIL_MODE`, `A365_DEFENDER_RTP_TIMEOUT_MILLISECONDS` (default 10000),
`A365_DEFENDER_RTP_AUTHENTICATION_SCOPE` and `A365_DEFENDER_RTP_MAX_CONTENT_CHARACTERS`
(default 20000), or the matching `ToolingConfiguration` overrides. `ENABLE_A365_DEFENDER_RTP`
and `A365_DEFENDER_RTP_FAIL_MODE` accept only known values, and
`A365_DEFENDER_RTP_TIMEOUT_MILLISECONDS` and `A365_DEFENDER_RTP_MAX_CONTENT_CHARACTERS` only whole
numbers (`10s` is rejected rather than read as 10 ms), so a typo fails at startup instead of
silently turning protection off or failing open. No new dependency.

### Added (`@microsoft/agents-a365-tooling-extensions-agenthooks`, new, preview)

- **`A365DefenderInterceptor`** - An agent-hooks interceptor (`@responsibleai/agent-hooks`, a peer
dependency, `>=0.1.0-alpha.5 <0.2.0`, tested with the `0.1.0-alpha.5` prerelease; install it
alongside) that sends each emitted context Defender evaluates through
`DefenderRtpClient` and maps the verdict, with a callback for each evaluation;
`createProtectionEmitter` (`enforce`, `parallel/strictest`) and `addA365Defender`. Contexts that
cannot be verified (no verdict, no agent identity, or an allow of truncated content) follow the
fail mode. Requires Node.js 20 or later.

## [1.0.0] - 2026-04-30

### Breaking Changes (`@microsoft/agents-a365-tooling`)
Expand Down
20 changes: 15 additions & 5 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,16 +73,18 @@ cd packages && pnpm pack --workspaces

### Monorepo Structure

This is a pnpm workspace monorepo with 9 packages in `packages/`:
This is a pnpm workspace monorepo with 11 packages in `packages/`:

```
packages/
├── agents-a365-runtime/ # Core utilities (no external deps)
├── agents-a365-observability/ # OpenTelemetry tracing (depends on runtime)
├── agents-a365-observability-hosting/ # Hosting-specific observability
├── agents-a365-observability-extensions-langchain/ # LangChain instrumentation
├── agents-a365-observability-extensions-openai/ # OpenAI instrumentation
├── agents-a365-notifications/ # Agent notification services
├── agents-a365-tooling/ # MCP server configuration
├── agents-a365-tooling/ # MCP server configuration, Defender RTP client
├── agents-a365-tooling-extensions-agenthooks/ # agent-hooks interceptor for Defender RTP
├── agents-a365-tooling-extensions-claude/ # Claude/Anthropic integration
├── agents-a365-tooling-extensions-langchain/ # LangChain integration
└── agents-a365-tooling-extensions-openai/ # OpenAI Agents SDK integration
Expand All @@ -92,7 +94,7 @@ packages/
```
runtime ──► observability ──► observability-hosting ──► observability-extensions-openai
│
└─────────► tooling ──► tooling-extensions-* (claude, langchain, openai)
└─────────► tooling ──► tooling-extensions-* (agenthooks, claude, langchain, openai)
│
└─────────► notifications
```
Expand Down Expand Up @@ -174,6 +176,7 @@ MCP tool server discovery and configuration:
- Prod mode (default): Discovers from Agent365 gateway endpoint
- **`Utility`**: Header composition, token validation, URL construction
- **Interfaces**: `MCPServerConfig`, `McpClientTool`, `ToolOptions`
- **`DefenderRtpClient`**: Microsoft Defender for AI real-time protection (opt-in, `ENABLE_A365_DEFENDER_RTP`). `evaluateHookContext` sends a copy of an agent-hooks/0.1 context, fitted to Defender's request validation, to the Defender prevention endpoint at `input`, `pre_tool_call`, `post_tool_call` and `output`, with the agent identity's app-only token (`DefenderRtpTokenResolvers.fromAgenticConnection`) and a unique `x-ms-correlation-id`, and returns the verdict; failures follow `A365_DEFENDER_RTP_FAIL_MODE`. No agent-hooks dependency: `A365DefenderInterceptor` in `agents-a365-tooling-extensions-agenthooks` drives it from an agent-hooks emitter.

### Notifications (`@microsoft/agents-a365-notifications`)
Extends `AgentApplication` with notification handlers via declaration merging:
Expand All @@ -199,8 +202,8 @@ The keyword "Kairo" is legacy and should not appear in any code. Flag and remove
### Code Standards
- **Unused variables**: Prefix with `_` to avoid ESLint errors (configured in `eslint.config.mjs`)
- **Module format**: This is an ESM project (`"type": "module"` in root `package.json`)
- **Node.js version**: Requires Node.js >= 18.0.0
- **Dependency versions**: Never specify version constraints directly in `package.json` files. All dependency versions must be defined in the `catalog:` section of `pnpm-workspace.yaml` and referenced using `catalog:` in package.json files. This applies to `dependencies`, `devDependencies`, and `peerDependencies`.
- **Node.js version**: Requires Node.js >= 18.0.0 (`agents-a365-tooling-extensions-agenthooks` requires >= 20, like its `@responsibleai/agent-hooks` native core)
- **Dependency versions**: Never specify version constraints directly in `package.json` files. All dependency versions must be defined in the `catalog:` section of `pnpm-workspace.yaml` and referenced using `catalog:` in package.json files. This applies to `dependencies`, `devDependencies`, and `peerDependencies`. A peer dependency range that differs from the pinned version goes in a named catalog under `catalogs:` and is referenced as `catalog:<name>` (for example `catalog:peers`).

## Environment Variables

Expand All @@ -210,6 +213,12 @@ The keyword "Kairo" is legacy and should not appear in any code. Flag and remove
| `CLUSTER_CATEGORY` | Environment classification | `local`, `dev`, `test`, `preprod`, `prod`, `gov`, `high`, `dod`, `mooncake`, `ex`, `rx` |
| `MCP_PLATFORM_ENDPOINT` | MCP platform base URL | URL string |
| `MCP_PLATFORM_AUTHENTICATION_SCOPE` | MCP platform auth scope | Scope string |
| `ENABLE_A365_DEFENDER_RTP` | Enable Defender real-time protection (`DefenderRtpClient`) | `true`, `false` (default); also 1/0, yes/no, on/off; other values are rejected |
| `A365_DEFENDER_RTP_ENDPOINT` | Defender prevention endpoint (required when enabled) | URL string |
| `A365_DEFENDER_RTP_FAIL_MODE` | Behavior when no Defender verdict is obtained | `open` (default), `closed`; other values are rejected |
| `A365_DEFENDER_RTP_TIMEOUT_MILLISECONDS` | Timeout of each Defender evaluation | Number (default: 10000, at most 2147481647) |
| `A365_DEFENDER_RTP_AUTHENTICATION_SCOPE` | Override the Defender API token scope | Scope string |
| `A365_DEFENDER_RTP_MAX_CONTENT_CHARACTERS` | Max characters of each content string sent to Defender; the request carries at most four times as much content | Number (default: 20000) |
| `A365_OBSERVABILITY_SCOPES_OVERRIDE` | Override observability auth scopes | Space-separated scope strings |
| `ENABLE_A365_OBSERVABILITY_EXPORTER` | Enable Agent365 exporter | `true`, `false` (default) |
| `ENABLE_A365_OBSERVABILITY_PER_REQUEST_EXPORT` | Enable per-request export mode | `true`, `false` (default) |
Expand Down Expand Up @@ -263,6 +272,7 @@ npm run version:check
- **Observability Extensions (OpenAI)**: [packages/agents-a365-observability-extensions-openai/docs/design.md](packages/agents-a365-observability-extensions-openai/docs/design.md)
- **Notifications Package**: [packages/agents-a365-notifications/docs/design.md](packages/agents-a365-notifications/docs/design.md)
- **Tooling Package**: [packages/agents-a365-tooling/docs/design.md](packages/agents-a365-tooling/docs/design.md)
- **Tooling Extensions (agent-hooks)**: [packages/agents-a365-tooling-extensions-agenthooks/docs/design.md](packages/agents-a365-tooling-extensions-agenthooks/docs/design.md)
- **Tooling Extensions (Claude)**: [packages/agents-a365-tooling-extensions-claude/docs/design.md](packages/agents-a365-tooling-extensions-claude/docs/design.md)
- **Tooling Extensions (LangChain)**: [packages/agents-a365-tooling-extensions-langchain/docs/design.md](packages/agents-a365-tooling-extensions-langchain/docs/design.md)
- **Tooling Extensions (OpenAI)**: [packages/agents-a365-tooling-extensions-openai/docs/design.md](packages/agents-a365-tooling-extensions-openai/docs/design.md)
Expand Down
4 changes: 4 additions & 0 deletions DEPENDENCIES.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ graph LR
agents_a365_observability_tokencache[agents-a365-observability-tokencache]
agents_a365_runtime[agents-a365-runtime]
agents_a365_tooling[agents-a365-tooling]
agents_a365_tooling_extensions_agenthooks[agents-a365-tooling-extensions-agenthooks]
agents_a365_tooling_extensions_claude[agents-a365-tooling-extensions-claude]
agents_a365_tooling_extensions_langchain[agents-a365-tooling-extensions-langchain]
agents_a365_tooling_extensions_openai[agents-a365-tooling-extensions-openai]
Expand All @@ -20,6 +21,8 @@ graph LR
agents_a365_observability_tokencache --> agents_a365_observability
agents_a365_observability_tokencache --> agents_a365_runtime
agents_a365_tooling --> agents_a365_runtime
agents_a365_tooling_extensions_agenthooks --> agents_a365_runtime
agents_a365_tooling_extensions_agenthooks --> agents_a365_tooling
agents_a365_tooling_extensions_claude --> agents_a365_runtime
agents_a365_tooling_extensions_claude --> agents_a365_tooling
agents_a365_tooling_extensions_langchain --> agents_a365_runtime
Expand All @@ -33,6 +36,7 @@ graph LR
style agents_a365_observability_tokencache fill:#e8f5e9,stroke:#66bb6a,color:#1f3d1f
style agents_a365_runtime fill:#bbdefb,stroke:#1565c0,color:#0d1a26
style agents_a365_tooling fill:#ffe0b2,stroke:#e65100,color:#331a00
style agents_a365_tooling_extensions_agenthooks fill:#fff3e0,stroke:#fb8c00,color:#4d2600
style agents_a365_tooling_extensions_claude fill:#fff3e0,stroke:#fb8c00,color:#4d2600
style agents_a365_tooling_extensions_langchain fill:#fff3e0,stroke:#fb8c00,color:#4d2600
style agents_a365_tooling_extensions_openai fill:#fff3e0,stroke:#fb8c00,color:#4d2600
Expand Down
2 changes: 2 additions & 0 deletions HOW_TO_BUILD.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ nodejs/
│ ├── agents-a365-notifications/ # @microsoft/agents-a365-notifications
│ ├── agents-a365-observability/ # @microsoft/agents-a365-observability
│ ├── agents-a365-tooling/ # @microsoft/agents-a365-tooling
│ ├── agents-a365-tooling-extensions-agenthooks/ # @microsoft/agents-a365-tooling-extensions-agenthooks
│ ├── agents-a365-tooling-extensions-claude/ # @microsoft/agents-a365-tooling-extensions-claude
│ ├── agents-a365-tooling-extensions-langchain/ # @microsoft/agents-a365-tooling-extensions-langchain
│ └── agents-a365-tooling-extensions-openai/ # @microsoft/agents-a365-tooling-extensions-openai
Expand Down Expand Up @@ -75,6 +76,7 @@ After building and packing, you'll find these `.tgz` files in the `nodejs/` dire
- `microsoft-agents-a365-notifications-{version}.tgz`
- `microsoft-agents-a365-observability-{version}.tgz`
- `microsoft-agents-a365-tooling-{version}.tgz`
- `microsoft-agents-a365-tooling-extensions-agenthooks-{version}.tgz`
- `microsoft-agents-a365-tooling-extensions-claude-{version}.tgz`
- `microsoft-agents-a365-tooling-extensions-langchain-{version}.tgz`
- `microsoft-agents-a365-tooling-extensions-openai-{version}.tgz`
Expand Down
1 change: 1 addition & 0 deletions HOW_TO_RELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ All packages in this release:
- @microsoft/agents-a365-runtime@1.1.0
- @microsoft/agents-a365-tooling@1.1.0
- @microsoft/agents-a365-observability@1.1.0
- @microsoft/agents-a365-tooling-extensions-agenthooks@1.1.0
- @microsoft/agents-a365-tooling-extensions-claude@1.1.0
- @microsoft/agents-a365-tooling-extensions-langchain@1.1.0
- @microsoft/agents-a365-tooling-extensions-openai@1.1.0
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ For more detailed build instructions, see the [HOW_TO_BUILD.md](HOW_TO_BUILD.md)
- **packages/agents-a365-observability-extensions-openai**: OpenAI observability extensions
- **packages/agents-a365-runtime**: Microsoft Agent 365 Runtime - Core runtime utilities and extensions
- **packages/agents-a365-tooling**: Microsoft Agent 365 Tooling SDK - Agent tooling and MCP integration
- **packages/agents-a365-tooling-extensions-agenthooks**: agent-hooks interceptor for Microsoft Defender for AI real-time protection
- **packages/agents-a365-tooling-extensions-claude**: Claude/Anthropic tooling extensions
- **packages/agents-a365-tooling-extensions-langchain**: LangChain tooling extensions
- **packages/agents-a365-tooling-extensions-openai**: OpenAI tooling extensions
Expand Down
8 changes: 6 additions & 2 deletions docs/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ Agent365-nodejs/
│ ├── agents-a365-notifications/
│ ├── agents-a365-observability-hosting/
│ ├── agents-a365-observability-extensions-openai/
│ ├── agents-a365-tooling-extensions-agenthooks/
│ ├── agents-a365-tooling-extensions-claude/
│ ├── agents-a365-tooling-extensions-langchain/
│ └── agents-a365-tooling-extensions-openai/
Expand Down Expand Up @@ -185,14 +186,16 @@ Framework-specific instrumentations that integrate with the observability core:

> **Detailed documentation**: [packages/agents-a365-tooling/docs/design.md](../packages/agents-a365-tooling/docs/design.md)

MCP (Model Context Protocol) tool server configuration and discovery.
MCP (Model Context Protocol) tool server configuration and discovery, and the Microsoft Defender for AI real-time protection client.

**Key Classes:**

| Class | Purpose |
|-------|---------|
| `McpToolServerConfigurationService` | Discover and configure MCP tool servers |
| `Utility` | Header composition, token validation, URL construction |
| `DefenderRtpClient` | Send agent-hooks contexts to the Defender prevention endpoint and return its verdict (opt-in, `ENABLE_A365_DEFENDER_RTP`) |
| `DefenderRtpTokenResolvers` | The agent identity's app-only Defender token from an Agents SDK connection |

**Interfaces:**

Expand Down Expand Up @@ -240,10 +243,11 @@ for (const server of servers) {

### 5. Tooling Extensions

Framework-specific adapters for MCP tool integration:
Framework-specific adapters for MCP tool integration, and the agent-hooks adapter for real-time protection:

| Package | Purpose | Design Doc |
|---------|---------|------------|
| `tooling-extensions-agenthooks` | agent-hooks interceptor for Microsoft Defender for AI real-time protection | [design.md](../packages/agents-a365-tooling-extensions-agenthooks/docs/design.md) |
| `tooling-extensions-claude` | Claude SDK integration | [design.md](../packages/agents-a365-tooling-extensions-claude/docs/design.md) |
| `tooling-extensions-langchain` | LangChain integration | [design.md](../packages/agents-a365-tooling-extensions-langchain/docs/design.md) |
| `tooling-extensions-openai` | OpenAI Agents SDK integration | [design.md](../packages/agents-a365-tooling-extensions-openai/docs/design.md) |
Expand Down
1 change: 1 addition & 0 deletions generate-package-dependencies.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const packageToType = {
'agents-a365-observability-tokencache': 'Observability Extensions',
'agents-a365-runtime': 'Runtime',
'agents-a365-tooling': 'Tooling',
'agents-a365-tooling-extensions-agenthooks': 'Tooling Extensions',
'agents-a365-tooling-extensions-claude': 'Tooling Extensions',
'agents-a365-tooling-extensions-langchain': 'Tooling Extensions',
'agents-a365-tooling-extensions-openai': 'Tooling Extensions'
Expand Down
Loading
Loading