Skip to content

[AAASM-1560] ✨ (sdk): Add enforcement_mode parameter to init_assembly#59

Merged
Chisanan232 merged 3 commits into
masterfrom
v0.0.1/AAASM-1560/feat/enforcement_mode
May 23, 2026
Merged

[AAASM-1560] ✨ (sdk): Add enforcement_mode parameter to init_assembly#59
Chisanan232 merged 3 commits into
masterfrom
v0.0.1/AAASM-1560/feat/enforcement_mode

Conversation

@Chisanan232
Copy link
Copy Markdown
Contributor

@Chisanan232 Chisanan232 commented May 23, 2026

Description

Per-agent governance posture override on the Python SDK side. Library users can now opt into observe mode (the gateway-side primitives landed in agent-assembly via #729 / #749) directly from init_assembly():

from agent_assembly import init_assembly

ctx = init_assembly(
    gateway_url="http://localhost:8080",
    api_key="...",
    agent_id="experimental-agent",
    enforcement_mode="observe",   # NEW
)
# Every action proceeds; the gateway records would-be violations as shadow audit events.

Shipped

Item Location
EnforcementMode = Literal["enforce", "observe", "disabled"] type alias agent_assembly/core/assembly.py
init_assembly(..., enforcement_mode="enforce") keyword-only parameter Same file
_validate_inputs rejects unknown strings with ConfigurationError Same file
`GatewayClient(..., enforcement_mode: str None = None)` constructor param
register_agent includes enforcement_mode in the POST body when set; omits when None Same file
5 new tests covering valid / invalid / default / on-the-wire-when-set / off-the-wire-when-None test/unit/test_assembly.py + test/unit/client/test_gateway_topology.py

Type of Change

  • ✨ New feature

Breaking Changes

  • No

The init_assembly parameter is keyword-only with a default of "enforce", so every existing caller is unaffected. The GatewayClient parameter defaults to None, which omits the field from the registration body entirely — a pre-feature python-sdk client talking to a pre-feature gateway sees the same wire shape as before. The gateway's REST → gRPC bridge maps the snake_case string onto RegisterRequest.enforcement_mode (proto enum) per AAASM-1555.

Related Issues

  • Related Jira ticket: AAASM-1560 (Story AAASM-1553)
  • Depends on (already merged): AAASM-1555 (proto field), AAASM-1557 (gateway registry storage), AAASM-1564 (gateway service-layer wiring)

What's in here

2 commits:

  1. ✨ Add enforcement_mode parameter to init_assembly and GatewayClient (type alias + validation + threading through to the registration body)
  2. ✅ Five unit tests (parametrize over enforce/observe/disabled, invalid-rejection, default-is-enforce, body-carries-when-set, body-omits-when-None)

Testing

.venv/bin/python -m pytest test/unit/       # 359 passed, 1 skipped (the skipped is an
                                            # unrelated native-binding wire-roundtrip
                                            # that needs `maturin develop` — pre-existing)

AC checklist

  • init_assembly(enforcement_mode="observe") passes enforcement_mode: OBSERVE in RegisterAgent RPC (test_register_agent_sends_enforcement_mode_when_set — snake_case string on the wire, the gateway REST→gRPC bridge maps it to the proto enum)
  • Default (enforcement_mode="enforce") is backward-compatible with all existing tests (the existing 354 tests in the suite pass without any modification)
  • enforcement_mode is documented in the public API docstring (rstdoc on both init_assembly and the EnforcementMode alias itself)
  • mypy type-checks clean with the new Literal annotation (9 pre-existing unrelated mypy errors on master remain, no new ones introduced — confirmed by running mypy on both branches)
  • Unit tests added for valid values and invalid value error path (5 tests covering all branches)

Checklist

  • Code follows project style guidelines (ruff format, ruff check)
  • Self-review of the diff completed
  • Documentation updated if behaviour changed (rstdoc on new symbols)
  • All CI checks passing
  • Commits are small and follow the Gitmoji convention

…lient

Operator surface for the per-agent observe-mode override the gateway
landed in AAASM-1557 + AAASM-1564.

* New EnforcementMode = Literal["enforce", "observe", "disabled"] alias
  in agent_assembly/core/assembly.py mirroring the snake_case wire tokens
  the gateway's REST endpoint expects.
* init_assembly() takes a new keyword-only enforcement_mode parameter,
  defaults to "enforce" so every existing caller is unaffected.
* _validate_inputs rejects unknown strings with a clear ConfigurationError
  message so a typo at init time fails fast instead of silently registering
  under live enforcement.
* GatewayClient gains enforcement_mode: str | None (default None) — the
  register_agent body only carries the field when set, so a pre-feature
  client talking to a pre-feature gateway sees the same wire shape as
  before. The gateway's REST -> gRPC bridge maps the string onto
  RegisterRequest.enforcement_mode (proto enum) per AAASM-1555.

Refs: AAASM-1560
Five new tests covering the AAASM-1560 AC:

* parametrized over enforce / observe / disabled — all three valid
  values land on the GatewayClient
* invalid string raises ConfigurationError with a clear message
* omitting enforcement_mode defaults to 'enforce'
* register_agent body carries enforcement_mode when set
* register_agent body omits the key when client was constructed
  without enforcement_mode — preserves the wire shape for a legacy
  gateway that doesn't know about the field

Refs: AAASM-1560
…ire shape

Fixes integration test test_register_agent_no_topology_omits_body which
expected the registration body to be empty when no topology / no
enforcement_mode is set.

The original implementation defaulted init_assembly's enforcement_mode
to "enforce", which then flowed into the GatewayClient and got written
to the registration body — breaking the contract that a pre-feature
SDK call produces a pre-feature wire shape.

Fix: default to None at the init_assembly level too (matching the
GatewayClient default). When None, the field is omitted from the body
and the gateway applies its server-side default (live enforce), so
semantic behaviour is unchanged. Explicit posture ("enforce" /
"observe" / "disabled") still serialises on the wire.

The validation branch also accepts None now, and the corresponding
default-value test is renamed/updated to assert client.enforcement_mode
is None when omitted.

Refs: AAASM-1560
@codecov
Copy link
Copy Markdown

codecov Bot commented May 23, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@sonarqubecloud
Copy link
Copy Markdown

@Chisanan232 Chisanan232 merged commit b2c232d into master May 23, 2026
24 checks passed
@Chisanan232 Chisanan232 deleted the v0.0.1/AAASM-1560/feat/enforcement_mode branch May 23, 2026 09:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant