The Pain: Scene routing solved 90% of single-scene tasks. But what about the remaining 10% — the composite ones? A single status report contains inquiries, quotations, reminders, DNs and PODs. No single scene can hold it.
What You'll Learn:
- Why a report is not a scene but a pipeline container — it orchestrates scenes instead of becoming one
- The five-stage pipeline: aggregate → decompose → dispatch → execute → report
- Why "unrestricted tools" is the container's special case, not a violation of scene routing
- Why scripts do the dirty work and the LLM only does the final assembly
- How report stability went from ~60% to ~95% in our system
1. The Problem: A Report Is Full of "Small Tasks"
After the scene-routing system went live, single-scene task quality improved dramatically. Report generation was the exception.
An in-transit report looks like one simple output task, but it is stuffed with sub-tasks:
- Read every email in the INBOX (the email scene's capability)
- Query the current status of every shipment (the query scene's capability)
- Reconcile receivables and payables (the finance scene's capability)
- Give a judgment on every status line (the decision scene's capability)
What makes it worse: every email inside the report needs its own judgment. Should this shipment be closed? Did a new DN or POD arrive? Does the agent need to be chased? These judgments weave multiple scenes together.
Our first attempt treated the report as a "report scene" — hand it every tool and let it improvise. You can guess the outcome: the LLM bounced between tool domains, output was unstable, it sometimes missed critical emails and sometimes sent duplicate reminders.
💡 Core insight: a report is not a scene — it is a pipeline container. It orchestrates the execution of multiple scenes instead of becoming one itself.
▲ A report is not a scene — it's a pipeline container: five stages, deterministic scripts up front, the LLM assembling at the end.
2. The Core Idea: A Five-Stage Pipeline
Redefine report generation as five stages:
aggregate → decompose → dispatch → execute → report
Stage 1 — Aggregate. Read everything in the reporting period: all emails, data updates, event logs. This stage does not classify, judge, or filter. It only collects.
Stage 2 — Decompose. Split the aggregated material into independent work units — by email, by shipment, by topic. Each work unit carries its raw data, the items awaiting judgment, and the related shipment numbers.
Stage 3 — Dispatch. Route each work unit to the scene handler that owns it. Emails go to the email scene, finance to the finance scene, collections to the collection scene. Every sub-task executes in its own independent context.
Stage 4 — Execute. Each sub-task runs independently and returns a structured sub-result. The email scene outputs "classified + judged", the finance scene outputs "receivables/payables summary", the collection scene outputs "reminder suggestions".
Stage 5 — Report. Assemble every sub-result into one complete report, in a uniform format.
▲ The five-stage container: stages 1–4 are deterministic scripts, stage 5 is the LLM — each stage has clear input, output, and validation.
3. Technical Implementation
3.1 The Container's Special Case: Unrestricted Tools
For the report pipeline, scene routing makes one exception: no tool restriction.
This is not a violation of scene routing — it is the "pipeline container" concept in action. The report pipeline needs email access (email scene tools), database queries (query scene tools), and table generation (report scene tools). Restricting any one category would produce an incomplete report.
But "unrestricted tools" is not "no rules." The report pipeline still obeys every iron rule; the gate system still checks behavioral compliance at critical nodes.
3.2 The Pipeline Code
def generate_report(period):
# stage 1 — aggregate: read everything in the period
all_mails = fetch_inbox(period)
all_events = fetch_events(period)
raw_data = all_mails + all_events
# stage 2 — decompose: split by shipment / topic
work_units = split_into_units(raw_data)
# [{"ticket": "TK001", "mails": [...], "pending": [...]}, ...]
# stage 3 — dispatch: route each unit to a scene
dispatched = {}
for unit in work_units:
scene = classify_unit(unit) # reuse the two-layer classifier
dispatched.setdefault(scene, []).append(unit)
# stage 4 — execute: each scene processes independently
results = {}
for scene, units in dispatched.items():
results[scene] = process_scene(scene, units)
# stage 5 — report: the LLM only does the final assembly
report = llm_assemble(results)
return report
3.3 The Key: Scripts Do the Dirty Work, the LLM Only Assembles
Why do the first four stages use scripts instead of the LLM?
Because dirty work — scanning emails, cleaning data, running statistics — is a poor fit for an LLM: it is slow, expensive, and unstable. Scripts do dirty work fast and exactly; the LLM does the final assembly with a consistent style. Each does what it is best at.
# stage 4 — execute: pure script (no_agent)
def process_scene(scene, units):
if scene == "email":
return classify_and_judge(units) # script logic
elif scene == "finance":
return summarize_finance(units) # script statistics
return None
# stage 5 — report: the LLM
def llm_assemble(results):
prompt = build_prompt(results) # structured data
return llm_call(prompt) # assemble natural language
▲ Composition and fork: work units fan out to email, finance, and collection scenes — each in its own context — then converge into one report.
✅ Verified: after the rework, report stability rose from ~60% to ~95%. Data sources are traceable, judgment rationale is explicit, and output format is uniform.
🩸 Pitfall: our earliest version let the LLM "freely improvise" the whole report — sometimes detailed, sometimes three lines. The turning point was accepting the feedback that letting a big model improvise in a scheduled task is inherently unstable, and switching to the five-stage pipeline.
💼 Value: every stage now has clear input, output, and validation criteria. The LLM's role shifted from "report writer" to "SOP executor."
▸ Cognitive leap: atomic scenes guarantee quality; composite flows get the job done. A scene is atomic, a flow is composite — two abstraction levels at different granularities.
4. Pros and Cons
✅ Pros
- Stable reports — the five-stage SOP guarantees the same flow every time
- Every email is classified and handled — nothing in the period gets missed
- Drafts live in one store — report drafts are traceable and reviewable
- Every conclusion cites its data source — judgments have evidence
- Cross sub-task isolation — one sub-task's error never poisons the others
⚠️ Cons
- Depends on a detailed SOP — when the SOP is thin, the LLM improvises
- Multi-scene auto-decomposition still needs an orchestration framework — today the flow is hand-wired
- The container adds latency — five stages cost roughly 30% more time than a single scene
- Composite-task boundaries are fuzzy — some tasks sit between single-scene and composite
5. The You Right Now
You are no longer the optimist who treated the report as a scene, handed the agent every tool, and let it improvise. You are becoming a system designer who orchestrates complex tasks with flow containers.
A report is not a scene; it is a pipeline container. Scenes are atomic — they handle single-responsibility tasks. Flows are composite — they orchestrate several atomic scenes toward a complex goal.
Next up: the system runs — but how do you know it is reliable? The observability trio — gate + audit + correction sedimentation — the feedback loop that lets a commercial agent keep improving.
About the author: Wu Ji (无记) — AI & digitalization practitioner focused on Agent engineering, Loop Engineering, and digital transformation. Practical, hands-on tutorials — follow along and it just works.



Top comments (0)