Skip to content

Conversation

@ibrahimsel
Copy link

@ibrahimsel ibrahimsel commented Jan 13, 2026

As mentioned in #824:

This PR aims to promote the existing Python SDK under sdks/python-sdk from a proof-of-concept to a structured, maintainable, and supported SDK.

Summary of changes

This PR introduces the following improvements:

  • Converts the SDK to a proper Python package with a pyproject.toml, explicit dependency definitions, and reproducible builds.

  • Establishes a clear SDK structure with separated concerns for:

    • Core client logic
    • Typed models
    • Provider and extension interfaces
    • Adds basic test coverage to validate core functionality
    • Includes minimal but functional examples to demonstrate intended usage
    • Improves documentation to clarify installation, usage, and extension points

Non-goals

This PR intentionally does not attempt to:

  • Implement every possible Symphony API or feature.
  • Lock the SDK API surface as final or frozen.
  • Optimize for advanced performance or edge cases.

Those concerns are deferred until the SDK is adopted and exercised by users.

Potential Follow-ups

  • Expanding API coverage as Symphony APIs stabilize.
  • Strengthening test coverage and possibly CI integration.
  • Publishing versioned releases and formal support guarantees.
  • Fix ruff and mypy warnings/errors

Notes For Reviewers

  • I intentionally did not add any license to the sdk's root or to pyproject.toml as I couldn't quite choose if we use EPL 2.0 or MIT for Eclipse Symphony. (You'll see license headers in source code, I didn't remove them since they're coming from Muto Agent's repository). If someone enlightens me of the license requirements, I could update accordingly
  • I did not touch the existing POC python-sdk. It is still there
  • You could manually try the SDK quickly before merge by following the guidelines in Examples
  • Unit test coverage is currently 76%
Screenshot from 2026-01-13 17-05-02
  • After the SDK is good to merge, please publish it to PyPI. We need this SDK in Muto Agent. Since the package is not published yet, we're currently keeping a tiny version of this SDK in Muto Agent's repo. If PyPI package gets published, we'll migrate to that. @Haishi2016

- FEATURES.md to outline all available features of the SDK, including client features, authentication, target management, solution management, and more.
- GLOSSARY.md to define key terms and concepts used within the SDK, enhancing understanding for new users.
- QUICKSTART.md to provide a step-by-step guide for installation and basic usage, including examples for connecting to Symphony, working with targets, deploying solutions, and tracking deployment status.
- Introduced `models.py` containing data structures for Symphony SDK, including specifications for instances, components, and errors.
- Added `summary.py` to provide Python translations of Symphony API summary models, including result specifications and summary generation.
- Created `types.py` to define essential types and states used in the Symphony COA API, including error handling and constants.
…etter

- Initialized examples/README.md with detailed descriptions of new examples and usage instructions.
Copy link
Contributor

@Haishi2016 Haishi2016 left a comment

Choose a reason for hiding this comment

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

Great PR. Some comments are added.


return self._handle_response(response)

def list_targets(self) -> List[Dict[str, Any]]:
Copy link
Contributor

Choose a reason for hiding this comment

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

This is a common pattern in multiple methods: _handle_reuquest() returns Dict[str, Any] while this method returns List[Dict[str,Any]]. Also, should methods like this use types defined in models.py like TargetState?

Copy link
Author

Choose a reason for hiding this comment

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

This is a common pattern in multiple methods: _handle_reuquest() returns Dict[str, Any] while this method returns List[Dict[str,Any]]

The response type varies between api calls (yes, all JSON but some returns a list, some returns a dict, some returns a list of dicts etc.), so I remember I had trouble determining the return type of a generic method like handle_response that parses a Response object and tries to return a pure python type. Perhaps my approach to this was flawed but I don't know any better 😁

Also, should methods like this use types defined in models.py like TargetState?

In the current state of the software, methods like this return pure python objects. They don't mess with Symphony object models. My initial thought while developing this was: "constructing models should be the sdk user's job". But if you think otherwise, let me know and I could arrange every corresponding method to return Symphony models instead of the Response JSON (e.g. list_targets would return a list of TargetSpec)

Copy link
Contributor

Choose a reason for hiding this comment

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

I see. We can keep the current approach as it is. Or, if we want to make it a bit more clearer, maybe use Any? def _handle_response(...) -> Any. Or, have a JSONType: JSONType = Union[Dict[str, Any], List[Dict[str, Any]]]
def _handle_response(...) -> JSONType. And because the method may return None, make it Optional[JsonType]? It's your call.

Copy link
Author

Choose a reason for hiding this comment

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

Or, have a JSONType: JSONType = Union[Dict[str, Any], List[Dict[str, Any]]]
def _handle_response(...) -> JSONType. And because the method may return None, make it Optional[JsonType]?

I'll try this soon

Copy link
Author

@ibrahimsel ibrahimsel Jan 15, 2026

Choose a reason for hiding this comment

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

implemented your suggestion for handle_response in 90a9cc5

Left the return types of list_* methods as is. Because callers would need to narrow the type before using it as a list, which would be unnecessary friction in my opinion

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.

2 participants