Repository navigation
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Shadow requests let a team try a candidate variation on real traffic without serving it and compare it on the normal AI metrics. This replaces the closed #241, which shipped it as experimental behind a new core invocation hook. We are not shipping new features as experimental, and a judges-style core design is easier to read.
Summary
Adds a core
shadows.pymodule thatconfig().invoke()and.stream()call directly, the same way they call judges.config()evaluates once withvariation_detail, picks the shadows for the matched rule or fallthrough, and runs the sampled ones in the background withshadow_timeout_s(default 30).skip_shadows=Truereturns them as picklableShadowTasks forrun_shadow(task, handlers). Shadow events reuse A'srunIdand addisShadow,primaryVariationKey,shadowRequestId,ownerKindandownerId.shutdown()cancels running shadows.Testing approaches
Feature flags
N/A
Note
Overview
Adds shadow requests to
config().invoke()and.stream(): after the primary variation is chosen, the SDK can run other pinned variations on the same input in the background, emit normal$ld:ai:*metrics withisShadow: true, and never change the caller’s response, latency, or primary events.Evaluation and wiring.
extract_variation(..., with_reason=True)usesvariation_detailwhen available so shadows attach to the matched rule or fallthrough slot fromshadowConfiguration. Primary and shadow runs share onerunId.execute_and_track/ streaming gain optionalrun_id,extra_track_data, and handlerspan_attributes(via__ld_span) for shadow OTel tags.API surface.
config()addsskip_shadowsandshadow_timeout_s(default 30s). Withskip_shadows=True, responses expose picklableShadowTasklists (invoke) or on the streamdoneevent; workers run them withrun_shadow, mirroring deferred judges. New typesShadowTask/ShadowResultare exported; README and the API report are updated.shutdown()cancels in-flight shadow tasks.Shadow execution rules. Sampled shadows use a stripped config (no tools, judges, or nested shadow config), no tool calls, timeout-wrapped handlers, and errors/timeouts recorded on
ShadowResultwithout affecting the primary path. Extensivetest_shadows.pyplus test mocks that dropvariation_detailwhen simulating older clients.Reviewed by Cursor Bugbot for commit 378a915. Bugbot is set up for automated code reviews on this repo. Configure here.