Skip to content

fix(schema): coerce string protocolVersion in InitializeRequest#92

Open
WeeeeeKdY wants to merge 1 commit intoagentclientprotocol:mainfrom
WeeeeeKdY:fix/protocol-version-string-coercion
Open

fix(schema): coerce string protocolVersion in InitializeRequest#92
WeeeeeKdY wants to merge 1 commit intoagentclientprotocol:mainfrom
WeeeeeKdY:fix/protocol-version-string-coercion

Conversation

@WeeeeeKdY
Copy link
Copy Markdown

Problem

Some ACP clients send a date string like "2024-11-05" as protocolVersion instead of an integer. Zed is a known example — its agent_servers implementation can emit the MCP-style date format during the ACP handshake.

The current Python SDK rejects this outright with a pydantic validation error, causing the agent process to crash immediately after the client connects:

acp.exceptions.RequestError: Invalid params
  protocol_version: Input should be a valid integer, unable to parse string as an integer

Root cause

The Rust SDK (agent-client-protocol-schema) already handles this gracefully with an explicit comment in the source:

fn visit_str<E>(self, _value: &str) -> Result<Self::Value, E> {
    // Old versions used strings, we consider all of those version 0
    Ok(ProtocolVersion::V0)
}

The Python SDK's generated schema.py uses a strict pydantic int type with no equivalent fallback.

Fix

  • Add a field_validator("protocol_version", mode="before") to InitializeRequest in src/acp/schema.py that coerces non-integer values to 1 (current stable version), mirroring the Rust SDK's lenient behaviour. Strings that look like integers (e.g. "1") are parsed normally; arbitrary strings (e.g. "2024-11-05") fall back to 1.
  • Add a CLASS_VALIDATOR_INJECTIONS table and _inject_field_validators post-processing step to scripts/gen_schema.py so the validator is automatically re-injected on future schema regenerations.
  • Add _ensure_pydantic_import helper to add field_validator to the generated pydantic import line when needed.

References

Some ACP clients (notably Zed) send a date string like "2024-11-05" as
the protocolVersion instead of an integer.  The Rust SDK already handles
this gracefully — its Deserialize impl maps any string to V0 with the
comment "Old versions used strings".  The Python SDK rejected strings
outright, causing the agent process to crash on the very first handshake.

Changes:
- Add `_coerce_protocol_version` field_validator to `InitializeRequest`
  in `src/acp/schema.py` that maps non-integer values to 1 (current
  stable version), mirroring the Rust SDK's lenient behaviour.
- Add `CLASS_VALIDATOR_INJECTIONS` table and `_inject_field_validators`
  post-processing step to `scripts/gen_schema.py` so the validator is
  re-applied automatically on future schema regenerations.
- Add `_ensure_pydantic_import` helper used by the injection step to
  add `field_validator` to the generated pydantic import line.

Ref: https://github.com/agentclientprotocol/rust-sdk/blob/main/crates/agent-client-protocol-schema/src/version.rs
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