Skip to content
Merged
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
26 changes: 26 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [6.8.0] - 2026-04-25 — Plugin Batch 1 / ADR-043 explainability fields on MCP responses

Minor release. Surfaces fields the AxonFlow agent has emitted since v7.1.0 (Plugin Batch 1 / ADR-042 / ADR-043) but the SDK didn't declare. Pure Cat B field-additions on existing methods — no new SDK methods, no breaking changes. Documented in OpenAPI via platform v7.4.3 (axonflow-enterprise#1714); SDK catches up here.

Coordinated cycle: TypeScript v6.1.0 / Go v5.8.0 / Java v6.1.0 ship same day with the same field set.

### Added

- **`MCPCheckInputResponse`** gains 5 optional Plugin Batch 1 fields:
- `decision_id: str | None` — audit correlator
- `risk_level: Literal["low", "medium", "high", "critical"] | None`
- `policy_matches: list[ExplainPolicy] | None` — per-policy explainability records
- `override_available: bool | None` — whether session override is permitted for the matched policies
- `override_existing_id: str | None` — already-active override consumed by this decision (if any)
- **`MCPCheckOutputResponse`** gains 3 optional fields:
- `decision_id`
- `policy_matches: list[ExplainPolicy] | None`
- `redacted_message: str | None` — text-redaction counterpart to `redacted_data` (used when the connector returned a string message rather than tabular rows; e.g. execute-style responses)
- **`ExplainPolicy`** is now re-exported from `axonflow.types` (it was previously only in `axonflow.decisions`). Same Pydantic model — Python's snake_case convention naturally aligns wire-shape and SDK types, so no separate model is needed.

All fields default to `None`. Pre-v7.1.0 platforms return `None` for every field; callers should treat absence as "context not available" rather than an error.

### Deferred

`client.explain_decision(decision_id)` and the full `ExplainRule` / `DecisionExplanation` type surface are tracked separately as feature work — see axonflow-enterprise#1716. This release ships only field-surfacing on existing methods.

## [6.7.0] - 2026-04-25 — Wire-shape canonicalization

Minor release. Purely additive — new fields default to `None`, deprecated aliases preserved for compile-time compat. Coordinated with TypeScript v6.0.0 / Java v6.0.0 / Go v5.7.0 SDK releases. The wire-shape contract gate's pinned OpenAPI spec SHA bumps with the platform v7.4.2 spec corrections; one baseline drift entry (`DynamicPolicyInfo`) auto-resolves.
Expand Down
2 changes: 2 additions & 0 deletions axonflow/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@
ExecutionSnapshot,
ExecutionSummary,
ExfiltrationCheckInfo,
ExplainPolicy,
# Policy Simulation types (Evaluation Tier+)
ImpactReportInput,
ImpactReportRequest,
Expand Down Expand Up @@ -297,6 +298,7 @@
"ConnectorHealthStatus",
"ConnectorPolicyInfo",
# MCP Policy Check types
"ExplainPolicy",
"MCPCheckInputRequest",
"MCPCheckInputResponse",
"MCPCheckOutputRequest",
Expand Down
2 changes: 1 addition & 1 deletion axonflow/_version.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
"""Single source of truth for the AxonFlow SDK version."""

__version__ = "6.7.0"
__version__ = "6.8.0"
26 changes: 26 additions & 0 deletions axonflow/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@

from pydantic import BaseModel, ConfigDict, Field, field_validator

# Re-export for use on MCP response types — same logical record per ADR-043.
# `as ExplainPolicy` is the explicit-re-export idiom (mypy-friendly).
from axonflow.decisions import ExplainPolicy as ExplainPolicy # noqa: PLC0414, TC001


class Mode(str, Enum):
"""SDK operation mode."""
Expand Down Expand Up @@ -410,6 +414,16 @@ class MCPCheckInputResponse(BaseModel):
block_reason: str | None = Field(default=None)
policies_evaluated: int = Field(default=0, ge=0)
policy_info: ConnectorPolicyInfo | None = Field(default=None)
# Plugin Batch 1 / ADR-042 / ADR-043 — richer governance context surfaced
# when the platform is v7.1.0+. All fields default to None on older
# platforms; callers should treat absence as "context not available"
# rather than an error. Source of truth:
# platform/agent/mcp_server_handler.go:880-940.
decision_id: str | None = Field(default=None)
risk_level: Literal["low", "medium", "high", "critical"] | None = Field(default=None)
policy_matches: list[ExplainPolicy] | None = Field(default=None)
override_available: bool | None = Field(default=None)
override_existing_id: str | None = Field(default=None)


class MCPCheckOutputRequest(BaseModel):
Expand All @@ -433,10 +447,22 @@ class MCPCheckOutputResponse(BaseModel):

allowed: bool
block_reason: str | None = Field(default=None)
# Tabular response data with PII fields masked (used when the connector
# returned rows; e.g. SQL/CSV results). None if no redaction needed or
# if the response was a text message.
redacted_data: Any | None = Field(default=None)
# Text message with PII fields masked (used when the connector returned
# a string message rather than tabular rows; e.g. execute-style
# responses). None if no redaction needed or if the response was tabular.
# Source of truth: platform/agent/mcp_server_handler.go:988.
redacted_message: str | None = Field(default=None)
policies_evaluated: int = Field(default=0, ge=0)
exfiltration_info: ExfiltrationCheckInfo | None = Field(default=None)
policy_info: ConnectorPolicyInfo | None = Field(default=None)
# Plugin Batch 1 / ADR-043 — explainability context (matches the
# MCPCheckInputResponse fields on the same call site).
decision_id: str | None = Field(default=None)
policy_matches: list[ExplainPolicy] | None = Field(default=None)


class PlanStep(BaseModel):
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "axonflow"
version = "6.7.0"
version = "6.8.0"
description = "AxonFlow Python SDK - Enterprise AI Governance in 3 Lines of Code"
readme = "README.md"
license = {text = "MIT"}
Expand Down
23 changes: 22 additions & 1 deletion tests/fixtures/wire_shape_baseline.json
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@
]
}
},
"openapi_specs_sha": "10d44eb4585a7b5321d7286b354ff8b43b8c6a57",
"openapi_specs_sha": "8c8d6c9c506aa25fcd8a887f6fc71f71b5d6bc30",
"per_model_drift": {
"AuditLogEntry": {
"sdk_only": [
Expand Down Expand Up @@ -275,6 +275,24 @@
],
"spec_only": []
},
"MCPCheckInputResponse": {
"sdk_only": [],
"spec_only": [
"decision_id",
"override_available",
"override_existing_id",
"policy_matches",
"risk_level"
]
},
"MCPCheckOutputResponse": {
"sdk_only": [],
"spec_only": [
"decision_id",
"policy_matches",
"redacted_message"
]
},
"MarkStepCompletedRequest": {
"sdk_only": [
"metadata"
Expand Down Expand Up @@ -398,12 +416,15 @@
"CreateStaticPolicyRequest",
"CreateWorkflowRequest",
"CreateWorkflowResponse",
"DecisionExplanation",
"DynamicPolicy",
"DynamicPolicyInfo",
"DynamicPolicyMatch",
"ExecutionSnapshot",
"ExecutionSummary",
"ExfiltrationCheckInfo",
"ExplainPolicy",
"ExplainRule",
"ListWorkflowsResponse",
"MCPCheckInputRequest",
"MCPCheckInputResponse",
Expand Down
Loading