Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Jan 27, 2026

Extends the multiple-services.md design document to support advanced client hierarchy customization using nested @client decorators.

Key Design Changes

Default Behavior for Multiple Services

  • Without explicit @client: Each @service namespace becomes its own root client automatically (consistent with single-service behavior)
  • With explicit @client: Users can customize client names or merge multiple services into one client

Key Design Principle (for explicit @client)

  • If the @client namespace is empty: TCGC auto-merges all services' nested namespaces/interfaces into the current client as children
  • If the @client namespace contains nested @client decorators: TCGC uses the explicitly defined client hierarchy instead of auto-merging

Scenarios

Scenario 0: Multiple Services Without Explicit @client (Default Behavior)

Multiple @service namespaces automatically become multiple root clients (e.g., ServiceAClient and ServiceBClient) - NEW: now includes full YAML output and Python SDK example

Scenario 1: Explicit Client Names for Multiple Services

Use @client to customize client names (e.g., MyServiceAClient instead of ServiceAClient)

Scenario 2: Services as Direct Children (No Deep Auto-Merge)

Use nested @client decorators to explicitly define each service as a child client, preventing deep auto-merging

Scenario 3: Fully Customized Client Hierarchy

Use nested @client decorators with explicit operation mapping via is keyword

Documentation Updates

  • Updated client.md to clarify that each @service namespace becomes a separate root client
  • Added full Scenario 0 with YAML output and Python examples for default behavior
  • Added YAML examples with proper children property (matching SdkClientType interface)
  • Added clientInitialization with initializedBy property to all YAML examples following client.md defaults
  • Added Python SDK examples for all scenarios
  • Added apiVersionsMap for multi-service clients (non-breaking change)
  • Added endpoint and credential limitations documentation
  • Expanded Changes Needed section

Design doc only—no code changes included.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI and others added 3 commits January 27, 2026 09:29
… customization

Co-authored-by: tadelesh <1726438+tadelesh@users.noreply.github.com>
Co-authored-by: tadelesh <1726438+tadelesh@users.noreply.github.com>
Co-authored-by: tadelesh <1726438+tadelesh@users.noreply.github.com>
Copilot AI changed the title [WIP] Update client hierarchy design for multiple services support Extend multiple-services design doc with autoMerge option for client hierarchy customization Jan 27, 2026
Copilot AI requested a review from tadelesh January 27, 2026 09:31
Copy link
Member

@tadelesh tadelesh left a comment

Choose a reason for hiding this comment

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

@copilot Refine with my comment. I don't want to add the new autoMerge flag. You need to check the current two design doc and current cache.ts implementation code to see this new design could meet all current cases and the new scenarios.

…stead

Co-authored-by: tadelesh <1726438+tadelesh@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Jan 28, 2026

@copilot Refine with my comment. I don't want to add the new autoMerge flag. You need to check the current two design doc and current cache.ts implementation code to see this new design could meet...

Refactored the design to remove the autoMerge flag. The new approach uses the existing @client decorator pattern where:

  • Empty namespace = auto-merge (first step design behavior)
  • Namespace with nested @client = explicit hierarchy

Also fixed subClientschildren and replaced YAML comments with real methods entries per the interface.ts structure. See commit f20ed7f.

Co-authored-by: tadelesh <1726438+tadelesh@users.noreply.github.com>
Copilot AI requested a review from tadelesh January 28, 2026 08:21
Copy link
Member

@tadelesh tadelesh left a comment

Choose a reason for hiding this comment

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

@copilot Resolve the remaining comments.

…tion to all YAML, remove comparison code

Co-authored-by: tadelesh <1726438+tadelesh@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Jan 28, 2026

@copilot Resolve the remaining comments.

Resolved all remaining comments in commit 83e9199:

  • Added Python SDK example for Scenario 1
  • Added clientInitialization with initializedBy to all YAML examples following client.md defaults
  • Removed the comparison code in Scenario 2
  • Removed the diagnostic warning about unreferenced operations

Copilot AI changed the title Extend multiple-services design doc with autoMerge option for client hierarchy customization Extend multiple-services design doc with nested @client pattern for client hierarchy customization Jan 28, 2026
Copilot AI requested a review from tadelesh January 28, 2026 09:20
Copy link
Member

@tadelesh tadelesh left a comment

Choose a reason for hiding this comment

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

@copilot I also want to make a change for client with multiple services: to make the apiVersions array could be 2-dimension to store all possible API versions for multiple services.

Co-authored-by: tadelesh <1726438+tadelesh@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Jan 28, 2026

@copilot I also want to make a change for client with multiple services: to make the apiVersions array could be 2-dimension to store all possible API versions for multiple services.

Updated apiVersions to be a 2-dimensional array for multi-service clients (e.g., [[av1, av2], [bv1, bv2]]) to store all possible API versions for each service. See commit b837d38.

Copilot AI requested a review from tadelesh January 28, 2026 09:29
@microsoft-github-policy-service microsoft-github-policy-service bot added the lib:tcgc Issues for @azure-tools/typespec-client-generator-core library label Jan 28, 2026
@pkg-pr-new
Copy link

pkg-pr-new bot commented Jan 28, 2026

Open in StackBlitz

npm i https://pkg.pr.new/Azure/typespec-azure/@azure-tools/typespec-client-generator-core@3847

commit: e613f9b

@tadelesh
Copy link
Member

@copilot Format the doc.

Co-authored-by: tadelesh <1726438+tadelesh@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Jan 28, 2026

@copilot Format the doc.

Formatted the doc with prettier. See commit c4d9bce.

kind: client
name: CombineClient
apiVersions: []
apiVersions: [[av1, av2], [bv1, bv2]] # 2-dimensional array for multiple services
Copy link
Member

