Skip to content

Define typed ACP capability and session contracts - #5293

Draft
MdTanwer wants to merge 1 commit into
OpenHands:mainfrom
MdTanwer:feat/4973-typed-acp-contracts
Draft

MdTanwer wants to merge 1 commit into
OpenHands:mainfrom
MdTanwer:feat/4973-typed-acp-contracts

Conversation

@MdTanwer

@MdTanwer MdTanwer commented Sep 24, 2026

Copy link
Copy Markdown

HUMAN:


AGENT:

Why

ACP integration code previously used 23 dynamic attribute calls (getattr, setattr, hasattr) across 4 files (acp_agent.py, acp_models.py, acp_file_credentials.py, acp_tracing.py) to probe objects from external ACP libraries due to protocol version differences (0.8.x RootModel vs 0.10.x union), UNSTABLE extensions (models), error data payloads, credential revisions, and background task slots.

Per #4973 (parent #4905), ACP integration code should express these capabilities and options through explicit typed models or protocols, with compatibility normalization strictly confined to the external-library boundary.

Summary

  • Introduced openhands.sdk.agent.acp_contracts defining typed dataclasses (ACPAuthMethod, ACPConfigSelectOption, ACPSessionModelState, ACPMcpCapabilities, ACPErrorInfo), runtime-checkable protocols, and boundary normalization helpers (extract_model_config_option, extract_session_models, normalize_auth_method, normalize_mcp_capabilities, normalize_acp_error).
  • Refactored acp_agent.py, acp_models.py, acp_file_credentials.py, and acp_tracing.py to use typed direct attribute access, eliminating all 23 dynamic calls and unrolling the background task cleanup loop.
  • Shrank scripts/forbidden_dynamic_attributes_baseline.json by removing all 23 ACP entries (-115 lines, 0 ACP dynamic violations remaining).

Issue Number

Resolves #4973
Parent: #4905

How to Test

Run the forbidden dynamic attribute checker to verify no new or stale violations exist:

python scripts/check_forbidden_dynamic_attributes.py
python scripts/check_forbidden_dynamic_attributes.py --baseline-ref origin/main

Run the unit tests covering the new contracts and boundary normalizers:

uv run pytest tests/sdk/agent/test_acp_contracts.py -v
uv run pytest tests/cross/test_check_forbidden_dynamic_attributes.py -v

Check linting and formatting:

uv run ruff check openhands-sdk/openhands/sdk/agent/acp_contracts.py openhands-sdk/openhands/sdk/agent/acp_agent.py openhands-sdk/openhands/sdk/agent/acp_models.py openhands-sdk/openhands/sdk/agent/acp_file_credentials.py openhands-sdk/openhands/sdk/agent/acp_tracing.py tests/sdk/agent/test_acp_contracts.py scripts/check_forbidden_dynamic_attributes.py
uv run ruff format --check openhands-sdk/openhands/sdk/agent/acp_contracts.py openhands-sdk/openhands/sdk/agent/acp_agent.py openhands-sdk/openhands/sdk/agent/acp_models.py openhands-sdk/openhands/sdk/agent/acp_file_credentials.py openhands-sdk/openhands/sdk/agent/acp_tracing.py tests/sdk/agent/test_acp_contracts.py scripts/check_forbidden_dynamic_attributes.py

Video/Screenshots

Command output evidence:

$ python scripts/check_forbidden_dynamic_attributes.py --baseline-ref origin/main
(exited 0 - baseline contains 0 additions and only shrinks)

$ uvx --with pydantic pytest tests/sdk/agent/test_acp_contracts.py tests/cross/test_check_forbidden_dynamic_attributes.py
======================== 49 passed in 0.65s ========================

Design Doc

Type

  • Bug fix
  • Feature
  • Refactor
  • Breaking change
  • Docs / chore

Notes

  • All 23 ACP entries previously recorded in scripts/forbidden_dynamic_attributes_baseline.json have been eliminated.
  • Made scripts/check_forbidden_dynamic_attributes.py path handling cross-platform (posix normalization and UTF-8 encoding).

@MdTanwer
MdTanwer force-pushed the feat/4973-typed-acp-contracts branch from 4199ab5 to 9abf1ea Compare September 24, 2026 07:13
@MdTanwer MdTanwer changed the title WIP: Add ACP Typed Contracts and Adapters - Resolves #4973 Define typed ACP capability and session contracts Sep 24, 2026
@MdTanwer
MdTanwer force-pushed the feat/4973-typed-acp-contracts branch from 9abf1ea to 2ff7ef3 Compare September 24, 2026 07:14
- Introduce openhands.sdk.agent.acp_contracts with typed dataclasses, protocols, and boundary normalizers
- Replace dynamic attribute probing (getattr, setattr, hasattr) across acp_agent.py, acp_models.py, acp_file_credentials.py, and acp_tracing.py
- Unroll task cleanup loop in ACPAgent to use explicit attribute access
- Shrink forbidden dynamic attributes baseline by eliminating all 23 ACP entries
- Add comprehensive unit tests in test_acp_contracts.py

Resolves OpenHands#4973

Co-authored-by: openhands <openhands@all-hands.dev>
@MdTanwer
MdTanwer force-pushed the feat/4973-typed-acp-contracts branch from 2ff7ef3 to ae6a849 Compare September 24, 2026 07:17
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.

Define typed ACP capability and session contracts

2 participants