02 - Explicit subgraph mapping¶
Compare two topics by running the same compiled analysis subgraph
on each, with each call site writing into disjoint parent fields.
This is the canonical use of ExplicitMapping.
Overview¶
You give the pipeline two topics ("Apollo 11" vs "Apollo 17", or
"Apollo program vs Artemis program"). One compiled subgraph
(summarize → score) is registered twice in the outer graph. The
first registration analyzes topic A and writes its results into
a_summary / a_score; the second analyzes topic B and writes
into b_summary / b_score. A final synthesize node reads both
sides and renders a verdict.
Without explicit mapping the two sites would both write to a single
parent.summary field under default name matching, and the second
call would clobber the first.
What it teaches¶
ExplicitMappingfor reusing one compiled subgraph at multiple parent sites with disjoint parent fields. Each site declares its owninputsandoutputsdicts; the same compiled subgraph value is registered twice.- The encapsulation property that makes this work: the subgraph
speaks in neutral field names (
topic,summary,score) and has no idea which side of the comparison it's running for. The mapping at each call site is what wires the subgraph's neutral names to the parent's per-side fields. - The contrast with example 01: there a custom
ProjectionStrategycarried one field in. Here the two sites need to be similar-but-different, andExplicitMappingis the zero-boilerplate way to express that.
How to run¶
uv sync --group examples
LLM_API_KEY=sk-... uv run python examples/02-explicit-subgraph-mapping/main.py "Apollo 11" "Apollo 17"
Or pass a single "X vs Y" arg, or no args (defaults to
"Apollo 11" vs "Apollo 17").
The graph¶
flowchart TD
start([start])
synthesize[synthesize]
stop([end])
subgraph analysis_a [analyze_a: analysis subgraph]
direction TB
sa[summarize]
ra[score]
sa --> ra
end
subgraph analysis_b [analyze_b: analysis subgraph]
direction TB
sb[summarize]
rb[score]
sb --> rb
end
start --> analysis_a --> analysis_b --> synthesize --> stop
Both subgraph boxes are the same compiled value, registered twice
under different names with different mappings. The analyze_a site
maps parent.topic_a → subgraph.topic and back out as summary →
a_summary, score → a_score. The analyze_b site does the same
thing on the B-side parent fields.
Reading the output¶
topic A: Apollo 11
summary: <one-sentence summary of Apollo 11>
score: 8/10
topic B: Apollo 17
summary: <one-sentence summary of Apollo 17>
score: 7/10
verdict:
<paragraph picking a winner or calling it a tie, citing the summaries>
trace: ['summarize', 'score', 'summarize', 'score', 'synthesize']
- The per-side summary and score fields are populated by separate invocations of the same subgraph, routed by the mappings.
traceshows the subgraph's nodes running twice, interleaved with the outersynthesize. Both invocations contribute to the same parenttracelist because eachoutputsmapping includes"trace": "trace".verdictis whateversynthesizeproduced from reading both sides. The outer node knows nothing about which side ran first; it just reads four parent fields.