Skip to content

Conversation

@westey-m
Copy link
Contributor

@westey-m westey-m commented Jan 2, 2026

Motivation and Context

There are some drawbacks to the current serialization mechanism used for AgentThread instances, so creating an ADR to consider some alternatives and their implications.

#303

Description

Contribution Checklist

  • The code builds clean without any errors or warnings
  • The PR follows the Contribution Guidelines
  • All unit tests pass, and I have added new tests where possible
  • Is this a breaking change? If yes, add "[BREAKING]" prefix to the title of the PR.

Copilot AI review requested due to automatic review settings January 2, 2026 11:21
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces an Architecture Decision Record (ADR) that evaluates alternative approaches to serializing and deserializing AgentThread instances. The ADR identifies drawbacks with the current custom Serialize/Deserialize methods and proposes solutions that would enable standard serialization mechanisms like JsonSerializer.

Key Changes

  • Proposes three options for AgentThread serialization: separating state from behavior with lazy reattachment, separating state from behavior completely, or maintaining the current approach
  • Documents the tradeoffs between supporting custom behaviors and enabling standard serialization
  • Outlines required changes to ChatMessageStore and related infrastructure to support state-based serialization

Comment on lines +115 to +117

### Option 3: Keep the current approach of custom Serialize/Deserialize methods

Copy link

Copilot AI Jan 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ADR is missing analysis of pros and cons for each option. According to the ADR template and conventions from other ADRs (like 0006-userapproval.md), each option should include a discussion of its advantages and disadvantages to help readers understand the tradeoffs.

Suggested change
### Option 3: Keep the current approach of custom Serialize/Deserialize methods
**Pros**
- Simplifies serialization because `AgentThread` contains only serializable state, without needing to persist behavior instances directly.
- Clearly separates concerns between persisted state (on `AgentThread`) and runtime behavior (constructed by the agent), which can make versioning of state easier.
- Avoids having to serialize behavior-specific implementation details or dependencies.
**Cons**
- Behaviors are no longer accessible directly from `AgentThread` (e.g., via `AgentThread.GetService<TBehavior>()`), which may break some existing usage patterns.
- The agent may need to construct multiple behavior instances over the lifetime of a single thread, potentially leading to additional allocations and lifecycle complexity.
- Introducing APIs such as `AIAgent.GetBehavior<TBehavior>(AgentThread thread)` increases coupling to the agent and may make behavior access patterns less intuitive.
### Option 3: Keep the current approach of custom Serialize/Deserialize methods
In this option we keep the existing model where `AgentThread` exposes a `Serialize` method and deserialization is handled via a custom `Deserialize` method on the `AIAgent`. No structural changes are made to how state and behavior are modeled today.
**Pros**
- Requires no migration effort for existing users and avoids breaking changes in public APIs.
- Keeps the current behavior semantics exactly as they are, which may be preferable while other parts of the system are evolving.
- Avoids introducing new abstractions or factory patterns, reducing the amount of refactoring needed in the short term.
**Cons**
- Continues to rely on custom `Serialize`/`Deserialize` implementations, which can be error-prone and lead to duplicated logic across agents and threads.
- Makes it harder to evolve the serialization format and versioning strategy, since behavior and state are tightly coupled to the current implementation.
- Keeps the conceptual model different from other components that rely on explicit state objects and factories, which can reduce consistency and discoverability for users.

Copilot uses AI. Check for mistakes.

- Option 1: Separate state from behavior, serialize state only and re-attach behavior on first usage
- Option 2: Separate state from behavior, and only have state on AgentThread
- Option 3: Keep the current approach of custom Serialize/Deserialize methods
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can Options 1 and 3 coexist? If so, we can keep all the benefits of both, allowing client code to decide on the option depending on their scenario.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They probably could, but I'm not sure if that is better. The behavior for the two options would differ somewhat, especially around whether the ChatMessageStore / AIContextProvider properties are instantiated or not, meaning users are not just confronted with two options for doing the same thing, these also behave differently.

@markwallace-microsoft markwallace-microsoft added the documentation Improvements or additions to documentation label Jan 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants