2.2 Conditions and routing
简体中文 · Control flow · All examples
Compose six routing patterns using the public Graph, Runtime, INFER and INTERACTION APIs. The application selects a Graph; unselected branches do not execute. Explicit dependencies join independent branches. Importing a module does not load configuration, request a model, or execute business operations.
Examples and commands
| File / function | Behavior | Command |
|---|---|---|
state-routing.ts / runStateRouting | Select extract or count by task type; blocked state takes precedence | npm run example:routing:state-routing |
conditional.ts / runConditional | Validate the model's priority/standard decision and execute one branch, selecting expedited/normal delivery queues | npm run example:routing:conditional |
branch-merge.ts / runBranchMerge | Extract owner and deadline independently, then deliver one validated result | npm run example:routing:branch-merge |
file-type.ts / runFileTask | Original file → selected parser tool → inference → delivery | npm run example:routing:file-type -- --file <path> --media-type <MIME> |
risk.ts / runRisk | Execute, independently verify, request confirmation, or refer to a human | npm run example:routing:risk |
confidence.ts / runConfidence | Return, analyze more evidence, retry, or escalate using an application verifier | npm run example:routing:confidence |
Requires Node.js 24+ and npm 11+. Run npm ci from the repository root. Configure the model, Provider credentials and network allowlist in .env using the configuration API. Commands explicitly load .env and ditto.yaml and call a real HTTP model. shared.ts provides result validation, delivery and CLI initialization for this example group; orchestration remains in the six topic files.
Functions accept a caller-owned Runtime and return { content, samples, receipt }; risk routing also returns toolCalls. Each sample is a NodeResult<SampleOutput> with execution ID, finish reason and token usage. The caller registers Workers and closes the Runtime in finally. See routing API usage for installation and integration.
Input boundaries
runFileType accepts a ParsedFile: extracted PDF text, CSV/XLSX string rows with a header, PNG/JPEG ocrText, or WAV/MP3 transcript. Extensions are case insensitive. Unknown formats, MIME/extension mismatches, empty text and irregular tables fail before inference.
runFileTask accepts an original file { path, name, mediaType }, selects and invokes INTERACTION.ACT.TOOL, then passes actual parsed content to runFileType. PDF, CSV/XLSX, OCR and transcription adapters are provided in the file ingestion tools, with independent dependencies and configuration. Outputs retain source SHA-256 and parser engine for verification.
Risk policy
risk is a finite application-authorized value, never permission generated by a model.
| Range | Route | Action |
|---|---|---|
[0, 25) | execute | Invoke record_pickup |
[25, 50) | verify | Invoke the tool only if verify(value) resolves to exactly true; otherwise pending_human |
[50, 75) | confirm | pending_confirmation; no tool call |
[75, 100] | human | pending_human; no tool call |
The pickup-ledger.ts adapter registers a RegisteredTool and writes to a caller-provided Map. Repeated identical IDs/content are idempotent; conflicting content fails. The Map is not persistent. A production adapter owns authentication, transactions and durable idempotency. Business registration logic does not belong to Core.
pickup-task-store.ts provides a SQLite task queue, durable ledger, review records and file OutputSink. Task acceptance verifies zero pending writes, approval followed by resumeRisk, rejection, changed-payload denial and idempotent resumption. resumeRisk checks a trusted authorize(id, value) callback, and the tool independently checks persisted policy. Test decisions come from an automated acceptance reviewer, not a real human. Ordinary CLI examples still use a console Sink. OUTPUT acceptance does not authorize an action; failed delivery does not undo tool effects.
Confidence policy
assess(value, attempt) may asynchronously return a finite value in [0, 1]. Attempt 0 assesses the initial result; attempt 1 assesses a correction. Use independent evidence or business validation rather than model self-reported confidence. These are application policy thresholds, not accuracy guarantees.
| Initial score | Route | Action |
|---|---|---|
[0.9, 1] | return | Return the result |
[0.7, 0.9) | analyze | Reconcile the candidate with required additional evidence |
[0.4, 0.7) | retry | Re-read the original input independently |
[0, 0.4) | escalate | pending_human |
At most one analysis or retry is allowed. A reassessed score below 0.9 escalates. The final content retains the initial route, final score and business status.
Failures and delivery
Model output must be success / stop / assistant text and pass JSON and field validation. Invalid routes, truncated responses, invalid scores, model failures and tool failures stop subsequent work. Merge requires both branches to be valid; partial output is not delivered. Business failure objects are data to Graph, so the examples check status explicitly. Rejected or unknown delivery receipts throw.
Real-model end-to-end checks
npm run check
npm run check:examples:routing:live
npm run check:examples:routing:package
# Optional configured Provider
npm run check:examples:routing:package -- --provider deepseekThe live suite generates random record IDs and quantities for 24 cases: two task routes plus blocked state, both conditional branches, a join, seven parsed file formats, five risk paths and six confidence paths. Assertions cover actual model output, selected Graphs, call counts, one final delivery, real tool writes, and zero business writes for pending routes. Confidence fixture scores exercise policy thresholds; they do not measure model confidence.
The package command installs an npm tarball into a temporary application, copies the examples and application tools, checks strict TypeScript resolution without paths aliases, and runs the same real-model suite. It requires no package src, copies no credential files and cleans up the temporary application.
Reports are .examples-routing-live-results.json and .examples-routing-package-live-results.json. They record Provider, model, timestamps, per-case expectations/results, Graph paths, execution IDs, token usage, model calls and deliveries. Failures exit nonzero. Offline regressions additionally cover invalid inputs, branch isolation, join ordering, rejected delivery, tool failures, denied permissions, idempotency and bounded correction.
Task-level end-to-end experiments
Install the file tool dependencies, then run:
npm run check:examples:routing:tasks
npm run check:examples:routing:tasks:packageThe 27 cases verify task outcomes beyond successful inference:
- Read disk requests and verify extraction reports, dispatch queues, joined handoff artifacts and blocked-task resumption.
- Generate and process actual PDF/CSV/XLSX/PNG/JPEG/WAV/MP3 files. Parsers receive only paths and MIME; expected answers never enter tool or model input.
- Persist pending risk tasks, approve/resume or reject them, and verify SQLite rows, payload-bound authorization, denied bypasses and idempotency.
- Compute confidence from actual matches against independent evidence files and reassess after correction. Scores represent experimental evidence coverage, not calibrated model probability.
- Reopen delivered JSON and database rows, persist corrupt-file failures without inference or business writes, then close/reopen SQLite to verify durability.
Inputs, evidence, reviews, JSON artifacts and tasks.sqlite remain in .examples-routing-tasks/run-*/. Reports are .examples-routing-tasks-live-results.json and .examples-routing-tasks-package-live-results.json, including tool calls, parser outputs, digests, model executions and task states. Missing dependencies or incorrect artifacts/states fail acceptance.
check:examples:routing:live checks routing contracts; commands containing tasks perform full task acceptance. The SQLite adapter is a local application example: the caller owns business authentication, and the database/JSON outputs are not a distributed scheduler or cross-storage transaction system.
