Co-authored-by: strandly-the-agent <strandly-the-agent@users.noreply.github.com>
3.8 KiB
Compatibility Policy
This document outlines the Strands SDK's policy on changes that are not considered breaking changes under semantic versioning. The policy applies to both the TypeScript and Python SDKs (strands-py, strands-ts); Strands harness and the Strands CLI are 0.x and follow their own rule. Understanding these policies helps you anticipate how the SDK may evolve without requiring major version bumps.
Field to Property Conversion
Converting a public mutable field to a property with accessor logic is not considered a breaking change, even when adding validation or side effects.
Policy
The SDK may convert public mutable fields to properties in minor or patch releases. This includes adding:
- Validation logic that throws errors for invalid values
- Side effects during assignment (logging, notifications, state updates)
- Computed or transformed values when reading the property
Rationale
In both TypeScript/JavaScript and Python, property accessors are syntactically and behaviorally identical to direct field access from the consumer's perspective. Consumers cannot distinguish between direct field access and property access at the call site, so the implementation change is transparent to user code.
Example
The agent's model attribute is currently a public mutable field. In a future release, it may gain accessor logic to add validation:
// TypeScript — before: direct field access
agent.model = newModel
const currentModel = agent.model
// After: getter/setter with validation (identical usage)
private _model: Model<BaseModelConfig>
public get model(): Model<BaseModelConfig> {
return this._model
}
public set model(value: Model<BaseModelConfig>) {
if (!value) {
throw new Error('Model cannot be null or undefined')
}
this._model = value
}
# Python — before: direct attribute access
agent.model = new_model
current_model = agent.model
# After: property with validation (identical usage)
@property
def model(self) -> Model:
return self._model
@model.setter
def model(self, value: Model) -> None:
if value is None:
raise ValueError("Model cannot be None")
self._model = value
User code remains unchanged and continues to work as before.
Union Type Extensions
Adding new types or classes to union types is not considered a breaking change, unless the union explicitly declares that it will no longer change.
Policy
The SDK may add new event types, result variants, or other union members in minor or patch releases. This includes:
- New event types in streaming results
- Additional error types in result unions
- New configuration options in config unions
- Extended enum-like union types
Rationale
Union type extensions are additive changes that don't break existing code. Consumers handle union types through type guards, switch statements, or pattern matching that focus on known variants. New union members are simply ignored by existing logic.
Example
The stream event type returned by the agent's streaming API may receive new event types:
// TypeScript — current usage continues to work
for await (const event of agent.stream('Hello')) {
if (event.type === 'textDelta') {
console.log(event.text)
}
// New event types are ignored by existing code
}
# Python — current usage continues to work
async for event in agent.stream_async("Hello"):
if "data" in event:
print(event["data"])
# New event types are ignored by existing code
New event types added to the union don't affect existing event handling logic.
Feedback
If you have questions or concerns about this compatibility policy, please open an issue on GitHub.