@weidongxu-microsoft weidongxu-microsoft Jan 29, 2026

Choose a reason for hiding this comment

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

Would it be beneficial to have a more explicit type (or a dict of namespace -> [<versions>]is also better).

A 2-dimensional array is not easy to understand (at least, to me...) -- which direction is for which catalog?

Copy link
Member

Choose a reason for hiding this comment

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

@copilot Change the apiVersions to be a map, the key is a service namespace's full qualified name, the value if the api versions array. Let's make it to be a non-breaking change, add a new property apiVersionMap, keep previous apiVersions property as a 1-dimensinal array and keep it empty for cross service client.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed to use apiVersionsMap (a map of service namespace full qualified name to API versions array) instead of a 2D array. The apiVersions property is kept as an empty array for cross-service clients to maintain backward compatibility. See commit c0517f2.


### Scenario 2: Services as Direct Children (No Deep Auto-Merge)

In the first step design, when combining multiple services with an empty client namespace, all nested namespaces/interfaces from all services are auto-merged into the root client as children. Some users prefer to keep each service's namespace as a direct child of the root client without deep merging.
Copy link
Member

@weidongxu-microsoft weidongxu-microsoft Jan 29, 2026

Choose a reason for hiding this comment

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

Personally, I feel it more natural to behave according to the standard Namespace arrangement. If there is 2 root Namespace, it would be 2 root client.

Or, if we don't want this behavior, we can let TCGC error out, if no explicit client is specified on multiple-service case.

Automatically "merge" the 2 independent Namespace into a single root client, seems not match the single service behavior.
(I think if 2 root Namespace belong to a single service, TCGC will produce 2 root client, right?)

Copy link
Member

Choose a reason for hiding this comment

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

I prefer if there are two root @service namespace, then TCGC auto make them to be two root clients.

Copy link
Member

Choose a reason for hiding this comment

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

@copilot Change previous design in client.tsp of just detect the first @service to be one client. If there are multiple services defined, each @service should be a separate client.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated the design so that multiple @service namespaces without explicit @client will automatically create separate root clients (one per service). Also updated client.md to clarify this behavior. See commit 448799a.

Copy link
Member

Choose a reason for hiding this comment

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

@copilot You need also to add another scenario into multiple-services.md to show this use case.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added "Scenario 0: Multiple Services Without Explicit @client (Default Behavior)" with full TCGC behavior details, YAML output, and Python SDK example. See commit 59382d3.

When TCGC detects multiple services in one client, it will:

1. Create the root client for the combined client. If any service is versioned, the root client's initialization method will have an `apiVersion` parameter with no default value. The `apiVersions` property and the `apiVersion` parameter for the root client will be empty (since multiple services' API versions cannot be combined). The root client's endpoint and credential parameters will be created based on the first sub-service, which means all sub-services must share the same endpoint and credential.
1. Create the root client for the combined client. If any service is versioned, the root client's initialization method will have an `apiVersion` parameter with no default value. The `apiVersions` property for the root client will be a 2-dimensional array to store all possible API versions for each service (e.g., `[[av1, av2], [bv1, bv2]]`). The root client's endpoint and credential parameters will be created based on the first sub-service, which means all sub-services must share the same endpoint and credential.
Copy link
Member

Choose a reason for hiding this comment

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

what if different services use different endpoint and credential, will TCGC report error?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, TCGC will report a diagnostic error if services have different @server or @useAuth definitions. This is documented in the TCGC Behavior section and the "Endpoint and Credential Limitations" sections for Scenarios 2 and 3.

Copy link
Member

@tadelesh tadelesh Jan 30, 2026

Choose a reason for hiding this comment

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

Yes. There will be diagnostics. TCGC does not support mix operations with different endpoint/credential into one client. This is mentioned in the following scenarios.

The key design principle is:

- **If the client namespace is empty**: TCGC auto-merges all services' nested namespaces/interfaces into the current client as children (first step design behavior).
- **If the client namespace contains nested `@client` decorators**: TCGC uses the explicitly defined client hierarchy instead of auto-merging.
Copy link
Member

Choose a reason for hiding this comment

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

Probably this will not happen in ARM, but do we support the mix, e.g. some sub clients could be merged while others has explicitly client hierachy?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The current design doesn't support a mix of merged and explicitly defined sub-clients at the same level. When the namespace has any nested @client decorators, TCGC uses only the explicitly defined hierarchy. To achieve partial merging, you would need to explicitly define all child clients you want.

Copy link
Member

Choose a reason for hiding this comment

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

This is a recursive behavior. For each @client namespace, TCGC will decide the merge behavior based on if there is any nested @client. So, you could mix all kinds of clients as you wish.


@client({
name: "CombineClient",
service: [ServiceA, ServiceB],
Copy link
Member

@lirenhe lirenhe Jan 30, 2026

Choose a reason for hiding this comment

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

What if we define service: [ServiceA, ServiceB, ServiceC],
but in namespace CombineClient, there is only serviceA and serviceB, will serviceC be ignored in client?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If a service is listed in service: [ServiceA, ServiceB, ServiceC] but not used in any nested @client decorator, its operations would be omitted from the SDK. The design doc mentions in Validation Rules: "Operations not referenced by any explicit client are omitted from the SDK."

Copy link
Member

Choose a reason for hiding this comment

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

Yes. If there are explicit nested @client then the service here is not so important.

…ients

Co-authored-by: tadelesh <1726438+tadelesh@users.noreply.github.com>
…nts by default

Co-authored-by: tadelesh <1726438+tadelesh@users.noreply.github.com>
…and Python examples

Co-authored-by: tadelesh <1726438+tadelesh@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lib:tcgc Issues for @azure-tools/typespec-client-generator-core library

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants