
Don't turn live-streaming defects into PRs based on conversation alone: Reproduce the late-arriving-event bug in co-streaming with an Event Capsule
- TencentRTC
- TypeScript
- AI
- Live Streaming
During live operations, a report may say, “We canceled the co-stream, but a few seconds later the display returned to ‘participating.’” Even then, all that remains in the thread is the outcome as seen by a human.
If you hand that straight to an AI agent to implement, it can produce a plausible fix PR, but the following information will be missing.
- Whether the cancellation or the approval notification arrived first
- Whether the media was actually published or only the UI changed
- Whether events from before the reconnection were mixed in
Whether a human’s cancellation action should take precedence over a late-arriving event
This is not so much a problem with AI’s summarization ability as a lack of a “timeline” in the input.
In this article, we convert Interactive Live events into compact reproduction data and connect the entire workflow, from task creation and AI-generated fix candidates to a GitHub PR and human review. Because it does not assume Tencent RTC-specific SDK API names and uses normalized in-app events as the boundary, it can be adapted to the platform you are using.Conclusion: Make the sequence of events before and after the operation—not the thread—the source of truth for the task
- What we are building this time is the Incident Capsule. We will record what happened on the live screen in JSON, along with the following three items:
- Normalized events that preserve arrival order
The expected outcome determined by a human
The development flow is as follows:
- Live screen ↓ Normalize UI actions, RTC notifications, and app state Short-lived ring buffer ↓ The operations staff member selects “Save incident” Incident Capsule ↓ A trusted process registers it in the repository Task + replay test ↓ AI agent changes only the implementation code ↓ Replay the event sequence in CI ↓ A human reviews and merges the PR
- AI can improve the part where it identifies the race condition in the event sequence and proposes a fix. The following judgments, however, will not be delegated to AI.
Whether cancellation or approval should take precedence
Which UI state should be called “co-streaming”
- Whether human actions may be overridden in production
Prerequisite: First check the built-in approach for Interactive Live
With Tencent RTC Live Streaming, you can choose to use a prebuilt UI or headless AtomicXCore integration for more granular assembly. The official setup guide is as follows.
The full range of features supported by Interactive Live, such as viewing, chat, co-hosting, and viewer management, can be found in the following official documentation.
The selection criteria for this task are simple.
| Condition | Approach |
|---|---|
| Use a prebuilt live UI as the foundation | Record operational actions and required notifications outside TUILiveKit |
| When there is a custom co-hosting UI or many state transitions | Consider an architecture that uses AtomicXCore and explicitly define a normalization layer |
| If the goal is initially to improve only the reproducibility of bug reports | Introduce it through a recording adapter without changing the built-in approach |
Terms such as cohost.accepted are not Tencent RTC API names, but normalized events internal to the app. The actual SDK callback names are mapped in the adapter according to the official documentation for the target platform.
Step 1: Create a minimal project
This assumes Node.js 20 or later.
Add the test commands to package.json.
Step 2: Normalize live events
Create src/events.ts.
operationId is the unit of a joint distribution request, and roomSessionId identifies a single room-entry/reconnection interval. Processing by user ID alone makes it impossible to distinguish repeated requests from the same participant or notifications from before a reconnection.
Also, seq is used for playback order instead of receivedAtMs. This is because sorting by device time or server time would hide the actual arrival order.
Step 3: Implement a ring buffer that stores data from before and after operations
Create src/recorder.ts.
The maximum number of events is an app-side setting. It is not a Tencent RTC limit or performance value. In actual operation, determine it by measuring the device's memory, the number of events generated, and the investigation time required.
SDK integration point
Notifications and UI operations on the Tencent RTC side must not be stored as-is. Differences between platforms are absorbed by an adapter.
The example pseudonymize is not sufficient for anonymization. Here, it only demonstrates the boundary rule: "Do not put raw participant IDs directly into events."
Step 4: Create an oracle that replays the event sequence
The expected behavior in this case is as follows:
After a human cancels a given operationId, a late approval notification for that operation alone must not cause the human to return to co-hosting.
Create src/replay.ts.
Here, "approved" and "media has been released" are distinguished. If the UI is marked as streaming based solely on the co-streaming approval notification, it cannot represent cases where the media has not yet been released or where cancellations race with each other.
Step 5: Lock in the failing fixture
Create test/late-accept.test.ts.
This test does not assume that the problematic event never arrived. After observing the late-arriving event, it verifies that the state of the cancelled operation does not advance.
In the actual app code, the same check as reduceEvent is applied before updating the UI state. Rather than ignoring SDK notifications, it determines whether they can be reflected in the app state using roomSessionId and operationId.
Boundaries from the task through the AI agent to the PR
Merely pasting the Incident Capsule into the AI prompt is not sufficient. If the AI is also allowed to modify tests or expected results, this becomes self-grading rather than a fix.
The recommended order is as follows:
- The operations staff save the incident
- A trusted bot or operator registers the Capsule in incidents/
- A human reviews expected.description
- First, merge the Capsule and the reproduction test into the base branch
- Create a branch for the AI agent from that commit
- The AI modifies only the implementation in src/
- Use CI to verify the protected target and the replay results
- A human reviews the diff and the behavior on the actual device
The information passed to the task is also separated.
Instructions for the AI should specify the prohibited modification areas more clearly than the implementation approach.
Reject changes to evidence files in CI
The branch for AI is assumed to be created from the base commit after Capsule registration.
Hashes can be used to detect accidental corruption, but they do not independently guarantee protection against tampering. Because files and hashes can be rewritten at the same time, use them in combination with branch protection, CODEOWNERS, and CI path checks.
Decision Table for the Scope of AI Delegation
| Task | Delegate to AI | Final decision |
|---|---|---|
| Summarizing the event sequence | Allowed | A person cross-checks it against the source data |
| Searching for Reducer branches that are likely to conflict | Allowed | A person determines where to adopt them |
| Creating implementation patches | Allowed | CI and review required |
| Determining expected outcomes | Not allowed | Operations/product owner |
| Rewriting the Incident Capsule | Not allowed | Only through a trusted registration path |
| Disabling joint delivery in the production live environment | Not allowed | Maintain a human-operable path |
| Merging PRs | Not possible | Have a person check the diff and behavior on an actual device |
AI is well suited for creating candidates from observed events. However, the product judgment that “it is more natural to prioritize approval even after cancellation” cannot be derived from code-generation capabilities.
Verification method
1. Automated testing
At a minimum, add the following cases as fixtures.
- requested → cancelled → accepted → ui.active
- requested → accepted → media.published → ui.active
- The same accepted event arrives more than once
- An operationId from before the reconnection arrives after the reconnection
- A cancellation for a different operationId is mixed in
- ui.active is recorded before media.published
2. Disrupt the operation order on two or more devices
Intentionally try the following operations, not just the happy path.
- Initiate a joint-streaming request on the broadcaster’s side
- Cancel on the operator’s side immediately before or after the other party performs the approval operation
- Switch networks, or resume the app from the background
- Check the UI display and the actual media publication status separately
- Check whether the seq of the saved Capsule preserves the observation order
A specific latency in seconds is not used as a pass condition because it varies with device and network conditions. The first thing to verify is that an operation canceled by a human never comes back to life, regardless of the order.
3. PR review
- The branch is created from the commit after Capsule registration
- incidents/ and the oracle have not been modified
- SDK notification names do not leak throughout the app and are normalized by the adapter
- Both roomSessionId and operationId are checked
- The UI’s active indication does not appear before media publication
- A human cancellation operation can be re-executed
- A person has checked the event sequence, not just the AI-generated explanation
Notes
Do not continuously store chat content or audio
If what is needed for reproduction is the state transition, it is safer not to mix message content, audio, gift details, and the like into the Incident Capsule. Limit it to the minimum necessary event types, pseudonymized actors, and operation IDs.
For a different type of investigation that requires message content, separately design the consent, retention period, access permissions, and deletion procedure.
Do not assume that network degradation is the cause
Even if the issue occurs before or after a period of poor network connectivity, that alone does not make it the cause. Record network status as a diagnostic event, separately from the pass/fail criteria for state transitions.
Do not infer TUILiveKit's internal state
Even when using the prebuilt UI, avoid creating tests that infer the internal state from its appearance. Normalize the public notifications, moderation operations, and media states that the app can observe. If deeper control is required, reconsider the embedding approach itself based on the official setup guide.
Even if the AI's PR passes, the production go/no-go decision remains
A replay test guarantees the app's decision-making for the recorded event sequence. It does not guarantee unobserved SDK behavior, the OS lifecycle, or the display on another device. Even after CI passes, verify on an actual device that the human cancellation flow works.
Summary
When turning a live-streaming bug from a thread into a task, simply summarizing the conversation cleanly will lose the timeline.
If you first pin down the event sequence and expected outcomes as an Incident Capsule, the AI agent can propose implementation candidates but cannot arbitrarily change the observed facts or pass/fail criteria. What matters is not whether AI is used, but maintaining the following boundary.
- Normalize Tencent RTC notifications into app events
- Preserve the arrival order and operation granularity
- A human determines the expected outcome
- Register the evidence before creating an AI branch
- Allow only the implementation code to be changed in the PR
- Finally, verify the human interaction flow on an actual device
This enables a transition from a state where "the report is plausible but cannot be reproduced" to a development workflow in which the same event sequence can be replayed any number of times.
Relationship disclosure: The author wrote this article from the standpoint of introducing Tencent RTC technical information and used the official Tencent RTC documentation as an implementation reference.
Go to list of users who liked
Go to list of comments
Register as a new user and use Qiita more conveniently
- You get articles that match your needs
- You can efficiently read back useful information
- You can use dark theme