-
Notifications
You must be signed in to change notification settings - Fork 0
Establish consistent strategy for mutable containers in frozen Pydantic models #113
Copy link
Copy link
Closed
Labels
prio:mediumShould do, but not blockingShould do, but not blockingscope:smallLess than 1 day of workLess than 1 day of workspec:architectureDESIGN_SPEC Section 15 - Technical ArchitectureDESIGN_SPEC Section 15 - Technical Architecturespec:toolsDESIGN_SPEC Section 11 - Tool & Capability SystemDESIGN_SPEC Section 11 - Tool & Capability Systemtype:researchEvaluate options, make tech decisionsEvaluate options, make tech decisions
Milestone
Description
Problem
Multiple frozen models contain dict[str, Any] fields with documented warnings:
# Note: The ``parameters_schema`` dict is shallowly immutable under the
# frozen model — reassignment is prevented but contents can still be
# mutated. Callers should treat it as read-only.This appears on:
ToolDefinition.parameters_schemaToolCall.argumentsToolExecutionResult.metadata- Various config models
The current approach is inconsistent:
BaseTooldoescopy.deepcopyon property access (expensive, see related issue)ToolInvokerdoesdict(tool_call.arguments)(shallow copy — nested refs still shared)- Most models just document "please don't mutate" and hope for the best
Pydantic's frozen=True is confirmed to be shallow — nested mutable objects can still be mutated in-place.
Options to Evaluate
| Approach | Pros | Cons |
|---|---|---|
| A. Document-only | Zero overhead, honest | No enforcement, bugs possible |
B. MappingProxyType at construction |
O(1), prevents top-level mutation | Shallow — nested dicts still mutable |
| C. Recursive freeze utility | True deep immutability | Complex, perf overhead at construction |
| D. Deep-copy at boundary only | Isolation where it matters | Must identify all boundaries correctly |
Recommendation
Option D — deep-copy only at system boundaries (when passing data to tool execute(), when serializing for persistence), with MappingProxyType for the common read-only access path. This balances safety and performance.
Acceptance Criteria
- Decision documented (ADR or DESIGN_SPEC update)
- Chosen strategy applied consistently across all affected models
- Remove or update all "callers should treat it as read-only" comments
-
ToolInvokerboundary handling aligned with chosen strategy - Tests verify immutability guarantees at boundaries
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
prio:mediumShould do, but not blockingShould do, but not blockingscope:smallLess than 1 day of workLess than 1 day of workspec:architectureDESIGN_SPEC Section 15 - Technical ArchitectureDESIGN_SPEC Section 15 - Technical Architecturespec:toolsDESIGN_SPEC Section 11 - Tool & Capability SystemDESIGN_SPEC Section 11 - Tool & Capability Systemtype:researchEvaluate options, make tech decisionsEvaluate options, make tech decisions