Behind the Scenes of Sitecore Stream: Decompiling DLLs to Discover API Calls


Today, I am going to explain how the Sitecore Stream works under the hood by decompiling the DLL and finding the APIs responsible for performing the necessary actions.

What is Sitecore Stream?

Sitecore Stream brings AI capabilities to Sitecore products, changing the way marketers create and manage content. Built on Microsoft Azure OpenAI Service, it uses advanced large language models (LLMs) to help teams ideate, craft, and refine on-brand content quickly and securely. Stream simplifies everyday marketing tasks like content creation, campaign development, and message personalization. It supports work across multiple brands and complex campaigns while keeping teams organized and on schedule. With an AI-first approach, it captures your brand’s voice and enhances daily workflows, helping marketing teams boost efficiency, improve collaboration, and deliver consistent, high-quality customer experiences across all channels.

Even though Sitecore Stream's surface-level documentation provides a broad understanding of its features and capabilities but there is a lot more happening beneath the surface. Interested in knowing about how Sitecore Stream really connects to its backend services, I went ahead and dug deeper to analyze the same. On decompiling and analyzing the most important DLL, I was able to discover how it interacts with internal APIs and handles data streaming behind the scenes.

Note: This blog post is for educational and informational purposes only. Always be cautious about the software licensing agreements when decompiling any proprietary code.

Troubleshooting Setup


The first step that I followed to understand the working of Sitecore Stream was gaining a comprehensive understanding of the Sitecore Stream Module package that we installed to set up and configure Sitecore Stream. I carried out a multi-step analysis involving both static and dynamic inspection techniques. I began by extracting the contents of the package to identify exactly which files it installs. The main files included are the "Sitecore.AiClient.dll" and its corresponding configuration files, that is "Sitecore.AiClient.config", and other supporting resources critical to its functionality. However, simply listing the installed files was not sufficient. To delve deeper, I decompiled the DLL using a .NET decompiler, which enabled me to explore the internal logic of the package, including its class structures, methods, and API interactions.

To explore Sitecore Stream’s internals, I used the following tools:
1. dnSpy - It is used for decompiling and debugging the .NET assemblies.
2. JetBrains dotPeek - It is an alternative viewer to cross-check code structures.
3. Postman - It is used for replicating and testing the discovered API calls.

Following the decompilation, I thoroughly examined the codebase to identify the key functionalities and map out the overall flow of operations. I paid close attention to how configuration values were used and how they influenced the application’s runtime behavior. To validate my findings and observe the package in action, I proceeded to debug the application. By setting breakpoints and stepping through the execution process, I was able to track the API calls being made in real time.

Discover the API Usage


Note: The Version of the DLL that I decompiled and debugged is 1.1.63.

Key Methods that drive API communication are listed below.

1. CreateVariantRecommendations method is located in the File: VariantsRecommendationsRequests.cs. This is the core method responsible for sending the recommendation (query) requests to Sitecore Stream API.

public CreateVariantsRecommendationsResponse CreateVariantRecommendations(CreateVariantsRecommendationsRequest createInvitationModel, string accessToken)
{
          ……….
}

What does this method do:
1. Build the API endpoint URL dynamically.
2. Serializes the request model into JSON.
3. Send a POST request via HttpService.
4. Handles and parses the API response.
5. Log or surface any errors encountered during the process.

This method is the business layer entry point into the module’s interaction with Sitecore Stream’s system.

2. GetHttpWebRequest method is located in the File: HttpService.cs.

public virtual HttpWebRequest GetHttpWebRequest(string requestUri, string requestHttpMethod, string requestAuthorizationBearerToken, [Nullable(2)] string requestBodyString = null, int requestTimeout = 300000)
{
          ……….
}

What does this method do:
1. Prepares an HTTP request by adding headers, setting the method (GET, POST), timeouts, and content type.
2. Injects the Bearer token for authorization.
3. Writes the JSON body (if present) to the request stream.

This method abstracts the complexities of setting up a secure HTTP call.

3. GetHttpWebResponse method is located in the File: HttpService.cs.

public virtual ValueTuple<string, int, string, string> GetHttpWebResponse(HttpWebRequest request)
{
          ……….
}

What does this method do:
1. Executes the prepared HTTP request.
2. Reads and returns the response data stream.
3. Catches WebException and captures response errors when the requests fail.

It's a helper that ensures every request gets a readable response or a descriptive failure.

4. EnsureSuccessStatusCode method is located in the File: HttpService.cs.

public bool EnsureSuccessStatusCode(int statusCode, string responseExceptionString)
{
          ……….
}

What does this method do:
1. Checks if the HTTP status is in the success range (2xx).
2. Throws a custom exception when an error status is received.

This method ensures that all failures are caught early and don't silently fail in the background.

5. CreateRequestModel method located in the File: VariantsRecommendationsRequests.cs

private static CreateVariantsRecommendationsRequest CreateRequestModel(string prompt, string fieldName, string variantFieldValue, string brandkitId, string brandkitReferencePath)
{
          ……….
}
private static CreateVariantsRecommendationsRequest CreateRequestModel(PredefinedPrompt predefinedPrompt, string fieldName, string variantFieldValue, string brandkitId, string brandkitReferencePath)
{
          ……….
}

What does this method do:
This method constructs and returns a fully populated instance of CreateVariantsRecommendationsRequest, which serves as the payload for making a variant recommendation API call to Sitecore Stream.

6. CreateRequestUri method located in the File: HttpService.cs.

public string CreateRequestUri(string baseUri, string relativePath, [Nullable(new byte[] { 2, 0, 1, 1 })] IEnumerable<KeyValuePair<string, string>> requestQueryStrings = null)
{
          ……….
}

What does this method do:
1. Combines base and relative paths into a full API endpoint.
2. Appends query parameters as needed.

Key Findings


1. AiClient.skin.xml - It defines how the custom editor fields appear inside the Content Editor. It is responsible for:
A. Custom buttons with Sitecore Stream icons added next to fields like Single-Line Text, Multi-Line Text, and Rich Text.
B.JavaScript logic “createAiClientContentButtonBlock” that hooks into the rendering of these fields and inserts custom buttons that open dialogs using Sitecore events, i.e., “aiclient:aiclientdialog(...)”.

2. AiClient Commands.js - This script registers a new command “AiClient” in the Rich Text Editor (RTE) toolbar. It is responsible for:
A. Launching a custom dialog via editor.showExternalDialog(...).
B. Use scAiClientCallback to inject the result of the dialog (i.e., generated text from Sitecore Stream) back into the RTE.

3. AiClient.css - It is responsible for styling the entire UI inside the Stream dialog. It is responsible for:
A. Button layout, i.e., top bar actions like “Improve Writing” or “Change Tone”.
B. Input box styling for prompts.
C. Spinner overlay for API processing.

4. AiClient.js - This is the main client-side logic used inside the Stream dialog. It is responsible for:
A. Loading original content from the editor or field.
B. Inserting generated content back into the field.
C. Toggling buttons based on input states.
D. Managing tone dropdowns and triggering API-related events using the GenerateClick method.

5. AiClientDialog.xml - It defines the UI layout of the AI client dialog using Sitecore’s FormDialog. It is responsible for:
A. A top bar with action buttons (Improve, Fix Spelling, Make Shorter, etc.)
B. A middle prompt entry section with a Generate button.
C. A bottom area that displays original content on the left and AI-generated variants on the right.
D. Spinner overlay for async processing.

6. Sitecore.AiClient.config - It stores the configuration required by the Stream for integration with Sitecore. It is responsible for:
A. Registering API base URLs and timeout settings.
B. Injecting JavaScript into the RTE.
C. Replacing the default Content Editor skin.
D. Registering custom commands and processors for AI actions.

Conclusion

Decompiling Sitecore Stream’s assemblies offered valuable insight into its API-driven architecture and how it manages the connection between Sitecore and Sitecore Stream. While Sitecore provides powerful features out of the box, sometimes peeking inside the box reveals even more possibilities. I hope this breakdown helps others who are also curious about what powers Sitecore Stream.

References

Chirag Goel

I am a developer, likes to work on different future technologies.

Post a Comment (0)
Previous Post Next Post